GOPHERSPACE.DE - P H O X Y
gophering on sdf.org
Sum And Product Puzzle
======================
Knowing something just because someone says you don't. Isn't it amazing?
Two mathematicians are playing a game. P know the product of twdifferent 
numbers both greater than 1 whose sum is no greater than 100. S knows 
their sum.
S says: P does not know the numbers.
P says: Now I know.
S says: Now I also know the numbers.
Well, what are the numbers?

How to solve?
Here's a little Python script that solves the puzzle
# First step: create a dictionary of pairs grouped by their product

possiblePairsByProduct = {}

for i in range(2,50):
  for j in range(i+1, 101-i):
    if i==j:
      continue
    p=i*j
    if p not in possiblePairsByProduct:
      possiblePairsByProduct[p]={(i,j)}
    else:
      possiblePairsByProduct[p].add((i,j))

# S says that P doesn't know the numbers.

# Second step: remove products that has 1 pair of factors only

countPairsBySum = {}

for i in possiblePairsByProduct.keys():
  if len(possiblePairsByProduct[i])==1:
    possiblePairsByProduct.pop(i)


# Third step: create sums from the pairs in possiblePairsByProduct
for curSet in possiblePairsByProduct.values():
  for pair in curSet:
    sum = pair[0]+pair[1]
    if sum not in countPairsBySum:
      countPairsBySum[sum]=1
    else:
      countPairsBySum[sum]+=1

# Check from which of the sum S can tell that P
#   does not know the two numbers
for i in countPairsBySum.keys():
  if i % 2:
    results = i/2 - 1
  else:
    results = i/2 - 2
  if countPairsBySum[i]!=results:
    countPairsBySum.pop(i)

# Get  products for whose pairs only one sum exists,
#  and vice versa
pairsBySum={}

for i in possiblePairsByProduct.keys():
  curSet=possiblePairsByProduct[i]
  curSum = None
  productRemoved=False
  for pair in curSet.copy():
    sum =pair[0]+pair[1]
    if sum in countPairsBySum:
      if curSum:
        if not productRemoved:
          possiblePairsByProduct.pop(i)
          productRemoved=True
      else:
        curSum=sum
    else:
      curSet.remove(pair)
  if not curSum:
    possiblePairsByProduct.pop(i)
    productRemoved=True
  if not productRemoved:
    if curSum not in pairsBySum:
      pairsBySum[curSum]=curSet.copy()
    else:
      pairsBySum[curSum].update(curSet)

# There's only one sum for which there's one pair.
for sum in pairsBySum:
  if len(pairsBySum[sum])==1:
    print pairsBySum[sum]

This will print:
set([(4, 13)])