Skip to content

Instantly share code, notes, and snippets.

@Cheesebaron
Last active August 29, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Cheesebaron/f813576f62dce8391c3b to your computer and use it in GitHub Desktop.
Save Cheesebaron/f813576f62dce8391c3b to your computer and use it in GitHub Desktop.
LINQPad script with a programmatic solution to the following logic puzzle. All credit goes to Peter Norvig's and his solution here: http://nbviewer.ipython.org/url/norvig.com/ipython/Cheryl.ipynb
// LINQPad script with a programatical solution to the following logic puzzle.
// All credit goes to Peter Norvig's and his solution here:
// http://nbviewer.ipython.org/url/norvig.com/ipython/Cheryl.ipynb
// 1. Albert and Bernard just became friends with Cheryl, and they want to know when her birtxhday is.
// Cheryl gave 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
//
// 2. Cheryl then tells Albert and Bernard separately the month and the day of the birthday respectively.
// 3. Albert: I don't know when Cheryl's birthday is, but I know that Bernard does not know too.
// 4. Bernard: At first I don't know when Cheryl's birthday is, but I know now.
// 5. Albert: Then I also know when Cheryl's birthday is.
// 6. So when is Cheryl's birthday?
/// <summary>
/// Dates given by Cheryl
/// </summary>
readonly string[] Dates =
{
"May 15", "May 16", "May 19",
"June 17", "June 18",
"July 14", "July 16",
"August 14", "August 15", "August 17"
};
/// <summary>
/// Accessor to get the month part from a date
/// </summary>
/// <param name="date">The string representation of a date</param>
/// <returns>
/// A <see cref="string" /> containing, the month part of the date
/// </returns>
string Month(string date)
{
var month = date.Split(' ');
return month[0];
}
/// <summary>
/// Accessor to get the day part from a Date
/// </summary>
/// <param name="date">The string representation of a Date</param>
/// <returns>The day part of the date</returns>
string Day(string date)
{
var month = date.Split(' ');
return month[1];
}
/// <summary>
/// Cheryl tells a part of her birthdate to someone
/// </summary>
/// <param name="part">The part Cheryl tells</param>
/// <param name="possibleDates">Possible dates</param>
/// <returns>
/// A new <see cref="IEnumerable{T}" /> of <see cref="string" />, containing all
/// possible dates that match the part
/// </returns>
IEnumerable<string> Tell(string part, IEnumerable<string> possibleDates = null)
{
if (possibleDates == null)
possibleDates = Dates;
return possibleDates.Where(x => x.Contains(part));
}
/// <summary>
/// A person knows the birthdate if they have exactly one possible date.
/// </summary>
/// <param name="possibleDates">
/// <see cref="IEnumerable{T}" /> of <see cref="string" />, containing
/// possible dates
/// </param>
/// <returns>
/// <value>true</value> if possible dates only contain exactly one date.
/// <value>false</value> if possible dates contain more than one date.
/// </returns>
bool Know(IEnumerable<string> possibleDates)
{
return possibleDates.Count() == 1;
}
/// <summary>
/// Return a list of the possible dates for which statements 3 to 5 are true.
/// </summary>
/// <param name="possibleDates">
/// <see cref="IEnumerable{T}" /> of <see cref="string" />, containing
/// possible dates
/// </param>
/// <returns>
/// <see cref="IEnumerable{T}" /> of <see cref="string" /> with all possible dates
/// for statements 3 to 5
/// </returns>
IEnumerable<string> CherylsBirthday(IEnumerable<string> possibleDates = null)
{
if (possibleDates == null)
possibleDates = Dates;
return possibleDates.Where(Statements3To5);
}
/// <summary>
/// Wrapper method around Statements 3 to 5 to check whether all statements
/// are true
/// </summary>
/// <param name="date">The date to check</param>
/// <returns>
/// <value>true</value> if statements 3 to 5 are true
/// <value>false</value> if any of the statements are false
/// </returns>
bool Statements3To5(string date)
{
return Statement3(date) && Statement4(date) && Statement5(date);
}
/// <summary>
/// Statement 3:
/// "Albert: I don't know when Cheryl's birthday is, but I know that Bernard
/// does not know too."
/// </summary>
/// <param name="date">The date to test the statement on</param>
/// <returns><value>true</value> if the statement is true</returns>
bool Statement3(string date)
{
var possibleDates = Tell(Month(date)).ToList();
return !Know(possibleDates) && possibleDates.All(x => !Know(Tell(Day(x))));
}
/// <summary>
/// Statement 4:
/// "Bernard: At first I don't know when Cheryl's birthday is, but I know now."
/// </summary>
/// <param name="date">The date to test the statement on</param>
/// <returns><value>true</value> if the statement is true</returns>
bool Statement4(string date)
{
var atFirst = Tell(Day(date)).ToList();
return !Know(atFirst) && Know(atFirst.Where(Statement3));
}
/// <summary>
/// Statement 5:
/// "Albert: Then I also know when Cheryl's birthday is."
/// </summary>
/// <param name="date">The date to test the statement on</param>
/// <returns><value>true</value> if the statement is true</returns>
bool Statement5(string date)
{
return Know(Tell(Month(date)).Where(Statement4));
}
void Main()
{
CherylsBirthday().Dump();
Know(CherylsBirthday()).Dump();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment