user
Task

Solve the "*Impossible Puzzle*":

X and Y are two different whole numbers greater than 1. Their sum is no greater than 100, and Y is greater than X. S and P are two mathematicians (and consequently perfect logicians); S knows the sum X+Y and P knows the product X\*Y. Both S and P know all the information in this paragraph.

The following conversation occurs:

* S says "P does not know X and Y."
* P says "Now I know X and Y."
* S says "Now I also know X and Y!"

What are X and Y?

Guidance

It can be hard to wrap one's head around what the three lines of dialog between S (the "sum guy") and P (the "product guy") convey about the values of X and Y.  
So for your convenience, here's a break-down:

|  | Quote | Implied fact |
| --- | --- | --- |
| 1) | S says "P does not know X and Y." | For every possible sum decomposition of the number X+Y, the product has in turn *more than one* product decomposition. |
| 2) | P says "Now I know X and Y." | The number X\*Y has *only one* product decomposition for which fact 1 is true. |
| 3) | S says "Now I also know X and Y." | The number X+Y has *only one* sum decomposition for which fact 2 is true. |

Terminology:

* *"sum decomposition" of a number* = Any pair of positive integers (A, B) so that A+B equals the number. Here, with the additional constraint 2 ≤ A < B.
* *"product decomposition" of a number* = Any pair of positive integers (A, B) so that A\*B equals the number. Here, with the additional constraint 2 ≤ A < B.

Your program can solve the puzzle by considering all possible pairs (X, Y) in the range 2 ≤ X < Y ≤ 98, and then successively eliminating candidates based on the three facts. It turns out only one solution remains!  
See the Python example for an implementation that uses this approach with a few optimizations.

See also

* Wikipedia:   Sum and Product Puzzle

---
assistant
(formerly Perl 6)

**Translation of**: Python

**Works with**: Rakudo version 2016.07

```
sub grep-unique (&by, @list) { @list.classify(&by).values.grep(* == 1).map(*[0]) }
sub sums        ($n)         { ($_, $n - $_ for 2 .. $n div 2) }
sub product     ([$x, $y])   { $x * $y }
sub sum         ([$x, $y])   { $x + $y }

my @all-pairs = (|($_ X $_+1 .. 98) for 2..97);

# Fact 1:
my %p-unique := Set.new: map ~*, grep-unique &product, @all-pairs;
my @s-pairs = @all-pairs.grep: { none (%p-unique{~$_} for sums sum $_) };

# Fact 2:
my @p-pairs = grep-unique &product, @s-pairs;

# Fact 3:
my @final-pairs = grep-unique &sum, @p-pairs;

printf "X = %d, Y = %d\n", |$_ for @final-pairs;

```

Output:

```
X = 4, Y = 13
```