diff --git a/_posts/2015-04-18-birthday-puzzle.html b/_posts/2015-04-18-birthday-puzzle.html new file mode 100644 index 0000000..1a2d7e7 --- /dev/null +++ b/_posts/2015-04-18-birthday-puzzle.html @@ -0,0 +1,473 @@ +--- +title: Birthday Puzzle +author: Correl Roush +--- +

+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: +

+ + + + +

+“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: +

+ +
+ +
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).
+
+
+ +

+And here they are, mapped out in a grid: +

+ + + + +++ ++ ++ ++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 MayJuneJulyAugust
14  XX
15X  X
16X X 
17 X X
18 X  
19X   
+
+
+ +
+

Albert's Statement

+
+
+

+I don’t know when your birthday is,… +

+
+ +

+Albert only knows the month, and the month isn't enough to uniquely +identify Cheryl's birthday. +

+ +
+ +
month_is_not_unique(M) :-
+    bagof(D, possible_birthday(M, D), Days),
+    length(Days, Len),
+    Len > 1.
+
+
+ +
+

+… but I know Bernard doesn’t know, either. +

+
+ +

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

+ +
+ +
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)).
+
+
+ +

+Based on what Albert knows at this point, let's see how we've +reduced the possible dates: +

+ +
+ +
part_one(M,D) :-
+    possible_birthday(M,D),
+    month_is_not_unique(M),
+    month_has_no_unique_days(M),
+    day_is_not_unique(D).
+
+
+ +
+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). +

+ + + + +++ ++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 JulyAugust
14XX
15 X
16X 
17 X
+
+
+ +
+

Bernard's Statement

+
+
+

+I didn’t know originally, but now I do. +

+
+ +

+For Bernard to know Cheryl's birthday, the day he knows must be +unique within the constraints we have so far. +

+ +
+ +
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).
+
+
+ +
+Results = [ (july, 16), (august, 15), (august, 17)].
+
+ +

+Both July and August contain the 14th, so that row is out. +

+ + + + +++ ++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
 JulyAugust
15 X
16X 
17 X
+
+
+ +
+

Albert's Second Statement

+
+
+

+Well, now I know, too! +

+
+ +

+Albert's month must be the remaining unique month: +

+ +
+ +
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).
+
+
+ +
+Results = [ (july, 16)].
+
+ +

+August had two possible days, so it's now clear that the only +possible unique answer is July 16th. +

+ + + + +++ ++ + + + + + + + + + + + + + + + + + + + + + + +
 July
15 
16X
17 
+
+
+ +
+

Cheryl's Birthday

+
+
+ +
cheryls_birthday(Month, Day) :-
+    part_three(Month, Day).
+
+
+ +
+Month = july,
+Day = 16.
+
+ +

+So, there we have it. Cheryl's birthday is July 16th! +

+ + + + +++ ++ + + + + + + + + + + + + +
 July
16X
+
+
+
diff --git a/_posts/2015-04-18-birthday-puzzle.org b/_posts/2015-04-18-birthday-puzzle.org new file mode 100644 index 0000000..983c9c7 --- /dev/null +++ b/_posts/2015-04-18-birthday-puzzle.org @@ -0,0 +1,203 @@ +#+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 |