Guest User

Untitled

a guest
Jun 22nd, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.20 KB | None | 0 0
  1. # Example:
  2. # B40 = HighBase.new(40, ([*"0".."9"]+[*"a".."z"]+[*"A".."Z"]).first(40))
  3. # a = B40.new 100 # => #<B40:0x1724b 2k (100 in base 40)>
  4. # b = B40.new '2k' # => #<B40:0x1728b 2k (100 in base 40)>
  5. # a.digits # => [2,20]
  6. # a.to_s # => "2k"
  7. class HighBase
  8. def self.new(base, characters)
  9. Class.new(Base) do
  10. eigenclass = class <<self; self; end
  11.  
  12. eigenclass.instance_eval do
  13. define_method :base do
  14. base
  15. end
  16.  
  17. define_method :characters do
  18. characters
  19. end
  20. end
  21.  
  22. define_method :base do
  23. base
  24. end
  25.  
  26. define_method :characters do
  27. characters
  28. end
  29.  
  30. yield if block_given?
  31. end
  32. end
  33.  
  34. class Base
  35. include Comparable
  36.  
  37. attr_reader :number
  38.  
  39. def self.from_string(string)
  40. number = string.split("").map { |c|
  41. characters.index(c)
  42. }.inject(0) { |num,digit|
  43. num*base+digit
  44. }
  45.  
  46. new(number)
  47. end
  48.  
  49. def self.new(number)
  50. String === number ? from_string(number) : super
  51. end
  52.  
  53. def initialize(number)
  54. @number = number
  55. end
  56.  
  57. %w[+ - * ** / % div quo].each { |name|
  58. sym_name = name.to_sym
  59. define_method(name) { |other|
  60. #printf "%p %s %p (%p)\n", self, name, other, (self.class === other ? other.instance_variable_get(:@number) : other)
  61. self.class.new(@number.__send__(sym_name, self.class === other ? other.instance_variable_get(:@number) : other))
  62. }
  63. }
  64.  
  65. def coerce(other)
  66. self.class === other ? [other, self] : [self.class.new(other), self]
  67. end
  68.  
  69. def <=>(other)
  70. @number <=> (self.class === other ? other.instance_variable_get(:@number) : other)
  71. end
  72.  
  73. def digits
  74. rv = []
  75. rest = @number
  76. until rest < base
  77. rest, num = *rest.divmod(base)
  78. rv << num
  79. end
  80. rv << rest
  81. rv.reverse
  82. end
  83.  
  84. def to_s
  85. digits.map { |digit| characters[digit,1] }.join("")
  86. end
  87.  
  88. def inspect
  89. sprintf "#<%s:0x%x %s (%d in base %d)>",
  90. self.class,
  91. object_id >> 1,
  92. self,
  93. @number,
  94. base
  95. end
  96. end
  97. end
Add Comment
Please, Sign In to add comment