Fathi
Fathi

Reputation: 1

caught speeding - CodingBat

most of you are aware of the 'caught speeding' coding problem on CodingBat. I have tried to solve it as below. i am not quite sure why it did not work there. i have viewed other solutions. and i believe the logic is similar but with some differences in implementation.

"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."

my code:

def caught_speeding(speed, is_birthday):
  while not is_birthday:
    speed = range(0,81)
    if speed <= 60:
      return 0
    elif speed > 65 and speed < 80:
      return 1
    else: 
      if speed > 81:
        return 2
  return speed - 5

Upvotes: -3

Views: 8096

Answers (7)

def caught_speeding(speed, is_birthday):
  while not is_birthday:
    speed = range(0,81)
    if speed <= 60:
      return 0
    elif speed > 65 and speed < 80:
      return 1
    else: 
      if speed > 81:
        return 2
  return speed - 5

In the give code the first line sets to check the if and else conditions only while is_birthday is false. All the code beneath "while not is_birthday" will not check what happens if is_birthday is true. Setting the speed to a range(0,81) is actually unnecessary since the function will accept any integer value as speed, but really we only need to check the cases for when the speed is below 60, between 61 and 80, and above 80.

The first statement to return 0 if speed is less than or equal to sixty will work correctly as long as is_birthday is false, but if its true, you then want to check if speed is less than or equal to 65. The return speed - 5 at the end will not check the is_birthday is true case. In actuality if a speed of 60 is given to function, it reduces the speed by 5 to 55 then passes it to the if statement.

The second if statement then checks if speed is between 65 and 80 which is not one of the cases given. If is_birthday is false, you want to check if speed is between 61 and 80, and it is true, if it's between 65 and 85. Here the min is set properly if you reduce speed by 5 in the return statement, but the speed max should be set to 85. Once again when you are changing speed you are not changing the bounds. You do not want to modify the input speed but rather modify the bounds based on the condition is_birthday.

The last statement should be checking if speed is greater than or equal to 81, but is not inclusive of 81. Once again the return speed - 5 at the end will take a given input of 85 reduce by 80 but does not do a check for if is_birthday is true.


We can break down the problem logically into two major parts, and three minor conditions. The major parts are if is_birthday equals True, and if is_birthday equals false. The minor parts or the speed ranges: less than or equal to 60, between 61 and 80 inclusive, and 81 or greater for when it is not your birthday, and in the case that it is your birthday, we raise all of the minimum and maximum speed limits by 5: less than or equal to 65, between 65 and 85 inclusive, and 86 or greater.

If we write the whole thing out it will look like this:

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

Now we can look for opportunities to simplify the conditions. We can set speed_min to 60 and speed_max to 80. Then check if is_birthday is true or false and raise both the min and max by 5.

As the true or false value of is_birthday is passed to the function, the min and max will be raised as necessary. Now we can check the minor conditions based on the input parameter of speed.

If it is between the min and max inclusive we return 1. If it is greater than the max we return 2. If it is less than the min we return 0.

When working through complicated logical structures, it's best to write everything out in the simplest way possible before attempting to simplify the function itself.

By writing out the boolean conditions in the longest way above we can clearly see where the bounds for the function are, and in what situation those bounds may be moved or changed. Since we are repeating code in the minor conditions, we can set hard values for the bound conditions and then modify the potential bounds by separating out the concern for when we want to change the maximum and minimum limits.

It's only after writing out the longer version can we find it easier to ask ourselves: What are the outer bounds for each condition? When do those bounds change? How can I separate the concern for changing the bounds? How can I reduce repeated code/logic by only checking the bound limits after a secondary condition is checked like is_birthday?

def caught_speeding(speed, is_birthday):
  
  speed_min = 60
  speed_max = 80
  
  if is_birthday:
    speed_min += 5
    speed_max += 5
  
  if speed_min < speed <= speed_max:
    return 1
  elif speed > speed_max:
    return 2
  elif speed <= speed_min:
    return 0

Upvotes: 0

Orwell
Orwell

Reputation: 1

I did it like this, to me it seems easier to read

def caught_speeding(speed, is_birthday):
   value = 0
        
   if is_birthday:
       speed -= 5
   if speed >= 81:
       value = 2
   elif speed >= 61:
       value = 1

   return value

Upvotes: 0

Muhammad Usman
Muhammad Usman

Reputation: 1

my code and it's working fine.

def caught_speeding(speed, is_birthday):

    if (is_birthday == False and speed <= 60):
        return 0
    elif (is_birthday == False and (speed > 60 and speed <= 80)):
        return 1    
    elif (is_birthday == False and speed > 80):
        return 2
    elif (is_birthday == True and speed <= 65):
        return 0
    elif (is_birthday == True and (speed > 65 and speed <= 85)):
        return 1
    elif (is_birthday == True and speed > 85):
        return 2
    else:
        pass

Upvotes: 0

Shashank Singh Yadav
Shashank Singh Yadav

Reputation: 459

This seems easy to understand for me:

def caught_speeding(speed, is_birthday):
               
  speed_adj=0
  
  if is_birthday:
    speed_adj=5
  if speed <=61 + speed_adj:
    return 0
  if speed <=80 + speed_adj:
    return 1
  return 2

Upvotes: 0

Ashish Umrao
Ashish Umrao

Reputation: 61

def caught_speeding(speed, is_birthday):
    # speed 60 or less ---> 0
    # b/t 61 and 80 ---> 1
    # 81+ ---> 2
    # if birthday 5+ in all

    if not is_birthday:
        if speed <= 60:
            return 0
        elif speed > 60 and speed <= 80:
            return 1
        elif speed > 80:
            return 2
        else:
            if speed <= 65:
                return 0
    elif speed > 65 and speed <= 85:
        return 1
    elif speed > 85:
        return 2

Upvotes: 1

Sayandip Dutta
Sayandip Dutta

Reputation: 15872

There are multiple issues with the code, but can be fixed without too much work.

  1. You are taking the speed as input, then again reassigning speed inside the function, which overwrites the integer with a range object.
  2. Your checking is wrong, you are missing the values from 61 to 65, hence if any number in this range is given as speed to the function, you will be stuck in an infinite loop is is_birthday is set to False.
  3. When is_birthday is True, you are returning the speed - 5 not the ticket he is going to get.

So, you may try this:

def caught_speeding(speed, is_birthday):
  while not is_birthday:
    if speed <= 60:
      return 0
    elif speed > 60 and speed < 81:
      return 1
    else: 
      if speed > 80:
        return 2
  return caught_speeding(speed - 5, False)

print(caught_speeding(64, False))
# 1
print(caught_speeding(64, True))
# 0

Here I have fixed the first two problems as you would expect, and for the last problem, used recursion. So when is_birthday is True, run as if the actual speed is 5 lower and is_birthday == False.

If you want to learn something new (assuming you don't know already):

def caught_speeding(speed, is_birthday):
    two = lambda x: 2 if x > 80 else one(x)
    one = lambda x: 1 if 60 < x <= 80 else zero(x)
    zero = lambda x: 0 if x <= 60 else two(x)
    return two(speed - 5*is_birthday)

Or,

def caught_speeding(speed, is_birthday):
    d = {0: lambda x: x <= 60, 1: lambda x: 60 < x < 81, 2: lambda x: x > 80}
    for ticket, condition in d.items():
        if condition(speed - 5*is_birthday): return ticket

Or (particular for this case),

def caught_speeding(speed, is_birthday):
    speed = speed - 5*is_birthday
    return [speed <= 60, 60 < speed <= 80, speed > 80].index(True)

Or (particular for this case),

def caught_speeding(speed, is_birthday):
    return min(max(0,(speed - 5*is_birthday-41)//20),2)

Or (particular for this case),

def caught_speeding(speed, is_birthday):
    s = speed-5*is_birthday
    return (s>60)+(s>80)

Upvotes: 1

Tony
Tony

Reputation: 10347

I've added some comments to your code:

def caught_speeding(speed, is_birthday): # << You are given the speed as a parameter
  while not is_birthday: # << you're using a while loop like an 'if' statement
    speed = range(0,81) # << so no need to generate a speed (and you probably meant to use random rather than range
    if speed <= 60:
      return 0
    elif speed > 65 and speed < 80: # << this logic does not match the question
      return 1
    else: 
      if speed > 81: # << what about when you are going 80 or 81 mph?
        return 2
  return speed - 5 # << and if it's your birthday it means you can add 5 mph to the speeds before you get a larger ticket. You are just subtracting 5

Upvotes: 2

Related Questions