def fashionably_late(arrivals, name):
"""Given an ordered list of arrivals to the party and a name, return whether the guest with that
name was fashionably late.
"""
half = len(arrivals)/2
fashion = arrivals[(int(half) + 1):-1]
if name in fashion:
return True
else:
return False
I expect return value of True given arrivals=['Paul', 'John', 'Ringo', 'George'] , name='Ringo' , but got False instead.
Where is the logic error in my code?
EDIT: I figured it out, thank you Vaclav and Quercus
def fashionably_late(arrivals, name):
"""Given an ordered list of arrivals to the party and a name, return whether the guest with that
name was fashionably late.
"""
if len(arrivals) % 2 != 1:
half = len(arrivals)/2
fashion = arrivals[int(half):-1]
return name in fashion
else:
half = len(arrivals)//2
fashion = arrivals[int(half)+1:-1]
return name in fashion
The expression name in fashion already has a boolean result (True|False) so instead of:
if name in fashion:
return True
else:
return False
You can use much simpler:
return name in fashion
The expression len(arrivals)/2 has result of type float which you later convert to int. You can use integer division and avoid later conversions: len(arrivals) // 2. The result will not be an exact half anymore so maybe the variable name should be updated then.
It is a good idea to use integer division to help divide the arrivals list. Consider the above expression in the context of a list that has an odd number of items compared to what happens with a list that has an even number of items. Is there a difference? It may also be worthwhile to think about whether the expression (len(arrivals) + 1) // 2 might be useful for this calculation.
With the right expression for calculating the index of the first person who arrived after at least half of the party’s guests, you can simply your code, eliminating the need for an if and an else block. That expression would compute the index correctly, regardless of whether an even or odd number of guests attended. See if you can figure it out. We can provide assistance if you need it.
It looks like you gave up looking for a simpler solution. I have already written it four days ago so here it is:
def fashionable_arrivals(arrivals):
"""Get list of guests who arrived fashionably late."""
after_half = (len(arrivals) + 1) // 2 # the first index after the half
return arrivals[after_half:-1]
def fashionably_late(arrivals, guest):
"""Tell if the guest is fashionably late.
Given an ordered list of arrivals to the party and a name, return whether
the guest with that name was fashionably late.
"""
return guest in fashionable_arrivals(arrivals)
Thanks, @vbrozik. That’s the key concept regarding how we can use a modulus along with an addend to get to the appropriate index for both an odd or even number of items in the list.
Regarding the bug in the original code, did you notice what index is produced by (int(half) + 1) compared to the list indexes? (The int() will work.)
0: 'Paul'
1: 'John'
2: 'Ringo'
3: 'George'
It looks like you ran into the 0-indexing paradox. It’s extremely useful most of the time, but at times like this, we end up either 1 before or 1 after where we wanted to be (and thought we were). I read recently that Julia and a few other languages use 1-based indexing and it creates more problems that it solves.