mirror of
https://github.com/correl/correl.github.io.git
synced 2024-12-29 11:09:24 +00:00
204 lines
5.7 KiB
Org Mode
204 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 |
|