Oliver Roeder posed this great riddle on fivethiryeight.

Three very skilled logicians are sitting around a table — Barack, Pete and Susan. Barack says: “I’m thinking of two natural numbers between 1 and 9, inclusive. I’ve written the product of these two numbers on this paper that I’m giving to you, Pete. I’ve written the sum of the two numbers on this paper that I’m giving to you, Susan. Now Pete, looking at your paper, do you know which numbers I’m thinking of?”

Pete looks at his paper and says: “No, I don’t.”

Barack turns to Susan and asks: “Susan, do you know which numbers I’m thinking of?” Susan looks at her paper and says: “No.”

Barack turns back to Pete and asks: “How about now? Do you know?”

“No, I still don’t,” Pete says.

Barack keeps going back and forth, and when he asks Pete for the fifth time, Pete says: “Yes, now I know!”

First, what are the two numbers? Second, if Pete had said no the fifth time, would Susan have said yes or no at her fifth turn?

Let’s solve it with code.

List the possible combinations.

For example the numbers might be 2 and 3. Order doesn’t matter so don’t list 3 and 2 if 2 and 3 is listed.

library(dplyr)

data <- data.frame(
  a = rep(1:9, 9),
  b = rep(1:9, each=9)
) %>%
  filter(a <= b)

# preview
print(head(data))
 a b
 1 1
 1 2
 2 2
 1 3
 2 3
 3 3

Simulate the “I don’t know rounds”.

During the first four rounds Pete and Susan don’t know the numbers. This can only happen if the numbers don’t have unique sums or products.

For example one possibility is that the numbers are 1 and 3. But after the first round we know that is impossible because Pete has said he doesn’t know the answer. If the numbers were 1 and 3 then the product would 3 and Pete would know the answer because there is no other pair with the product 3.

After each round we eliminate the unique sums and products until all four initial rounds are complete.

is_unique <- function(x) !(duplicated(x) | duplicated(x, fromLast=TRUE))
# e.g. is_unique(c(1, 1, 2)) == c(FALSE, FALSE, TRUE)

data <- data %>%
  mutate(
    product = a * b,
    sum = a + b
  ) %>%
  
  # round 1
  # pete
  filter(!is_unique(product)) %>% 
  # susan
  filter(!is_unique(sum)) %>% 
  
  # round 2 
  # pete
  filter(!is_unique(product)) %>% 
  # susan
  filter(!is_unique(sum)) %>% 
  
  # round 3 
  # pete
  filter(!is_unique(product)) %>% 
  # susan
  filter(!is_unique(sum)) %>% 
  
  # round 4
  # pete
  filter(!is_unique(product)) %>% 
  # susan
  filter(!is_unique(sum))

After these rounds we are left with the following possible numbers:

print(data)
 a b product sum
 3 3       9   6
 2 4       8   6
 3 6      18   9
 4 6      24  10
 1 8       8   9
 2 8      16  10
 3 8      24  11
 1 9       9  10
 2 9      18  11

If Pete knows, the answer is 2 and 8.

data %>%
  filter(is_unique(product)) %>%
  print
 a b product sum
 2 8      16  10

If Pete doesn’t know, Susan won’t either.

If Pete says “I don’t know” after 5 rounds. Susan will say I don’t know too because none of the remaining possible sums is unique. In fact no more progress can be made because none of the sums or products are unique any more.

data %>%
  filter(!is_unique(product)) %>%
  mutate(
    unique_sum = is_unique(sum),
    unique_product = is_unique(product)) %>%
  print
 a b product sum unique_sum unique_product
 3 3       9   6      FALSE          FALSE
 2 4       8   6      FALSE          FALSE
 3 6      18   9      FALSE          FALSE
 4 6      24  10      FALSE          FALSE
 1 8       8   9      FALSE          FALSE
 3 8      24  11      FALSE          FALSE
 1 9       9  10      FALSE          FALSE
 2 9      18  11      FALSE          FALSE