number2expression.sf 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #!/usr/bin/ruby
  2. # Author: Trizen
  3. # Date: 01 May 2022
  4. # https://github.com/trizen
  5. # Compress a number into a polynomial expression in a given base.
  6. func number2expr(n, base=10) {
  7. if (!n.is_int && n.is_rat) { # rational support
  8. var (nu, de) = n.nude
  9. return (__FUNC__(nu, base) / __FUNC__(de, base))
  10. }
  11. var D = n.digits(base).flip
  12. var t = D.len
  13. D.run_length.sum_2d {|d,l|
  14. t -= l
  15. (l == 1) ? d*Poly(t) : (((Poly(l) - 1)/(base-1) * d) * Poly(t))
  16. }
  17. }
  18. func number2expr_alt(n, base=10) { # returns: n * (base-1)
  19. if (!n.is_int && n.is_rat) { # rational support
  20. var (nu, de) = n.nude
  21. return (__FUNC__(nu, base) / __FUNC__(de, base) * (base-1))
  22. }
  23. var D = n.digits(base).flip
  24. var t = D.len
  25. D.run_length.sum_2d {|d,l|
  26. t -= l
  27. ((Poly(l) - 1) * d) * Poly(t)
  28. }
  29. }
  30. var tests = [
  31. [0b100000100000111111101, 2],
  32. [(7**911 - 4*(7**455) - 1), 7],
  33. [11113338888999999999, 10],
  34. [43/97, 10],
  35. ]
  36. for n,b in (tests) {
  37. say ("base #{'%2d'%b}: ", number2expr(n,b).pretty)
  38. say ("base #{'%2d'%b}: (", number2expr_alt(n,b).pretty, ")/#{b-1}")
  39. say ''
  40. assert_eq(number2expr(n,b) -> eval(b), n)
  41. assert_eq(number2expr_alt(n,b)/(b-1) -> eval(b), n)
  42. }
  43. __END__
  44. base 2: x^20 + x^14 + x^9 - x^2 + 1
  45. base 2: (x^21 - x^20 + x^15 - x^14 + x^9 - x^2 + x - 1)/1
  46. base 7: x^911 - x^456 + 3*x^455 - 1
  47. base 7: (6*x^911 - 4*x^456 + 4*x^455 - 6)/6
  48. base 10: 1/9*x^20 + 2/9*x^16 + 5/9*x^13 + 1/9*x^9 - 1
  49. base 10: (x^20 + 2*x^16 + 5*x^13 + x^9 - 9)/9
  50. base 10: (4*x + 3)/(9*x + 7)
  51. base 10: ((36*x^2 - 9*x - 27)/(9*x^2 - 2*x - 7))/9