|
| 1 | +#!/usr/bin/ruby |
| 2 | + |
| 3 | +# Daniel "Trizen" Șuteu |
| 4 | +# Date: 22 December 2017 |
| 5 | +# https://github.com/trizen |
| 6 | + |
| 7 | +# A simple long addition algorithm to sum two arbitrary large string-numbers in any base. |
| 8 | + |
| 9 | +func long_addition(String a, String b, Number base=10) { |
| 10 | + |
| 11 | + a = a.flip.chars.map { Num(_, base) } |
| 12 | + b = b.flip.chars.map { Num(_, base) } |
| 13 | + |
| 14 | + (a.any { .is_nan } || b.any { .is_nan }) && return nil |
| 15 | + |
| 16 | + var l = (a.len `max` b.len) |
| 17 | + var c = l.of(0) |
| 18 | + |
| 19 | + a += (l - a.len -> of(0)) |
| 20 | + b += (l - b.len -> of(0)) |
| 21 | + |
| 22 | + for i in (0 ..^ l) { |
| 23 | + |
| 24 | + c[i] += (a[i] + b[i]) |
| 25 | + |
| 26 | + if (c[i] >= base) { |
| 27 | + c[i+1, i] = c[i].divmod(base) |
| 28 | + } |
| 29 | + } |
| 30 | + |
| 31 | + return c.map { .base(base) }.join.flip |
| 32 | +} |
| 33 | + |
| 34 | +var a = "37107287533902102798797998220837590246510135740250" |
| 35 | +var b = "36546866040552898237115466322123187317060305120" |
| 36 | + |
| 37 | +say long_addition(a, b) |
| 38 | + |
| 39 | +# Test for base 10 |
| 40 | +assert_eq(Num(a) + Num(b), Num(long_addition(a, b))) |
| 41 | + |
| 42 | +# Test for base 36 |
| 43 | +var alphanum = [('a'..'z')..., (0..9)...].shuffle |
| 44 | +var (c, d) = 2.of { 100.irand(1).of { alphanum.pick }.join.sub(/^0/, '1') }... |
| 45 | +assert_eq(Num(c, 36) + Num(d, 36) -> base(36), long_addition(c, d, 36)) |
| 46 | + |
| 47 | +# Test for base 2 |
| 48 | +var (e, f) = 2.of { 100.irand(1).of { ['0', '1'].pick }.join.sub(/^0/, '1') }... |
| 49 | +assert_eq(Num(e, 2) + Num(f, 2) -> base(2), long_addition(e, f, 2)) |
0 commit comments