Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Example:
- # B40 = HighBase.new(40, ([*"0".."9"]+[*"a".."z"]+[*"A".."Z"]).first(40))
- # a = B40.new 100 # => #<B40:0x1724b 2k (100 in base 40)>
- # b = B40.new '2k' # => #<B40:0x1728b 2k (100 in base 40)>
- # a.digits # => [2,20]
- # a.to_s # => "2k"
- class HighBase
- def self.new(base, characters)
- Class.new(Base) do
- eigenclass = class <<self; self; end
- eigenclass.instance_eval do
- define_method :base do
- base
- end
- define_method :characters do
- characters
- end
- end
- define_method :base do
- base
- end
- define_method :characters do
- characters
- end
- yield if block_given?
- end
- end
- class Base
- include Comparable
- attr_reader :number
- def self.from_string(string)
- number = string.split("").map { |c|
- characters.index(c)
- }.inject(0) { |num,digit|
- num*base+digit
- }
- new(number)
- end
- def self.new(number)
- String === number ? from_string(number) : super
- end
- def initialize(number)
- @number = number
- end
- %w[+ - * ** / % div quo].each { |name|
- sym_name = name.to_sym
- define_method(name) { |other|
- #printf "%p %s %p (%p)\n", self, name, other, (self.class === other ? other.instance_variable_get(:@number) : other)
- self.class.new(@number.__send__(sym_name, self.class === other ? other.instance_variable_get(:@number) : other))
- }
- }
- def coerce(other)
- self.class === other ? [other, self] : [self.class.new(other), self]
- end
- def <=>(other)
- @number <=> (self.class === other ? other.instance_variable_get(:@number) : other)
- end
- def digits
- rv = []
- rest = @number
- until rest < base
- rest, num = *rest.divmod(base)
- rv << num
- end
- rv << rest
- rv.reverse
- end
- def to_s
- digits.map { |digit| characters[digit,1] }.join("")
- end
- def inspect
- sprintf "#<%s:0x%x %s (%d in base %d)>",
- self.class,
- object_id >> 1,
- self,
- @number,
- base
- end
- end
- end
Add Comment
Please, Sign In to add comment