A “Re-Worked” Number Guesser

In a previous project, my Computer Science 1 students were assigned the task of creating a “number guesser” in Python that could “guess” the number selected by the user based upon the user answering if the guess was too high or too low. To accomplish this task, we created a program similar to the following:

#Programmer Name: Eric Evans
#Program Name: Number Guesser
#Program Description: A program that will "guess" the number selected by the user that is between 1 and 100 using a series of questions.
runAgain = "Y"
high = 100
low = 1
guess = (high + low) / 2
#guess = random.randint(low, high)
while (runAgain =="Y"):
  correct = "N"
  guessCount = 1
  print("Let's play a guessing game")
  print("Pick a whole number between 1 and 100")
  print("You have to tell me if I get it correct or if I'm too high or too low.")
  print("Let's get started.")
  print("")
  while (correct == "N"):
    guess = int(guess)
    guessAsString = str(guess)
    print("Is Your Number " + guessAsString + "?")
    response = input("[C]orrect / [L]ow / [H]igh")
    response = response.upper()
    if (response == "C"):
      guessCountAsString = str(guessCount)
      print("Yay! I got it in " + guessCountAsString + " guesses!")
      correct = "Y"
    elif (response == "L"):
      print("Too Low Huh?")
      low = guess + 1
      guess = (high + low) / 2
      guessCount = guessCount + 1
    elif (response == "H"):
      print("Too High Huh?")
      high = guess - 1
      guess = (high + low) / 2
      guessCount = guessCount + 1
  print("Would You Like to Run the Program Again?")
  runAgain = input("[Y]es or [N]o")
  runAgain = runAgain.upper()
print("Thank you for playing.")
print("Exiting Program - Goodbye")

Now, for the second version of this program, the roles will be flipped. The computer will now be selecting a whole number between 1 and 100 and the user will be attempting to guess the number.

Here is an basic example of what a possible solution could look like:

#Programmer Name: Eric Evans
#Program Name: Number Guesser - Take 2
#Program Description: A program that will select a random number and have the user attempt to guess the chosen number.
import random
#Imports the random library to allow for random number generation
runAgain = "Y"
#Declares and initializes the variable runAgain with a value of "Y" 
high = 100
#Declares and initializes the variable high with a value of "100"
low = 1
#Declares and initializes the variable low with a value of "1"
while (runAgain =="Y"):
#Starts a while loop to allow the program to run again.
  computerNumber = random.randint(low, high)
  #Declares and initializes the variable computerNumber with a randomly selected integer between the value of the variables high and low.
  correct = "N"
  #Declares and initializes the variable correct with a value of "N"
  guessCount = 1
  #Declares and initializes the variable guessCount with a value of "1"
  print("Let's play a guessing game")
  #Outputs information to the screen for the user
  print("I am going to pick a whole number between 1 and 100")
  #Outputs information to the screen for the user
  print("After each guess, I will tell you if you are correct or if you're too high or too low.")
  #Outputs information to the screen for the user
  print("Let's get started.")
  #Outputs information to the screen for the user
  print("")
  #Visually breaks-up the information on the screen for the user
  while (correct == "N"):
    #Starts a nested while loop to allow the user to make more guesses until the variable correct is equal to "Y"
    guess = input("What Is Your Guess? ")
    #Declares and initializes variable guess with the value entered by the user from the keyboard
    guess = int(guess)
    #Casts the variable guess as an integer
    if (guess == computerNumber):
    #Starts a conditional if statement to address when the user guesses the correct number
      guessCountAsString = str(guessCount)
      #Declares and initializes variable guessCountAsString with the value of the variable guessCount cast as a string
      print("Wow! You guessed my number in " + guessCountAsString + " guesses!")
      #Outputs information to the screen for the user
      correct = "Y" #Sets the value of the variable correct to "Y" to exit the inner while loop
    elif (guess < computerNumber and (abs(computerNumber - guess) > (int(computerNumber * .15)))):
    #Starts a conditional else/if statement to address when the user guesses a number that is less than the number selected by the computer and is more than 15% of the value of the computerNumber away
      guessAsString = str(guess)
      #Declares and initializes variable guessAsString with the value of the variable guess cast as a string
      print("Your guess of "+ guessAsString + " is too low.")
      #Outputs information to the screen for the user
      print("Please try again.")
      #Outputs information to the screen for the user
      print("")
      #Visually break-up the information on the screen for the user between their guesses
      guessCount = guessCount + 1
      #Increments the value of the guessCount variable by 1
    elif (guess < computerNumber and (abs(computerNumber - guess) <= (int(computerNumber * .15)))):
    #Starts a conditional else/if statement to address when the user guesses a number that is less than the number selected by the computer and is less than or equal to 15% of the value of the computerNumber away
      guessAsString = str(guess)
      #Declares and initializes variable guessAsString with the value of the variable guess cast as a string
      print("Your guess of "+ guessAsString + " is too low.")
      #Outputs information to the screen for the user
      print("You are very close!!!")
      #Outputs information to the screen for the user
      print("Please try again.")
      #Outputs information to the screen for the user
      print("")
      #Visually break-up the information on the screen for the user between their guesses
      guessCount = guessCount + 1
      #Increments the value of the guessCount variable by 1
    elif (guess > computerNumber and (abs(computerNumber - guess) > (int(computerNumber * .15)))):
    #Starts a conditional else/if statement to address when the user guesses a number that is greater than the number selected by the computer and is more than 15% of the value of the computerNumber away
      guessAsString = str(guess)
      #Declares and initializes variable guessAsString with the value of the variable guess cast as a string
      print("Your guess of "+ guessAsString + " is too high.")
      #Outputs information to the screen for the user
      print("Please try again.")
      #Outputs information to the screen for the user
      print("")
      #Visually break-up the information on the screen for the user between their guesses
      guessCount = guessCount + 1
      #Increments the value of the guessCount variable by 1
    elif (guess > computerNumber and (abs(computerNumber - guess) <= (int(computerNumber * .15)))):
    #Starts a conditional else/if statement to address when the user guesses a number that is greater than the number selected by the computer and is less than or equal to 15% of the value of the computerNumber away
      guessAsString = str(guess)
      #Declares and initializes variable guessAsString with the value of the variable guess cast as a string
      print("Your guess of "+ guessAsString + " is too high.")
      #Outputs information to the screen for the user
      print("You are very close!!!")
      #Outputs information to the screen for the user
      print("Please try again.")
      #Outputs information to the screen for the user
      print("")
      #Visually break-up the information on the screen for the user between their guesses
      guessCount = guessCount + 1
      #Increments the value of the guessCount variable by 1
  print("Would You Like to Run the Program Again?")
  #Outputs information to the screen for the user
  runAgain = input("[Y]es or [N]o")
  #Sets the value of the variable runAgain to the keyboard input received to allow user to repeat program or exit the outer-loop
  runAgain = runAgain.upper()
  #Sets the value of the variable runAgain to upper-case
print("Thank you for playing.")
#Outputs information to the screen for the user
print("Exiting Program - Goodbye")
#Outputs information to the screen for the user

As you can see, this version of the program also provides “encouragement” as you close-in on the selected number. Once you are within 15% of that number on the number-line you are told that you are very close.

Python Number Guesser

Last year, I gave a problem in JAVA to create a number guesser. The idea was that the computer would randomly select a number and the user had to guess the number the computer had picked. http://funmultiplies.com/semester-review-computer-science

This year, in Computer Science 1, we have done a similar assignment in Python. However, in this version, the user is selecting the number and the computer has to “guess” the number the user selected.

On the first day of this project, students had to first choose a solving strategy. The two best strategies were called Hi/Lo Average and Hi/Lo Random.

The idea with both of these is that we ask the user to pick an integer (whole number) between 1 and 100.

With Hi/Lo Average, we take the average of the highest and lowest numbers, in this case 100 and 1 and we get 49. So, our first guess will be 49. If that is too low, then we move the lowest value up from 1 to 48. If 49 was too high, then we would move the highest value down from 100 to 50. We then make our second guess by taking the average of the new highest and lowest numbers. We repeat this process until we get to the number the user selected. The key advantage to this process is that we are guaranteed to solve the problem in 7 or fewer questions.

With Hi/Lo Random, we move the highest and lowest numbers identically to how we did in Hi/Lo Average after each incorrect guess, but we don’t take the average – we just select a random number between the highest and lowest numbers. This can potentially solve the problem very quickly or take considerably longer than Hi/Lo Average since you are entirely dependent upon what integers are selected by a random number generator.

Here is what a possible Hi/Lo Average solution looks like:

#Programmer Name: Eric Evans, M.Ed.
#Program Name: Number Guesser (Hi/Lo Average)
#Program Description: Uses a Hi/Lo Average algorithm to determine the number chosen the user.
#Algorithm: Starts with hi/lo or 100/1. Calculates average of hi/lo. Adjusts hi/lo accordingly after guess. Repeat calculation of average between new hi/lo. Repeat hi/lo adjustment...
#
correct = "N"
#Creates a variable named "correct" and sets the initial value as N
high = 100
#Creates a variable named "high" and sets the initial value as 100
low = 1
#Creates a variable named "low" and sets the initial value as 1
guessCount = 1
#Creates a variable named "guessCount" and sets the initial value as 1
guess = (high + low) / 2
#Creates a variable named "guess" and sets the initial value as the average of high and low
while (correct == "N"):
#Starts a loop that runs as long as the variable "correct" has a value of "N".
  guess = int(guess)
  #Casts the value of the variable "guess" as an integer. This truncates any decimals.
  guessAsString = str(guess)
  #Creates a variable named "guessAsString" and sets the initial value as the value of the variable named "guess" as a string.
  print ("Is Your Number " + guessAsString + "?")
  #Outputs the current "guess" for the user to see.
  response = input("[C]orrect  /  Too [L]ow  /  Too [H]igh")
  #Creates a variable named "response" and sets the initial value as the input from the keyboard.
  if (response == "C"):
  #Start of a conditional statement if the keyboard input is "C".
    guessCountAsString = str(guessCount)
    #Creates a variable named "guessCountAsString" and sets the initial value as the value of the variable named "guessCount" as a string.
    print("Yay! I got it in " + guessCountAsString + " guesses!")
    #Outputs the line displayed when the correct number is guessed.
    correct = "Y"
    #Changes the value of the variable named "correct" to "Y".
  elif (response == "L"):
  #Start of a conditional statement if the keyboard input is "L".
    print ("Too Low Huh?")
    #Outputs an acknowledgement to the user of their input.
    low = guess + 1
    #Changes the value of the variable named "low" to the value of the current guess + 1.
    guess = (high + low) / 2
    #Changes the value of the variable named "guess" to the value of the average of high and low.
    guessCount = guessCount + 1
    #Changes the value of the variable named "guessCount" by adding 1 to its existing value.
  elif (response == "H"):
  #Start of a conditional statement if the keyboard inputs is "H".
    print ("Too High Huh?")
    #Outputs an acknowledgement to the user of their input.
    high = guess - 1
    #Changes the value of the variable named "high" to the value of the current guess - 1.
    guess = (high + low) / 2
    #Changes the value of the variable named "guess" to the value of the average of high and low.
    guessCount = guessCount + 1
    #Changes the value of the variable named "guessCount" by adding 1 to its existing value.
print ("Exiting Program")
#Outputs a message letting the user they are exiting the program.

At the time of the first writing, I omitted the Hi/Lo Random solution as I wanted to see if my students could identify a key weakness inherent in that strategy. Here is a possible Hi/Lo Random solution (I discuss the weakness below):

#Programmer Name: Eric Evans, M.Ed.
#Program Name: Number Guesser (Hi/Lo Random)
#Program Description: Uses a Hi/Lo Random algorithm to determine the number chosen the user.
#Algorithm: Starts with hi/lo or 100/1. Selects a random number between hi/lo. Adjusts hi/lo accordingly after guess. Repeat selection of a random number between new hi/lo. Repeat hi/lo adjustment...
#
import random
correct = "N"
high = 100
low = 1
guessCount = 1
guess = random.randint(low, high)
while (correct == "N"):
  guess = int(guess)
  guessAsString = str(guess)
  print ("Is Your Number " + guessAsString + "?")
  response = input("[C]orrect  /  Too [L]ow  /  Too [H]igh")
  if (response == "C"):
    guessCountAsString = str(guessCount)
    print("Yay! I got it in " + guessCountAsString + " guesses!")
    correct = "Y"
  elif (response == "L"):
    print ("Too Low Huh?")
    low = guess + 1
    guess = random.randint(low, high)
    guessCount = guessCount + 1
  elif (response == "H"):
    print ("Too High Huh?")
    high = guess - 1
    guess = random.randint(low, high)
    guessCount = guessCount + 1
print ("Exiting Program")

If you played the Hi/Lo Random version of the game, you realized that there is nothing in the program to prevent the computer from randomly guessing the same number multiple times. This would need to be addressed by using a data structure to store the guesses and compare them as each subsequent guess was being made.

In addition, the odds are not “favorable” with a Hi/Lo Random game when compared to a Hi/Lo Average game.

Let’s say that the user has selected the number 21 as their number. Now, let’s look at the odds through each run compared side-by-side. I am going to use the random number generator from Google to generate the guesses for this example:

Run # Hi/Lo Average Hi/Lo Random
Guess Odds Guess Odds
1 50 1:100 16 1:100
2 25 1:49 48 1:30
3 12 1:23 17 1:29
4 18 1:11 27 1:8
5 21 1:1 25 1:6
6 N/A N/A 21 1:1

As you can see, with Hi/Lo Random, you are completely at the mercy of the numbers that are randomly generated whereas with Hi/Lo Average, you are guaranteed that your odds are twice as good after each guess.

Tabs Don’t Mean Spit – at Least in JAVA

You would think I could remember this, but I can’t. Tabs don’t mean spit – at least in JAVA!

My UIL Computer Science team was working on the following question recently:

What is the output of the following code?

a) north
b) northKorea
c) china
d) south
e) There is no output due to an error

String count="Korea";
boolean host=true;
if(count.equalsIgnoreCase("KoReA")) {
    if(host)
      out.print("north");
    else
      out.print("south");
  }
  else
    out.print("china");
    out.print(count);

The answer key shows the correct answer as being “B”. When you compile the program, you find that the answer is in-fact “B”.

We had originally reasoned that the answer would be “A” since the else condition that starts online 11 is never met. We interpreted that lines 12 and 13 would run as part of that else statement.

I have been working with Python programming in my Computer Science 1 class and anyone who has worked with Python knows that tabs are the end-all of everything.

For reference, here is what the program looks like with all of the conditionals enclosed in curly braces and tabs adjusted for readability…

class Main {
  public static void main(String[] args) {
    String count="Korea";
    boolean host=true;
    if(count.equalsIgnoreCase("KoReA")) {
      if(host){
        System.out.print("north");
      }else{
        System.out.print("south");
      }
     }else{
       System.out.print("china");
    }
    System.out.print(count);
  }
}

As you can see below, you get the same solution with the code in this configuration:

It was my mistake for not catching it, but it’s a lesson learned. As you can see, line 14 is NOT part of the else statement that starts on line 11.

Grade Calculator Programming – Day 1

Today, we started development of the minimum grade calculator in Computer Science 1.

#Programmer Name: Eric Evans, M.Ed.
#Program Name: Grade Calculator
#Program Description: Provides a minimum grade needed to get a C, B, or A in a given course for the semester and for the year.
#
print ("*********************************************************")
print ("** Welcome to the Grade Calculator                     **")
print ("**                                                     **")
print ("** You will need the following information to proceed: **")
print ("** - Fall Semester (S1) Grade                          **")
print ("** - 3rd Quarter (Q3) Grade                            **")
print ("**                                                     **")
print ("*********************************************************")
print ("")

Here, we started with our generic header and then a welcome screen that lets the user know what to expect and what they will need to proceed.

minC = 68.5
#Minimum average grade for "C" per Ferris ISD
minB = 79.5
#Minimum average grade for "B" per Ferris ISD 
minA = 89.5
#Minimum average grade for "A" per Ferris ISD

Here, are establishing the minimum graded needed to pass (minC), and get a B (minB) and an A (minA) according to our current grading guidelines.

s1 = float(input("What is your Fall Semester (S1) Grade? "))
#Ask for S1 input and cast as float
q3 = float(input("What is your 3rd Quarter (Q3) Grade? "))
#Ask for Q3 input and cast as float

Here, we are creating a variable named s1, which is going to hold the data entered by the user for their fall semester grade. We then create a variable named q3which is going to hold the data entered by the user for their 3rd quarter grade.

semMinC = ( ( ( 5 * minC ) - ( q3 * 2 ) ) / 3 )
#C Algorithm - Developed on 19-March-2018
semMinB = ( ( ( 5 * minB ) - ( q3 * 2 ) ) / 3 )
#B Algorithm - Developed on 19-March-2018
semMinA = ( ( ( 5 * minA ) - ( q3 * 2 ) ) / 3 )
#A Algorithm - Developed on 19-March-2018

Here is where we get to use the algorithm that was developed in the previous class ( Grade Calculator Algorithm Development ).

You will notice that it is being used 3 different times. Each case is separate to address the 3 different grade breaks (68.5, 79.5, and 89.5).

semMinCRounded = round(semMinC,2)
#Rounds minimum "C" output to 2 decimal points
semMinBRounded = round(semMinB,2)
#Rounds minimum "B" output to 2 decimal points
semMinARounded = round(semMinA,2)
#Rounds minimum "A" output to 2 decimal points

Here, we take the solution for each case and then round it to 2 decimal points.

semMinCString = str(semMinCRounded)
#Casts minimum "C" output as string
semMinBString = str(semMinBRounded)
#Casts minimum "B" output as string
semMinAString = str(semMinARounded)
#Casts minimum "A" output as string

Here, we are casting the rounded output as a string so we can use it in our output.

print("")
print("***********Q4 & SE2 MINIMUMS (SEMESTER)***********")
print("Min for C for Semester = " + semMinCString)
#Outputs minimum for "C" for semester
print("Min for B for Semester = " + semMinBString)
#Outputs minimum for "B" for semester
print("Min for A for Semester = " + semMinAString)
#Outputs minimum for "A" for semester

Here we finally provide our output for the use to see.

This code is deliberately broken-up so the students can see and manipulate the various components. (e.g., lines 24, 30, and 36).

Here is a consolidated version of the code that combines multiple steps:

#Programmer Name: Eric Evans, M.Ed.
#Program Name: Grade Calculator
#Program Description: Provides a minimum Grade
#
print ("*********************************************************")
print ("** Welcome to the Grade Calculator                     **")
print ("**                                                     **")
print ("** You will need the following information to proceed: **")
print ("** - Fall Semester (S1) Grade                          **")
print ("** - 3rd Quarter (Q3) Grade                            **")
print ("**                                                     **")
print ("*********************************************************")
print("")
minC = 68.5
#Minimum average grade for "C" per Ferris ISD
minB = 79.5
#Minimum average grade for "B" per Ferris ISD 
minA = 89.5
#Minimum average grade for "A" per Ferris ISD
s1 = float(input("What is your Fall Semester (S1) Grade? "))
#Ask for S1 input and cast as float
q3 = float(input("What is your 3rd Quarter (Q3) Grade? "))
#Ask for Q3 input and cast as float
semMinC = str ( round ( ( ( ( 5 * minC ) - ( q3 * 2 ) ) / 3 ), 2) )
#C Algorithm - Developed on 19-March-2018 rounded to 2 decimal places and cast as a string
semMinB = str ( round ( ( ( ( 5 * minB ) - ( q3 * 2 ) ) / 3 ), 2) )
#B Algorithm - Developed on 19-March-2018 rounded to 2 decimal places and cast as a string
semMinA = str ( round ( ( ( ( 5 * minA ) - ( q3 * 2 ) ) / 3 ), 2) )
#A Algorithm - Developed on 19-March-2018 rounded to 2 decimal places and cast as a string
print("")
print("***********Q4 & SE2 MINIMUMS (SEMESTER)***********")
print("Min for C for Semester = " + semMinC)
#Outputs minimum for "C" for semester
print("Min for B for Semester = " + semMinB)
#Outputs minimum for "B" for semester
print("Min for A for Semester = " + semMinA)
#Outputs minimum for "A" for semester

You can see that lines 24 through 29 are compressed versions of lines 24 through 41 of the original code. Let’s take a quick look at how this was accomplished:

semMinC = str ( round ( ( ( ( 5 * minC ) - ( q3 * 2 ) ) / 3 ), 2) )

Here is line 24 of the compressed version. You can see that we have a math problem in the middle that is rounded to 2 decimal points that is cast as a string.

The original (expanded) code took the following lines to accomplish the same thing:

semMinC = ( ( ( 5 * minC ) - ( q3 * 2 ) ) / 3 )
semMinCRounded = round(semMinC,2)
semMinCString = str(semMinCRounded)

When we return next class, the students will be developing the second part of the program, which addresses the minimums needed for the 3 cases for the year.

For reference, here is a link to the IDE of the code at this checkpoint:

Coding Bat Logic Problems – Day 2

Last class we looked at the first of 4 logic problems on Coding Bat in Computer Science 1 ( http://funmultiplies.com/coding-bat-logic-problems-day-1 ). We’re now looking at the last 4 logic problems of that Coding Bat set in CS1 as we get ready to depart for Spring Break.

alarm clock

http://codingbat.com/prob/p119867

Here is the setup of this problem:

Given a day of the week encoded as 0=Sun, 1=Mon, 2=Tue, …6=Sat, and a boolean indicating if we are on vacation, return a string of the form “7:00” indicating when the alarm clock should ring. Weekdays, the alarm should be “7:00” and on the weekend it should be “10:00”. Unless we are on vacation — then on weekdays it should be “10:00” and weekends it should be “off”.

def alarm_clock(day, vacation):
  if (day == 0 or day == 6) and vacation == True:
    return "off"
  elif (day == 0 or day == 6) and vacation == False:
    return "10:00"
  elif (day == 1 or day == 2 or day == 3 or day == 4 or day == 5) and vacation == False:
    return "7:00"
  else:
    return "10:00"

This one is not hard, but just involved with conditional statements. The major things to keep an eye out for are the spelling of the return “off” is all lower-case and the week starts on day 0 with Sunday.

love 6

http://codingbat.com/prob/p100958

Here is the setup for this problem:

The number 6 is a truly great number. Given two int values, a and b, return True if either one is 6. Or if their sum or difference is 6. Note: the function abs(num) computes the absolute value of a number.

def love6(a, b):
  if (a) == 6 or (b) == 6:
    return True
  elif (a) + (b) == 6 or (b) + (a) == 6:
    return True
  elif (a) - (b) == 6 or (b) - (a) == 6:
    return True
  else:
    return False

I personally do not like this problem because of the “Note” at the end. It throws many programmers off. Yes, you can solve this using absolute values, but it’s not necessary.

Once you get other that “distractor”, this is a simple conditional logic problem.

In 1 to 10

http://codingbat.com/prob/p158497

Here is the setup for this problem:

Given a number n, return True if n is in the range 1..10, inclusive. Unless outside_mode is True, in which case return True if the number is less or equal to 1, or greater or equal to 10.

def in1to10(n, outside_mode):
  if outside_mode == False and (n >= 1 and n <= 10):
    return True
  elif outside_mode == True and (n <= 1 or n >= 10):
    return True
  else:
    return False

This is a pretty simple conditional logic problem. If the Boolean flag is False, we are looking for numbers between 1 and 10 (inclusive) and if the Boolean flag is True, we are looking for numbers outside of 1 and 10 (inclusive).

On this particular question, I awarded extra credit if my students could explain mathematically why when the outside_mode Boolean flag is True, the Boolean operator must be OR.

The reason is that while the Boolean flag is False, num is to be between 1 and 10 inclusive. A number can be simultaneously between 1 and 10. As such, the Boolean AND is used in this statement.

Conversely, when the Boolean flag is True, num is to be outside of 1 and 10 inclusive. A number CANNOT be simultaneously less than 1 and greater than 10. As such, the Boolean OR is needed for this statement.

near ten

http://codingbat.com/prob/p165321

Here is the setup for this problem:

Given a non-negative number “num”, return True if num is within 2 of a multiple of 10. Note: (a % b) is the remainder of dividing a by b, so (7 % 5) is 2.

def near_ten(num):
  if num % 10 == 0 or num % 10 == 1 or num % 10 == 2 or num % 10 == 8 or num % 10 == 9:
    return True
  else:
    return False

This particular one needs a little bit of explanation on the algorithm that was used. The general concept is pretty straightforward, but the formula may not be.

Here, we are looking at the modulus of num by 10. In this case, that will always return a 0, 1, or 2 if the number is a multiple of 10, or 1 greater than a multiple of 10, or 2 greater than a multiple of 10 respectively.

On the other side, we will always return an 8 or 9 if the number is 2 less than a multiple of 10, or 1 less than a multiple of 10 respectively.

Beyond the algorithm, the problem is a simple logic conditional program.

Coding Bat Logic Problems – Day 1

Today, we looked at logic problems in Coding Bat in Computer Science 1. Students had to use Boolean logic operators and conditional if/else an if/elif/else statements.

Cigar Party

http://codingbat.com/prob/p195669

Here is the setup of the problem:

When squirrels get together for a party, they like to have cigars. A squirrel party is successful when the number of cigars is between 40 and 60, inclusive. Unless it is the weekend, in which case there is no upper bound on the number of cigars. Return True if the party with the given values is successful, or False otherwise.

def cigar_party(cigars, is_weekend):
  if is_weekend == True and cigars >=40:
    return True
  elif is_weekend == False and cigars >=40 and cigars <=60:
    return True
  else:
    return False

Here, we used the Boolean AND operator to check the number of cigars in relation to the value of is_weekend.

Lines 2 – 3 address if it is a weekend AND are there at least 40 cigars. If so, a TRUE is returned.

Lines 4 – 5 address if is is NOT a weekend AND there are between 40 and 60 cigars. If so, a TRUE is returned.

Lines 6 – 7 address everything else as the default case and return a FALSE.

Date Fashion

http://codingbat.com/prob/p129125

Here is the setup of the problem:

You and your date are trying to get a table at a restaurant. The parameter “you” is the stylishness of your clothes, in the range 0..10, and “date” is the stylishness of your date’s clothes. The result getting the table is encoded as an int value with 0=no, 1=maybe, 2=yes. If either of you is very stylish, 8 or more, then the result is 2 (yes). With the exception that if either of you has style of 2 or less, then the result is 0 (no). Otherwise the result is 1 (maybe).

def date_fashion(you, date):
  if you <=2 or date <=2:
    return 0
  elif you >= 8 or date >= 8:
    return 2
  else:
    return 1

Here, the order of the conditions is EXTREMELY important. Let’s look at the case of you = 9 and date = 1.

In the code above, we would reach the first the first conditional statement with you <=2 is FALSE but date <=2 is TRUE. Since a Boolean OR is being used, only one of them must be true for the associated code to run. So, we return a value of 0 and exit the conditional loop, which is the correct response for the problem.

Now, let’s change the code to the following:

def date_fashion(you, date):
  if you >= 8 or date >= 8:
    return 2
  elif you <=2 or date <=2:
    return 0
  else:
    return 1

All that we have done is swap the conditions between lines 2 and 4 with each other. Let’s examine the case of you = 9 and date = 1 again.

We enter at the first conditional statement with you >= 8 is TRUE but date >= is FALSE. Since a Boolean OR is being used, only one of them must be true for the associated code to run. So, we return a value of 2 and exit the conditional loop, which is the incorrect response for the problem.

The order of our conditional statements is EXTREMELY important!

Squirrel Play

http://codingbat.com/prob/p135815

Here is the setup of the problem:

The squirrels in Palo Alto spend most of the day playing. In particular, they play if the temperature is between 60 and 90 (inclusive). Unless it is summer, then the upper limit is 100 instead of 90. Given an int temperature and a boolean is_summer, return True if the squirrels play and False otherwise.

def squirrel_play(temp, is_summer):
  if is_summer == True and temp >= 60 and temp <= 100:
    return True
  elif is_summer == False and temp >= 60 and temp <= 90:
    return True
  else:
    return False

Lines 2 – 3 check if it is summer. If it is, we then check to see if the temperature is between 60 and 100 degrees inclusive. If it passes all 3 of these tests (Boolean AND), we return the value of TRUE.

Lines 4 – 5 check if it is NOT summer. If it is NOT summer, we then check to see if the temperature is between 60 and 90 degrees inclusive. If it passes all 3 of these tests (Boolean AND), we return the value of TRUE.

Lines 6 -7 are the default case if neither of the above tests can be passed and returns the value of FALSE.

Caught Speeding

http://codingbat.com/prob/p137202

Here is the setup of the problem:

You are driving a little too fast, and a police officer stops you. Write code to compute the result, encoded as an int value: 0=no ticket, 1=small ticket, 2=big ticket. If speed is 60 or less, the result is 0. If speed is between 61 and 80 inclusive, the result is 1. If speed is 81 or more, the result is 2. Unless it is your birthday — on that day, your speed can be 5 higher in all cases.

def caught_speeding(speed, is_birthday):
  if is_birthday == True and speed <= 65:
    return 0
  elif is_birthday == False and speed <= 60:
    return 0
  elif is_birthday == True and speed >= 66 and speed <=85:
    return 1
  elif is_birthday == False and speed >=61 and speed <= 80:
    return 1
  else:
    return 2

Much like the problem before earlier, we a set of Boolean AND statements. When using the Boolean AND we must remember that ALL conditions must be satisfied for the statement to be considered TRUE and to thereby execute the associated instructions.

Lines 2 – 3 and 6 – 7 are working with when is_birthday is TRUE while lines 4 – 5 and 8 – 9 are working with when is_birthday is FALSE. All of these lines are using comparative operators for the speeds.

Coding Bat Recursive Problems – Day 1

Today, we are looking at a primer for recursion using problems in CodingBat in Computer Science 2. We looked at 3 different problems from CodingBat.

Bunny Ears

http://codingbat.com/prob/p183649

Here is the setup of the problem:

We have a number of bunnies and each bunny has two big floppy ears. We want to compute the total number of ears across all the bunnies recursively (without loops or multiplication).

public int bunnyEars(int bunnies) {
  if (bunnies == 0){
    return 0;
  } else {
    return 2 + bunnyEars(bunnies-1);
  }
}

Let’s use an input of 6. With this, we would anticipate the output to be 12, since each bunny has 2 ears.

Line 3 will not be run since the condition set in line 2 is FALSE. Currently, bunnies is set to 6.

So, we move on to line 4, which is the start of the default case, and is executed on line 5. So with bunnies set to 6, we return a 2 and then add that to the number of bunny ears from the next bunny (bunnies – 1), which is bunny #5.

Now, bunnies = 5, so line 2 is still FALSE, so we run the default case on line 6. We return a 2 and add that to the number of bunny ears from the next bunny (bunnies – 1), which is bunny #4.

Now, bunnies = 4, so line 2 is still FALSE, so we run the default case on line 6. We return a 2 and add that to the number of bunny ears from the next bunny (bunnies – 1), which is bunny #3.

Now, bunnies = 3, so line 2 is still FALSE, so we run the default case on line 6. We return a 2 and add that to the number of bunny ears from the next bunny (bunnies – 1), which is bunny #2.

Now, bunnies = 2, so line 2 is still FALSE, so we run the default case on line 6. We return a 2 and add that to the number of bunny ears from the next bunny (bunnies – 1), which is bunny #1.

Now, bunnies = 1, so line 2 is still FALSE, so we run the default case on line 6. We return a 2 and add that to the number of bunny ears from the next bunny (bunnies – 1), which is 0.

Now, bunnies = 0, so line 2 is now TRUE, so we return a 0 and exit the loop.

We now add the following together:

  • 0 from when bunnies = 0 (cumulative total = 0)
  • 2 from when bunnies = 1 (cumulative total = 2)
  • 2 from when bunnies = 2 (cumulative total = 4)
  • 2 from when bunnies = 3 (cumulative total = 6)
  • 2 from when bunnies = 4 (cumulative total = 8)
  • 2 from when bunnies = 5 (cumulative total = 10)
  • 2 from when bunnies = 6 (cumulative total = 12)

The total is returned as 12 ears.

Bunny Ears 2

http://codingbat.com/prob/p107330

Here is the setup of the problem:

We have bunnies standing in a line, numbered 1, 2, … The odd bunnies (1, 3, ..) have the normal 2 ears. The even bunnies (2, 4, ..) we’ll say have 3 ears, because they each have a raised foot. Recursively return the number of “ears” in the bunny line 1, 2, … n (without loops or multiplication).

public int bunnyEars2(int bunnies) {
  if (bunnies == 0){
    return 0;
  } else if (bunnies % 2 != 0){
    return 2 + bunnyEars2(bunnies-1);
  } else{
    return 3 + bunnyEars2(bunnies-1);
  }
}

For this one, let’s use an input of 5. We would expect the output to be 12 since bunnies 1, 3, & 5 have a total 6 ears and bunnies 2 & 4 have a total of 6 ears.

Line 3 will not be run since the condition set in line 2 is FALSE. Currently, bunnies is set to 5.

So, we move on to line 4. This condition is looking to see if we are working with an even numbered or odd numbered bunny. We have set the condition to use the modulus of 2 of the integer of bunnies. If the modulus is NOT 0, then the statement is TRUE and therefore it is an ODD numbered bunny.

Line 6 is the start of the default case which is used if we are working with an EVEN numbered bunny.

Now, bunnies = 5, so line 2 is FALSE, and line 4 is TRUE. We return a 2 and add that to the number of bunny ears from the next bunny (bunnies – 1), which is bunny #4.

Now, bunnies = 4, so line 2 is FALSE, line 4 is FALSE, so we run the default case at line 6. We return a 3 and add that to the number of bunny ears from the next bunny (bunnies -1), which is bunny #3.

Now, bunnies = 3, so line 2 is FALSE, and line 4 is TRUE. We return a 2 and add that to the number of bunny ears from the next bunny (bunnies – 1), which is bunny #2.

Now, bunnies = 2, so line 2 is FALSE, line 4 is FALSE, so we run the default case at line 6. We return a 3 and add that to the number of bunny ears from the next bunny (bunnies -1), which is bunny #1.

Now, bunnies = 1, so line 2 is FALSE, and line 4 is TRUE. We return a 2 and add that to the number of bunny ears from the next bunny (bunnies – 1), which is 0.

Now, bunnies = 0, so line 2 is now TRUE, so we return a 0 and exit the loop.

We now add the following together:

  • 0 from when bunnies = 0 (cumulative total = 0)
  • 2 from when bunnies = 1 (cumulative total = 2)
  • 3 from when bunnies = 2 (cumulative total = 5)
  • 2 from when bunnies = 3 (cumulative total = 2)
  • 3 from when bunnies = 4 (cumulative total = 10)
  • 2 from when bunnies = 5 (cumulative total = 12)

The total is returned as 12 ears.

Triangle

http://codingbat.com/prob/p194781

Here is the setup of the problem:

We have triangle made of blocks. The topmost row has 1 block, the next row down has 2 blocks, the next row has 3 blocks, and so on. Compute recursively (no loops or multiplication) the total number of blocks in such a triangle with the given number of rows.

public int triangle(int rows) {
 if (rows == 0){
   return 0;
 } else {
   return rows + triangle(rows - 1);
 }
}

Here, we are building something that looks like this:

Like the cases before it, line 2 is a condition looking for when we are to row 0. If line 2 is FALSE, we will move to line 4. For this example, let’s use rows = 4. With this, the output should be 10 as there are 10 cubes needed to complete a 4 row triangle.

So, we start with rows = 4. Line 2 is FALSE, so we move to line 4 to execute line 5, where we return the row number and add it to the number of cubes on the next row (rows – 1), which is row #3.

We are returning the row number as that is equal to the number of cubes of each row (e.g. row 7 = 7 cubes, row 4 = 4 cubes, etc…).

We now move to rows = 3. Line 2 if FALSE, so we move to line 4 to execute line 5, where we return the row number and add it to the number of cubes on the next row (rows – 1), which is row #2.

We now move to rows = 2. Line 2 if FALSE, so we move to line 4 to execute line 5, where we return the row number and add it to the number of cubes on the next row (rows – 1), which is row #1.

We now move to rows = 1. Line 2 if FALSE, so we move to line 4 to execute line 5, where we return the row number and add it to the number of cubes on the next row (rows – 1), which is 0.

Now, rows = 0, so line 2 is now TRUE, so we return a 0 and exit the loop.

We now add the following together:

  • 0 from when rows = 0 (cumulative total = 0)
  • 1 from when rows = 1 (cumulative total = 1)
  • 2 from when rows = 2 (cumulative total = 3)
  • 3 from when rows = 3 (cumulative total = 6)
  • 4 from when rows = 4 (cumulative total = 10)

Python Recursion and Factorial

As the final Computer Science lesson of the 2016/2017 academic year, I reviewed the somewhat concept of recursion in the Python programming language. In this review, I used the mathematical concept of factorial to discuss recursion.

#Program Name: Recursion Sample
#Programmer Name: Eric Evans, M.Ed.
#Program Description: Provide a functional example of a recursion problem in Computer Science using the mathematical concept of factorial.
#
#Define function named factorial which will have an input value of n.
def factorial(n):
    print("Factorial has been called with n = " + str(n))
    if n == 1:
        return 1
    else:
        result = n * factorial(n-1)
        print(n,"! = ",result)
        return result
#Output the function factorial with an input value of 4.
print(factorial(4))

Let’s pull this concept apart line-by-line.

Lines 1 through 5 and line 14 are comment lines and have no real bearing on the program. They simply exist for documentation purposes.

At line 6, we declare a new function named “factorial” that will receive an input of “n”. This is done using the def or define call in Python. The “factorial” function occupies lines 6 through 13.

On line 7, we output the text “Factorial has been called with n = ” concatenated with the value of “n” cast as a string.

On lines 8 and 9, we enter the first part of a conditional statement. At line 8, we use a Boolean equals to see if “n” is equal to 1. If “n” is equal to 1, then line 8 executes and returns the value “1”.

Line 10 begins the process of addressing what to do if “n” does not equal 1.

On line 11, we declare a variable named “result”, which is defined as the value of “n” multiplied by the value of the “factorial” function with an input value that is one less than the current value of “n”.

Line 12 is simply allowing us to see the factorial value of the current “n” value each time through the loop.

Line 13 returns the value of the variable named “result”.

Line 15 calls the “factorial” function and provides it the necessary input to process. In this case, it is a 4.

Now, let’s see what happens when we run this code:

Factorial has been called with n = 4
Factorial has been called with n = 3
Factorial has been called with n = 2
Factorial has been called with n = 1
2 ! =  2
3 ! =  6
4 ! =  24
24

So, let’s see what’s going on with this output.

Lines 1 through 4 of the output are generated by line 7 of the code. That code displays the static words with the dynamic output of the value of “n”. Notice that each time through the loop, it decremented by 1.

Looking at lines 5 through 7 of the output, we see that the calculations actually start with the lowest factorial number of 2 and increment by 1.

Now, if you notice, the way the calculation was coded on line 11, we are performing the following:

  • (Step 1)  4! = 4 X 3!
    • This is the original problem. Solve for 4!, but it is defined needing to know the value of 3!, which is defined in step 2.
  • (Step 2)  3! = 3 X 2!
    • To solve step 1, we need to know the value of 3!. However, it is defined needing to know the value of 2!, which is defined in step 3.
  • (Step 3)  2! = 2 X 1!
    • To solve step 2, we need to know the value of 2!. However, it is defined needing to know the value of 1!, which is defined in step 4.
  • (Step 4)  1! = 1
    • To solve 3, we need to know the value of 1!. It has a given value of 1.
  • (Step 5)  2! = 2 X 1 = 2
    • Now, that we know the value of 1!, we can calculate the value of 2!.
  • (Step 6)  3! = 3 X 2 = 6
    • Now that we know the value of 2!, we can calculate the value of 3!.
  • (Step 7)  4! = 4 X 6 = 24
    • Now that we know the value of 3!, we can calculate the value of 4!, which was the original problem.

As you can see, the final solution is dependent upon the solution of a previous step, which was dependent upon the solution of a previous step, which was dependent upon the solution of a previous step, which – well you get the idea. This is the basic concept of recursion.

Basic Variables in Python

Today, we have been playing with basic variables in Python. The plan is to output something similar to the following:

Hello World
1 + 1 = 2
2 + 2 = 4
4 + 4 = 8

This output is to be generated entirely from calling variables.

#Programmer Name: Eric Evans, M.Ed.
#Program Name: 02 - Hello Variable
#Program Description: Outputs assigned information using only variables.
#
#DECLARATION OF VARIABLES
firstWord = "Hello"
secondWord = "World"
space = ' '
#OUTPUT
print(firstWord + space + secondWord)

Now, as you can see, the first line of the output is somewhat easy to code. We declared the variables firstWord, secondWord, and space and then called them to print concatenated together.

#Programmer Name: Eric Evans, M.Ed.
#Program Name: 02 - Hello Variable
#Program Description: Outputs assigned information using only variables.
#
#DECLARATION OF VARIABLES
firstWord = "Hello"
secondWord = "World"
space = ' '
firstAddend = 1
firstProblemSum = firstAddend + firstAddend
secondAddend = firstProblemSum
secondProblemSum = secondAddend + secondAddend
thirdAddend = secondProblemSum
thirdProblemSum = thirdAddend + thirdAddend
#OUTPUT
print(firstWord + space + secondWord)
print(firstAddend + " + " + firstAddend + " = " + firstProblemSum)
print(secondAddend + " + " + secondAddend + " = " + secondProblemSum)
print(thirdAddend + " + " + thirdAddend + " = " + thirdProblemSum)

Things start to act problematically when we try to produce the last 3 lines of output. When we run the application, we receive an error because we are attempting to mix string and integer variables on a combined output line.

To resolve this issue, we must typecast the integers as strings.

#Programmer Name: Eric Evans, M.Ed.
#Program Name: 02 - Hello Variable
#Program Description: Outputs assigned information using only variables.
#
#DECLARATION OF VARIABLES
firstWord = "Hello"
secondWord = "World"
space = ' '
firstAddend = 1
firstProblemSum = firstAddend + firstAddend
secondAddend = firstProblemSum
secondProblemSum = secondAddend + secondAddend
thirdAddend = secondProblemSum
thirdProblemSum = thirdAddend + thirdAddend
#CASTING OF VARIABLES
firstProblemSum = str(firstProblemSum)
firstAddend = str(firstAddend)
secondProblemSum = str(secondProblemSum)
secondAddend = str(secondAddend)
thirdProblemSum = str(thirdProblemSum)
thirdAddend = str(thirdAddend)
#OUTPUT
print(firstWord + space + secondWord)
print(firstAddend + " + " + firstAddend + " = " + firstProblemSum)
print(secondAddend + " + " + secondAddend + " = " + secondProblemSum)
print(thirdAddend + " + " + thirdAddend + " = " + thirdProblemSum)

As you can see, on lines 15 – 21 we cast each of the integer variables as a string variable. At this point, lines 24 – 26 will execute as expected.

The compilable code can be viewed at https://repl.it/HesM/3

2-Dimensional Arrays in Java

Today, we started to cover 2-dimensional arrays in Java. I decided to start with something very easy:

2-D Array Visual
2-D Array Visual

We have an array with 2 rows and 3 columns. Like all things in Java, we start counting our indices at 0.

As such, the value of [0][0] is Vanilla and [1][0] is Ice Cream. Note that the first number in the reference points to the row and the second number in the reference points to the column.

import java.util.*;
public class TwoDArrays {
    public static void main(String[] args){
        String[][] myBigArray = new String [][] {
            {"Vanilla ", "Chocolate ", "Strawberry "},
            {"Ice Cream", "Cookie", "Candy"}
        };
        System.out.println(myBigArray[0][0] + myBigArray[1][0]);
        System.out.println(myBigArray[0][1] + myBigArray[1][0]);
        System.out.println(myBigArray[0][2] + myBigArray[1][0]);
        
        System.out.println(myBigArray[0][0] + myBigArray[1][1]);
        System.out.println(myBigArray[0][1] + myBigArray[1][1]);
        System.out.println(myBigArray[0][2] + myBigArray[1][1]);
        
        System.out.println(myBigArray[0][0] + myBigArray[1][2]);
        System.out.println(myBigArray[0][1] + myBigArray[1][2]);
        System.out.println(myBigArray[0][2] + myBigArray[1][2]);
    }
}

Line 4 is where we created the 2-dimensional array named “myBigArray”.

Lines 5 and 6 are where we populated the array. Note that line 5 is the first row and line 6 is the second row.

Lines 8 through 18 are where we are outputting text that is “fed” by the 2-D array.

Line 8 concatenates [0][0] with [1][0] which is Vanilla and Ice Cream.

Line 9 concatenates [0][1] with [1][0] which is Chocolate and Ice Cream.

Line 10 concatenates [0][2] with [1][0] which is Strawberry and Ice Cream.

Line 12 concatenates [0][0] with [1][1] which is Vanilla and Cookie.

Line 13 concatenates [0][1] with [1][1] which is Chocolate and Cookie.

Line 14 concatenates [0][2] with [1][1] which is Strawberry and Cookie.

Line 16 concatenates [0][0] with [1][2] which is Vanilla and Candy.

Line 17 concatenates [0][1] with [1][2] which is Chocolate and Candy.

Line 18 concatenates [0][2] with [1][2] which is Strawberry and Candy.