mirror of
https://github.com/correl/correl.github.io.git
synced 2024-12-29 11:09:24 +00:00
203 lines
5.7 KiB
Org Mode
203 lines
5.7 KiB
Org Mode
#+TITLE: Birthday Puzzle
|
||
#+DATE: <2015-04-18 Sat>
|
||
#+AUTHOR: Correl Roush
|
||
#+EMAIL: correl@gmail.com
|
||
#+OPTIONS: toc:nil num:nil
|
||
#+PROPERTY: header-args:prolog :system swipl :session *birthday* :goal true :exports both
|
||
|
||
This logic puzzle has been floating around the internet lately. When I
|
||
caught wind of it, I thought it would be a great exercise to tackle
|
||
using Prolog. I'm not especially good with the language yet, so it
|
||
added to the challenge a bit, but it was a pretty worthwhile
|
||
undertaking. When I got stumped, I discovered that mapping out the
|
||
birthdays into a grid helped me visualize the problem and ultimately
|
||
solve it, so I've included that with my prolog code so you can see how
|
||
I arrived at the answer.
|
||
|
||
* The Puzzle
|
||
Albert and Bernard have just met Cheryl. “When is your birthday?”
|
||
Albert asked Cheryl. Cheryl thought for a moment and said, “I won’t
|
||
tell you, but I’ll give you some clues”. She wrote down a list of
|
||
ten dates:
|
||
|
||
|
||
- May 15, May 16, May 19
|
||
- June 17, June 18
|
||
- July 14, July 16
|
||
- August 14, August 15, August 17
|
||
|
||
“One of these is my birthday,” she said.
|
||
|
||
|
||
Cheryl whispered in Albert’s ear the month, and only the month, of
|
||
her birthday. To Bernard, she whispered the day, and only the
|
||
day. “Can you figure it out now?” she asked Albert.
|
||
|
||
|
||
Albert: “I don’t know when your birthday is, but I know Bernard
|
||
doesn’t know, either.”
|
||
|
||
Bernard: “I didn’t know originally, but now I do.”
|
||
|
||
Albert: “Well, now I know, too!”
|
||
|
||
/When is Cheryl’s birthday?/
|
||
|
||
* The Solution
|
||
** The Dates
|
||
|
||
To start off, i entered each of the possible birthdays as facts:
|
||
|
||
#+BEGIN_SRC prolog :results silent
|
||
possible_birthday(may, 15).
|
||
possible_birthday(may, 16).
|
||
possible_birthday(may, 19).
|
||
possible_birthday(june, 17).
|
||
possible_birthday(june, 18).
|
||
possible_birthday(july, 14).
|
||
possible_birthday(july, 16).
|
||
possible_birthday(august, 14).
|
||
possible_birthday(august, 15).
|
||
possible_birthday(august, 17).
|
||
#+END_SRC
|
||
|
||
And here they are, mapped out in a grid:
|
||
|
||
| | May | June | July | August |
|
||
|----+-----+------+------+--------|
|
||
| 14 | | | X | X |
|
||
| 15 | X | | | X |
|
||
| 16 | X | | X | |
|
||
| 17 | | X | | X |
|
||
| 18 | | X | | |
|
||
| 19 | X | | | |
|
||
|
||
** Albert's Statement
|
||
#+BEGIN_QUOTE
|
||
I don’t know when your birthday is,...
|
||
#+END_QUOTE
|
||
|
||
Albert only knows the month, and the month isn't enough to uniquely
|
||
identify Cheryl's birthday.
|
||
|
||
#+BEGIN_SRC prolog :results silent
|
||
month_is_not_unique(M) :-
|
||
bagof(D, possible_birthday(M, D), Days),
|
||
length(Days, Len),
|
||
Len > 1.
|
||
#+END_SRC
|
||
|
||
#+BEGIN_QUOTE
|
||
... but I know Bernard doesn’t know, either.
|
||
#+END_QUOTE
|
||
|
||
Albert knows that Bernard doesn't know Cheryl's
|
||
birthday. Therefore, the day alone isn't enough to know Cheryl's
|
||
birthday, and we can infer that the month of Cheryl's birthday does
|
||
not include any of the unique dates.
|
||
|
||
#+BEGIN_SRC prolog :results silent
|
||
day_is_not_unique(D) :-
|
||
bagof(M, possible_birthday(M, D), Months),
|
||
length(Months, Len),
|
||
Len > 1.
|
||
|
||
month_has_no_unique_days(M) :-
|
||
forall(possible_birthday(M,D),
|
||
day_is_not_unique(D)).
|
||
#+END_SRC
|
||
|
||
Based on what Albert knows at this point, let's see how we've
|
||
reduced the possible dates:
|
||
|
||
#+HEADER: :goal findall((M,D), part_one(M,D), Results)
|
||
#+BEGIN_SRC prolog
|
||
part_one(M,D) :-
|
||
possible_birthday(M,D),
|
||
month_is_not_unique(M),
|
||
month_has_no_unique_days(M),
|
||
day_is_not_unique(D).
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
: Results = [ (july, 14), (july, 16), (august, 14), (august, 15), (august, 17)].
|
||
|
||
So the unique days (the 18th and 19th) are out, as are the months
|
||
that contained them (May and June).
|
||
|
||
| | July | August |
|
||
|----+------+--------|
|
||
| 14 | X | X |
|
||
| 15 | | X |
|
||
| 16 | X | |
|
||
| 17 | | X |
|
||
|
||
** Bernard's Statement
|
||
#+BEGIN_QUOTE
|
||
I didn’t know originally, but now I do.
|
||
#+END_QUOTE
|
||
|
||
For Bernard to know Cheryl's birthday, the day he knows must be
|
||
unique within the constraints we have so far.
|
||
|
||
#+BEGIN_SRC prolog :goal findall((M,D), part_two(M,D), Results)
|
||
day_is_unique(Month, Day) :-
|
||
findall(M, part_one(M, Day), [Month]).
|
||
part_two(Month, Day) :-
|
||
possible_birthday(Month, Day),
|
||
day_is_unique(Month, Day).
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
: Results = [ (july, 16), (august, 15), (august, 17)].
|
||
|
||
Both July and August contain the 14th, so that row is out.
|
||
|
||
| | July | August |
|
||
|----+------+--------|
|
||
| 15 | | X |
|
||
| 16 | X | |
|
||
| 17 | | X |
|
||
|
||
** Albert's Second Statement
|
||
#+BEGIN_QUOTE
|
||
Well, now I know, too!
|
||
#+END_QUOTE
|
||
|
||
Albert's month must be the remaining unique month:
|
||
|
||
#+BEGIN_SRC prolog :goal findall((M,D), part_three(M,D), Results)
|
||
month_is_not_unique(Month, Day) :-
|
||
findall(D, part_two(Month, D), [Day]).
|
||
part_three(Month, Day) :-
|
||
possible_birthday(Month, Day),
|
||
month_is_not_unique(Month, Day).
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
: Results = [ (july, 16)].
|
||
|
||
August had two possible days, so it's now clear that the only
|
||
possible unique answer is July 16th.
|
||
|
||
| | July |
|
||
|----+------|
|
||
| 15 | |
|
||
| 16 | X |
|
||
| 17 | |
|
||
|
||
** Cheryl's Birthday
|
||
#+BEGIN_SRC prolog :goal cheryls_birthday(Month, Day)
|
||
cheryls_birthday(Month, Day) :-
|
||
part_three(Month, Day).
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
: Month = july,
|
||
: Day = 16.
|
||
|
||
So, there we have it. Cheryl's birthday is July 16th!
|
||
|
||
| | July |
|
||
|----+------|
|
||
| 16 | X |
|