Advertisement
Guest User

Untitled

a guest
Sep 26th, 2017
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.54 KB | None | 0 0
  1. /*
  2. Dutch mathematician Hans Freudenthal proposed this puzzle in 1969 — at first it appears impossible because so little information is given.
  3.  
  4. X and Y are two different whole numbers greater than 1. Y is greater than X, and their sum is no greater than 100. S and P are two logicians; S knows the sum X + Y, and P knows the product X × Y. S and P both reason perfectly, and both know everything I’ve just told you.
  5.  
  6. S says, “P does not know X and Y.”
  7. P says, “Now I know X and Y.”
  8. S says, “Now I also know X and Y.”
  9. What are X and Y?
  10. */
  11.  
  12. const objMap = (obj, fn) => (
  13. Object.entries(obj).map(([key, val]) => [key, fn(val, key)]).reduce((o, r) => (o[r[0]] = r[1], o), {})
  14. );
  15.  
  16. const objFilter = (obj, fn) => (
  17. Object.entries(obj).filter(([key, val]) => fn(val, key)).reduce((o, r) => (o[r[0]] = r[1], o), {})
  18. );
  19.  
  20. const keyedBy = (list, key) => (
  21. list.reduce((r, o) => (r[key(o)] = r[key(o)] || [], r[key(o)].push(o), r), {})
  22. );
  23.  
  24.  
  25. const numbers = [...Array(99).entries()].map(x => x[0]+2);
  26.  
  27. const possible = Array.prototype.concat.apply([], numbers.map(x => numbers.map(y => ({x, y, p:x*y, s:x+y})))).filter(({x, y, p, s}) => (x<y && s<101));
  28.  
  29. // const keyedBySum = possible.reduce((r, {a, b, p, s}) => (r[s] = r[s] || [], r[s].push({a, b, p, s}), r), {})
  30. const keyedBySum = keyedBy(possible, ({s}) => s);
  31.  
  32. // const keyedByProduct = possible.reduce((r, {a, b, p, s}) => (r[p] = r[p] || [], r[p].push({a, b, p, s}), r), {})
  33. const keyedByProduct = keyedBy(possible, ({p}) => p);
  34.  
  35.  
  36.  
  37. // Track S's possible knowledge for statement 1: [S says, “P does not know X and Y.”]
  38. // Initialise to all possibilities, keyed by sum.
  39. const sKnowledge0 = keyedBySum;
  40. // Map each possibility to a list of other possibilities with the same product.
  41. // (
  42. // So possible sum 11 has [[2,9], [3,8], [4,7], [5,6]] which gets mapped to
  43. // products: [[18], [24], [28], [30]] which gets mapped to
  44. // possibilities: [[2:9, 3:6], [2:12, 3:8, 4:6], [2:14, 4:7], [2:15, 3:10, 5:6]]
  45. // So all of these products have multiple possible x, y so if S sees 11 he can say P doesn't know.
  46. // )
  47. const sKnowledge1 = objMap(keyedBySum, (list) => list.map(({p}) => keyedByProduct[p]));
  48.  
  49. // Filter out sums that contain potential x,y pairs that would be identifiable by P
  50. const sKnowledge2 = objFilter(sKnowledge1, (l) => l.every((l2) => l2.length > 1));
  51.  
  52. // -- sKnowledge2 is the possible sums that S could see for statement 1 to be true. --
  53.  
  54.  
  55. // Track P's possible knowledge for statement 2: [P says, “Now I know X and Y.”]
  56. // Initialise to all possibilities keyed by product.
  57. const pKnowledge0 = keyedByProduct;
  58. // We know from statement 1 that P doesn't know X and Y, so filter out products that only have one factorisation
  59. const pKnowledge1 = objFilter(keyedByProduct, (list) => list.length > 1);
  60. // Now apply statement 2. P gains sKnowledge2's list of possible sums.
  61. // Knowing that the sum is in sKnowledge2 means that P now knows X, Y.
  62. // Filter out possibilities that don't have a sum in sKnowledge2
  63. const pKnowledge2 = objMap(pKnowledge1, (list) => list.filter(({s}) => sKnowledge2[s]));
  64.  
  65. // Now filter out products that don't have exactly 1 set of possibilities left
  66. const pKnowledge3 = objFilter(pKnowledge2, (list) => list.length ===1);
  67.  
  68. // -- pKnowledge3 now contains the possible products that satisfy statement 2 --
  69.  
  70. // Track S's possible knowledge for statement 3: [S says, “Now I also know X and Y.”]
  71. // S's knowledge from before says that the possible sums are in sKnowledge2.
  72. // Now that S gains the knowledge of pKnowledge3, S knows the possible products
  73. // that P could have seen. This gives S knowledge of x,y.
  74. // That means that whatever sum S saw must have only one potential product in pKnowledge3.
  75. // sKnowledge2 is currently keyed by sum, giving an array of products. each product gives possibilities.
  76. // Lets clean up to get the second level keyed by product.
  77. // First explode children
  78. const sKnowledge3 = objMap(sKnowledge2, (list) => Array.prototype.concat.apply([], list));
  79. // Strip out possibilities that don't have the matching sum
  80. const sKnowledge4 = objMap(sKnowledge3, (list, sum) => list.filter(({s}) => s == sum));
  81.  
  82. // Now we are ready to filter out products that aren't in pKnowledge3
  83. const sKnowledge5 = objMap(sKnowledge4, (list) => list.filter(({p}) => pKnowledge3[p]));
  84.  
  85. // And finally, we filter out sums that now have only a single possiblity in order to make
  86. // statement 3 true.
  87. const sKnowledge6 = objFilter(sKnowledge5, (list) => list.length === 1);
  88.  
  89. // Which leaves us with "{"17":[{"a":4,"b":13,"p":52,"s":17}]}"
  90. // X is 4, Y is 13. P saw 52, S saw 17.
  91.  
  92. console.log(Object.values(sKnowledge6)[0][0]);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement