Skip to content

Instantly share code, notes, and snippets.

@JCallicoat
Created May 5, 2015 06:44
Show Gist options
  • Save JCallicoat/c644b7076dc65d1391b6 to your computer and use it in GitHub Desktop.
Save JCallicoat/c644b7076dc65d1391b6 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
# Albert and Bernard have just become friends with Cheryl, and they want to know when her birthday is.
# Cheryl gives them a list of 10 possible dates:
# May 15, May 16, May 19
# June 17, June 18
# July 14, July 16
# August 14, August 15, August 17
# Cheryl then tells Albert and Bernard separately the month and day of her birthday respectively.
# Albert: I don't know when Cheryl's birthday is, but I know that Bernard does not know it too.
# Bernard: At first I don't know when Cheryl's birthday is, but now I know.
# Albert: Then I also know when Cheryl's birthday is.
from copy import deepcopy
DATES = {
'May': ['15', '16', '19'],
'June': ['17', '18'],
'July': ['14', '16'],
'August': ['14', '15', '17']
}
def Month(date):
return date.split(' ')[0]
def Day(date):
return date.split(' ')[1]
def day_counts(possible_dates=DATES):
day_counts = {}
for month, days in possible_dates.items():
for day in days:
if day in day_counts:
day_counts[day] += 1
else:
day_counts[day] = 1
return day_counts
def remove_unique_days(possible_dates):
possible_dates = deepcopy(possible_dates)
counts = day_counts(possible_dates)
for month, days in possible_dates.items():
for day, count in counts.items():
if count < 2 and days.count(day) > 0:
days.remove(day)
return possible_dates
def remove_single_days(possible_dates):
possible_dates = deepcopy(possible_dates)
for month, days in possible_dates.items():
if len(days) == 1:
possible_dates[month] = []
return possible_dates
def initial_dates(possible_dates):
print('List of possible dates initially given by Cheryl:\n%s\n' % possible_dates)
def alberts_first_statement(possible_dates):
'''
Albert: I don't know when Cheryl's birthday is, but I know that Bernard does not know it too.
'''
print('Albert must eliminate any date that is a unique day of the month:\n'
' If Bernard knows the day, and it is unique to a month, then he knows the month and day.\n'
' May 19th and June 18th are eliminated.')
possible_dates = remove_unique_days(possible_dates)
print('%s\n' % possible_dates)
print('Albert must eliminate any months with only one day:\n'
' If Albert knows the month and there is only one day, then he knows the day and month.\n'
' June 17th is eliminated.')
possible_dates = remove_single_days(possible_dates)
print('%s\n' % possible_dates)
return possible_dates
def bernards_first_statement(possible_dates):
'''
Bernard: At first I don't know when Cheryl's birthday is, but now I know.
'''
# XXX: How can this function be written?
#
# At this point, the possible_dates looks like:
#
# {'May': ['15', '16'], 'July': ['14', '16'], 'June': [], 'August': ['14', '15', '17']}
#
# We were NOT required to eliminate May in either of the two previous steps required
# to satisfy alberts_first_statement above.
#
# So how can we solve for the remaining requirements?
print('Bernard cannot narrow down the dates any further with the information he has. :(')
return possible_dates
def alberts_second_statement(possible_dates):
'''
Albert: Then I also know when Cheryl's birthday is.
'''
# XXX: How can this function be written?
print('Albert cannot narrow down the dates any further with the information he has. :(')
return possible_dates
initial_dates(DATES)
possible_dates = alberts_first_statement(DATES)
possible_dates = bernards_first_statement(possible_dates)
possible_dates = alberts_second_statement(possible_dates)
print('\nFinal possible dates of Cheryls birthday are:\n%s\n' % possible_dates)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment