Advertisement
Paul_Pedant

Ramanujan Awk Code

May 20th, 2020
2,327
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Awk 1.97 KB | None | 0 0
  1. #! /bin/bash
  2.  
  3. AWK='
  4. BEGIN { stderr = "cat 1>&2"; }
  5.    
  6. #.. Use binary search to find the largest b <= e, where b^3 < n.
  7. function bCbrt (n, e, Local, j, k, m) {
  8.  
  9.     j = 0; k = e;
  10.     while (j < k) {
  11.         m = int ((1 + j + k) / 2);
  12.         if (m * m * m < n) j = m; else k = m - 1;
  13.     }
  14.     for (++j; j * j * j > n; j--) { }
  15.     return ((j < e) ? j : e);
  16. }
  17.  
  18. #.. Run the overall algorithm.
  19. function Ramanujan (nb, ne, Local, n, v,
  20.             a, ab, ae, af, b, be, bf, c, d, de, tx, ty) {
  21.  
  22.     #.. Find the overall range for (a,b) pairs up to the limit.
  23.     ab = 1; ae = af = bCbrt( ne / 2, ne); bf = 1 + bCbrt( ne, ne);
  24.     printf ("nb = %s; ne = %s; ab = %s; af = %s; bf = %d\n",
  25.         nb, ne, ab, af, bf) | stderr;
  26.  
  27.     #.. Try all the numbers in ascending order.
  28.     for (n = nb; n <= ne; ++n) {
  29.         be = bCbrt( n, bf);
  30.  
  31.         #.. Run a from low to high.
  32.         for (a = ab; a <= ae; ++a) {
  33.  
  34.             #.. Run b from high to low, looking for an exact total.
  35.             for (b = be; b >= a; --b) {
  36.                 v = a * a * a + b * b * b;
  37.                 if (v <= n) break;
  38.             }
  39.             #.. If v went low, it is a new lower limit for b.
  40.             if (v < n || b < a) { be = b; continue; }
  41.  
  42.             #.. We have the first (a,b) for n, with small a and large b.
  43.             tx = sprintf ("%16d %d,%d", n, a, b); ty = "";
  44.  
  45.             #.. Squeeze the interval (a+1,b-1) for others.
  46.             be = de = b - 1;
  47.  
  48.             #.. Same logic to find any (c,d) intervals.
  49.             for (c = 1 + a; c <= ae; ++c) {
  50.                 for (d = de; d >= c; --d) {
  51.                     v = c * c * c + d * d * d;
  52.                     if (v <= n) break;
  53.                 }
  54.                 #.. If v went low, it is a new lower limit for d.
  55.                 if (v < n || d < c) { de = d; continue; }
  56.  
  57.                 #.. Found another (c,d) for same n.
  58.                 ty = sprintf ("%s; %d,%d", ty, c, d);
  59.  
  60.                 #.. Shrink interval.
  61.                 de = d - 1;
  62.             }
  63.             #.. Print if more than one pair found.
  64.             if (ty) print tx ty;
  65.  
  66.             #.. Avoid finding the (c,d) intervals again as (a,b).
  67.             break;
  68.         }
  69.     }
  70. }
  71.  
  72. { if ($1 <= $2) Ramanujan( $1, $2); else Ramanujan( $2, $1); }
  73. '
  74.     echo "${1:-100000}" "${2:-1}" | awk -f <( printf '%s\n' "${AWK}" )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement