Guest User

!!스포주의!!

a guest
Dec 18th, 2021
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (() => {
  2.     const { floor, sqrt } = Math;
  3.  
  4.     function clamp(min, n, max) {
  5.         return Math.max(min, Math.min(max, n));
  6.     }
  7.  
  8.     function inRange(min, n, max) {
  9.         return clamp(min, n, max) === n;
  10.     }
  11.  
  12.     function range(start, end) {
  13.         return start > end ? [] : Array.from(new Array(end - start + 1)).map((_unused, i) => i + start);
  14.     }
  15.  
  16.     function isDivisible(n, by) {
  17.         return floor(n / by) * by === n;
  18.     }
  19.  
  20.     const RANGE_MIN = 2;
  21.     const RANGE_MAX = 50;
  22.  
  23.     const SUM_MIN = RANGE_MIN + (RANGE_MIN + 1);
  24.     const SUM_MAX = RANGE_MAX + (RANGE_MAX - 1);
  25.     const MUL_MIN = RANGE_MIN * (RANGE_MIN + 1);
  26.     const MUL_MAX = RANGE_MAX * (RANGE_MAX - 1);
  27.  
  28.     function possibleSetWhenSum(sum) {
  29.         return range(RANGE_MIN, floor(clamp(SUM_MIN, sum, SUM_MAX) / 2))
  30.             .map((i) => [i, sum - i])
  31.             .filter(([n, m]) => n < m && inRange(RANGE_MIN, n, RANGE_MAX) && inRange(RANGE_MIN, m, RANGE_MAX));
  32.     }
  33.  
  34.     function possibleSetWhenMul(mul) {
  35.         return range(floor(sqrt(MUL_MIN)), floor(sqrt(clamp(MUL_MIN, mul, MUL_MAX))))
  36.             .filter((i) => isDivisible(mul, i))
  37.             .map((i) => [i, mul / i])
  38.             .filter(([n, m]) => n < m && inRange(RANGE_MIN, n, RANGE_MAX) && inRange(RANGE_MIN, m, RANGE_MAX));
  39.     }
  40.  
  41.     function possibleSumWhenMul(mul) {
  42.         return possibleSetWhenMul(mul).map(([n, m]) => n + m);
  43.     }
  44.  
  45.     function possibleMulWhenSum(sum) {
  46.         return possibleSetWhenSum(sum).map(([n, m]) => n * m);
  47.     }
  48.  
  49.     function isTrivialSum(sum, mulWhitelist = possibleMulWhenSum(sum)) {
  50.         return possibleSetWhenSum(sum)
  51.             .filter(([n, m]) => mulWhitelist.includes(n * m))
  52.             .length <= 1;
  53.     }
  54.  
  55.     function isTrivialMul(mul, sumWhitelist = possibleSumWhenMul(mul)) {
  56.         return possibleSetWhenMul(mul)
  57.             .filter(([n, m]) => sumWhitelist.includes(n + m))
  58.             .length <= 1;
  59.     }
  60.  
  61.     function solution() {
  62.         // S가 아는 두 수의 합 후보
  63.         const possibleSum =
  64.             // 합으로 주어질 수 있는 모든 수 중에
  65.             range(SUM_MIN, SUM_MAX)
  66.             .filter((sum) => {
  67.                 // S는 정답을 모르므로 우선 S가 답을 아는 경우 제외
  68.                 if (isTrivialSum(sum)) return false;
  69.                 // 합이 sum일 때 P가 아는 수 후보
  70.                 const possibleMul = possibleMulWhenSum(sum);
  71.                 // 그 중 하나의 경우라도 P가 답을 알 수 있다면
  72.                 const PMightKnow = possibleMul.some((mul) => isTrivialMul(mul));
  73.                 // S는 P가 답을 모른다는 것을 알 수 없었을 것임
  74.                 return !PMightKnow;
  75.             });
  76.         // P가 아는 두 수의 곱 후보
  77.         const possibleMul =
  78.             // P가 합이 possibleSum 중 하나라는 것을 알아도 정답을 모르려면
  79.             possibleSum.map(possibleMulWhenSum).flat(1) // 가능한 모든 곱
  80.             .sort().filter((_unused, i, a) => a[i] != a[i - 1]) // 중복 제거
  81.             // 하지만 P는 S가 정답을 모른다는 것을 알고 있음
  82.             .filter((mul) => !isTrivialMul(mul, possibleSum));
  83.         // S가 예상할 수 있는, P가 아는 가능한 정답 후보
  84.         const possibleSet =
  85.             possibleMul.map(possibleSetWhenMul).flat(1) // 가능한 모든 경우
  86.             .filter(([n, m]) => possibleSum.includes(n + m)); // 아닌 경우 제거
  87.         // 실제로 S가 아는 두 수의 합
  88.         const realSum =
  89.             possibleSum // S가 아는 두 수의 합 후보 중에서
  90.             .filter((sum) => // S가 정답을 알겠다고 했으니 가능한 경우가 1개여야 함
  91.                 possibleSet.filter(([n, m]) => n + m == sum).length === 1
  92.             );
  93.         if (realSum.length !== 1) throw new Error('문제 에러 아님???');
  94.         return possibleSet.filter(([n, m]) => n + m == realSum[0])[0];
  95.     }
  96.  
  97.     return solution();
  98. })()
Advertisement
Add Comment
Please, Sign In to add comment