long_addition.sf 1.3 KB

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