Wednesday, September 20, 2017

Nice To Hear

So I've been tossing some sample problems at my AP students in preparation for the HS Programming Contest at Kansas State University later this fall. If I'm not busy with something else, I'm working on solving it myself for my own practice.

For the one from a couple days ago, I only had time to start the skeleton of the idea and didn't finish it to the full requirements of the problem. I showed them what I wrote this morning, as most of them were still battling the overall structure to approach the problem.

It was really nice, even as the teacher, to hear one of my students (and one of the best coders in the class) look at what I wrote and say, "That is beautiful code, man."

Here is what I wrote, feel free to shred me if you catch anything. Ultimately the problem included taking three entries, comparing them, and then giving output on which entry was the largest and whether it was a "t", "s", or "r".

def main():
    print('Enter object types as t for triangle, r for rectangle, and s for sqaure.')
    print('Enter numbers only for dimension values.')
    print()
    firstObjectType = input('Enter type of first object: ')
    if firstObjectType == 't':
        h = int(input('Enter height of triangle: '))
        b = int(input('Enter base of triangle: '))
        object1 = triangleCalc(b, h)
        print(object1)
   
def triangleCalc(base, height):
    tArea = 0.5 * base * height
    return tArea
   
def squareCalc(sideLength):
    sArea = sideLength * sideLength
    return sArea
   
def rectangleCalc(length, width):
    rArea = length * width
    return rArea

9 comments:

  1. Just to be geeky I would put the input statements for each object in the Calc function for each object. All the main() should do is point to other functions.

    Change "enter numbers only" to "enter integers only" since you are using the int function for your dimensions.

    ReplyDelete
    Replies
    1. I wouldn't add the input to the calc functions but that's because I personally lean towards a functional style -- minimize side effects, functions take input and return output. I might make another function for the io but that's probably overkill for this.

      Delete
  2. Nice - love it that your students are thinking about this.

    A couple of things I noticed - the first is really a statement about me being a dinosaur and isn't about your code at all. It bothered me that you have main on top and the other functions below.

    I've heard people say "put main on top functions below and then call main on the bottom" but I always define my main routine below. I said it's because I'm a dinosaur. Back in the day using languages like Pascal, you HAD to do this and in languages like C if you didn't do this you had to have a bunch of "forward references" so it was just easier to put the called functions on top and the main or caller below.

    Nothing wrong with what you wrote but it's funny how it really bothers me :-)

    The only legit thing I'd say - particularly if your kids are preparing for a competition where they will work collaboratively with each others code is to name functions as more descriptive verbs so instead of squareCalc which doesn't actually tell me what is being calculated, I might name it CalcAreaSquare or SquareAreaCalc. Not important at all for something so short but if the kids are working with each others code under time pressure you want to minimize any chance for misinterpretation.

    ReplyDelete
    Replies
    1. I like main on the top. I'm older than you but perhaps I have more experience with languages that don't required you to declare functions before you call them. But who knows really. I am old after all. :-)

      Delete
  3. Chuckle. Is that what we are "dinosaurs"? Mike is probably right on the input business. I just hate big chunks of stuff in an "if" statement. Back to that dinosaur thing.

    ReplyDelete
  4. Thanks for the comments, Mike and Garth. Part of "sticking my neck out" I can see now includes being willing to put my code out for public viewing. I do see the logic of putting the call for main at the bottom even if it isn't necessary. And I was naming stuff pretty fast and I'm surprised I didn't just use s, t, and r more. But I do talk constantly with my students about naming things very descriptively.

    So, Garth, would the change based on your comment be to call another function from the if statement?

    ReplyDelete
    Replies
    1. For this program it is not a big deal. Mike is a function guy, functions do one thing and that is all. The functions would contain the one line of math in this instance. I learned with procedures. I package all the triangle stuff in one procedure and so on. It is a style thing, not a law. At the high school level I just hope for something that is organized and consistent. You have to understand, like 90% of the CS teachers in the US, I learned my programming from books and blogs and having to teach it. My style can be crude and "improper" but it makes sense to the kids and is teachable. I also teach a lot of small programs where the function concept does not necessarily make the code easier to understand while the procedures do.

      My solution or what I would teach would be more like this. Is it the right way to do it? Nope, just the way I like to do it.

      def getObjectType():
      print('Enter object types as t for triangle, r for rectangle, and s for sqaure.')
      print('Enter numbers only for dimension values.')
      print()
      objectType = input('Enter type of object: ')
      return objectType

      def computerObjectArea(objectType):
      if objectType == 't':
      areaTriangle = triangleAreaCalc()
      print(areaTriangle)
      elif objectType == 'r':
      areaRectangle = rectangleAreaCalc()
      print(areaRectangle)
      elif objectType == 's':
      areaSquare = squareAreaCalc()
      print(areaSquare)
      else:
      print("This is not a letter I recognize")

      def triangleAreaCalc():
      height = int(input('Enter height of triangle: '))
      base = int(input('Enter base of triangle: '))
      tArea = 0.5 * base * height
      return tArea

      def rectangleAreaCalc():
      height = int(input('Enter height of rectangle: '))
      width = int(input('Enter width of rectangle: '))
      rArea = height * width
      return rArea

      def squareAreaCalc():
      sideLength = int(input('Enter side length of the square: '))
      sArea = sideLength * sideLength
      return sArea

      def main():
      objectType = getObjectType()
      computerObjectArea(objectType)

      main()

      Delete
    2. Just for overkill you could do something like the following (although the fact that squareArea only takes one parameter kills the deal) :-)

      def triangleCalc(base, height):
      tArea = 0.5 * base * height
      return tArea

      def squareCalc(sideLength):
      sArea = sideLength * sideLength
      return sArea

      def rectangleCalc(length, width):
      rArea = length * width
      return rArea


      dispatchtable = {
      't' : triangleCalc,
      'r' : rectangleCalc
      }

      def main():
      print('Enter object types as t for triangle, r for rectangle, and s for sqaure.')
      print('Enter numbers only for dimension values.')
      print()
      firstObjectType = input('Enter type of first object: ')
      h = int(input('Enter height of triangle: '))
      b = int(input('Enter base of triangle: '))
      area = dispatchtable[firstObjectType](h,b)
      print(area)

      Delete
    3. I'm a function guy myself. I started out as a procedure person but time spent on large projects with lots of people working on the same project made me think more in terms of functions. Reusable and sharable code really means that I/O operations should be separate from functions that do other sorts of work. IMHO of course.

      Delete