Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add modes when unary chars

  • Loading branch information...
commit 9d03a04923c1241492fe767950b2e31c9d98e2c0 1 parent ccf7cc6
@kachick authored
Showing with 130 additions and 55 deletions.
  1. +90 −50 lib/integer/base/eigen.rb
  2. +40 −5 test/test_integer-base.rb
View
140 lib/integer/base/eigen.rb
@@ -8,69 +8,58 @@ class << self
# @param [Array<#to_sym>] chars
# @return [Integer]
def parse(str, chars)
- chars = base_chars_for chars
str = str.to_str.downcase
+
+ sign = parse_sign! str
+ abs = (
+ case chars.length
+ when 1
+ parse_unary_abs str, chars.first
+ else
+ parse_positional_abs str, chars
+ end
+ )
- sign = parse_sign! str
-
- case chars.length
- when 1
- parse_unary_abs str, chars.first
- else
- trim_paddings! str, chars.first
-
- abs = parse_abs str, chars
-
- (sign == :-) ? -abs : abs
- end
- end
-
- def parse_unary_abs(str, char)
- chars = str.chars
- p chars.to_a
- atom = chars.to_a.uniq.first.to_sym
-
- raise InvalidCharacter, 'contain multiple chars' unless atom.length == 1
- raise InvalidCharacter, 'not match the char and atom' unless atom == char
-
- chars.length
+ (sign == :-) ? -abs : abs
end
# @param [#to_int] num
# @param [Array<#to_sym>] chars
# @return [String]
def convert_to_string(num, chars)
- chars = base_chars_for chars
- int = num.to_int
- base = chars.length
-
- return chars.first.to_s if int == 0
+ case chars.length
+ when 1
+ convert_to_string_unary num, chars.first
+ else
+ convert_to_string_positional num, chars
+ end
+ end
- ''.tap {|s|
- n = int.abs
+ private
- until (n, excess = n.divmod base; n == 0 && excess == 0)
- s << chars[excess].to_s
- end
-
- s.reverse!
- s.insert 0, '-' if int < 0
- }
- end
+ # @return [Symbol]
+ def parse_sign!(str)
+ sign = str.slice!(/\A([-+])/, 1)
- def convert_unary(num, char)
+ if sign
+ if str.empty?
+ raise InvalidCharacter
+ else
+ sign.to_sym
+ end
+ else
+ :+
+ end
end
- private
-
# @param [Array<#to_sym>] chars
# @return [Array<Symbol>]
def base_chars_for(chars)
chars = chars.map{|c|c.downcase.to_sym}
case
- when chars.length < 1
- raise TypeError, 'use 2 and more characters'
+ when chars.length < 2
+ raise TypeError, 'use 2 or more than characters'
when chars.dup.uniq!
raise InvalidCharacter, 'dupulicated characters'
when chars.any?{|s|s.length != 1}
@@ -81,20 +70,26 @@ def base_chars_for(chars)
chars
end
end
-
+
# @return [Symbol]
- def parse_sign!(str)
- sign = str.slice!(/\A([-+])/, 1)
- sign ? sign.to_sym : :+
+ def unary_char_for(char)
+ raise InvalidCharacter unless (char.length == 1) and char.respond_to?(:to_sym)
+
+ char.to_sym
end
- def trim_paddings!(str, pad_char)
+ def trim_positional_paddings!(str, pad_char)
str.slice!(/\A#{pad_char}+/)
end
# @return [Integer]
- def parse_abs(str, chars)
+ def parse_positional_abs(str, chars)
+ raise InvalidCharacter if str.empty?
base = chars.length
+ chars = base_chars_for chars
+
+ str = str.dup
+ trim_positional_paddings! str, chars.first
str.chars.reverse_each.with_index.inject(0) {|sum, char_index|
char, index = *char_index
@@ -106,6 +101,51 @@ def parse_abs(str, chars)
end
}
end
+
+ # @return [Integer]
+ def parse_unary_abs(str, char)
+ char = unary_char_for char
+ return 0 if str.empty?
+
+ chars = str.chars.to_a
+ atoms = chars.uniq
+ raise InvalidCharacter, 'contain multiple chars' unless atoms.length == 1
+
+ atom = atoms.first.to_sym
+ raise InvalidCharacter, 'not match the char and atom' unless atom == char
+
+ chars.length
+ end
+
+ # @return [String]
+ def convert_to_string_positional(num, chars)
+ chars = base_chars_for chars
+ int = num.to_int
+ base = chars.length
+
+ return chars.first.to_s if int == 0
+
+ ''.tap {|s|
+ n = int.abs
+
+ until (n, excess = n.divmod base; n == 0 && excess == 0)
+ s << chars[excess].to_s
+ end
+
+ s.reverse!
+ s.insert 0, '-' if int < 0
+ }
+ end
+
+ # @return [String]
+ def convert_to_string_unary(num, char)
+ char = unary_char_for char
+ int = num.to_int
+
+ (char.to_s * int.abs).tap {|s|
+ s.insert 0, '-' if int < 0
+ }
+ end
end
View
45 test/test_integer-base.rb
@@ -5,6 +5,14 @@ class TestIntegerBase < Test::Unit::TestCase
def test_parse
assert_equal(1, '0a'.to_i(['0', *'A'..'I']))
+ assert_equal(0, ''.to_i(['0']))
+ assert_equal(1, '0'.to_i(['0']))
+ assert_equal(2, '00'.to_i(['0']))
+
+ assert_raises Integer::Base::InvalidCharacter do
+ '01'.to_i(['0'])
+ end
+
assert_raises Integer::Base::InvalidCharacter do
'9a'.to_i(['0', *'A'..'I'])
end
@@ -43,10 +51,10 @@ def test_parse
def test_characterable
assert_raises Integer::Base::InvalidCharacter do
- '210'.to_i('1'..'2')
+ '210'.to_i(('1'..'2').to_a)
end
- assert_equal(21, '210'.to_i('0'..'2'))
+ assert_equal(21, '210'.to_i(('0'..'2').to_a))
end
def test_to_s
@@ -59,25 +67,52 @@ def test_to_s
assert_equal('101', 5.to_s(%w[0 1]))
assert_equal('-aib', -192.to_s(['0', *'A'..'I']))
- assert_equal('0', 0.to_s(%w[0 1]))
assert_equal('-1', -1.to_s(%w[0 1]))
assert_equal('-10', -2.to_s(%w[0 1]))
assert_equal('-11', -3.to_s(%w[0 1]))
assert_equal('-100', -4.to_s(%w[0 1]))
assert_equal('-101', -5.to_s(%w[0 1]))
+
+ assert_equal('0' * 192, 192.to_s(['0']))
+ assert_equal('', 0.to_s(['0']))
+ assert_equal('0', 1.to_s(['0']))
+ assert_equal('00', 2.to_s(['0']))
+ assert_equal('000', 3.to_s(['0']))
+
+ assert_equal("-#{'0' * 192}", -192.to_s(['0']))
+ assert_equal('-0', -1.to_s(['0']))
+ assert_equal('-00', -2.to_s(['0']))
+ assert_equal('-000', -3.to_s(['0']))
+
end
def test_binary
assert_equal 2, Integer::Base.parse('10', %w[0 1])
end
- def test_standards
+ def test_standards_to_i
+ assert_raises Integer::Base::InvalidCharacter do
+ Integer::Base.parse('', Integer::Base::STANDARD_CHARS[2])
+ end
+
assert_equal(0, Integer::Base.parse('', Integer::Base::STANDARD_CHARS[1]))
assert_raises Integer::Base::InvalidCharacter do
- Integer::Base.parse('', Integer::Base::STANDARD_CHARS[2])
+ Integer::Base.parse('-', Integer::Base::STANDARD_CHARS[2])
end
+ assert_raises Integer::Base::InvalidCharacter do
+ Integer::Base.parse('-', Integer::Base::STANDARD_CHARS[1])
+ end
+
+ assert_raises Integer::Base::InvalidCharacter do
+ Integer::Base.parse('+', Integer::Base::STANDARD_CHARS[2])
+ end
+
+ assert_raises Integer::Base::InvalidCharacter do
+ Integer::Base.parse('+', Integer::Base::STANDARD_CHARS[1])
+ end
+
assert_equal(1, Integer::Base.parse('0', Integer::Base::STANDARD_CHARS[1]))
assert_equal(2, Integer::Base.parse('00', Integer::Base::STANDARD_CHARS[1]))
assert_equal('11'.to_i(2), Integer::Base.parse('11', Integer::Base::STANDARD_CHARS[2]))
Please sign in to comment.
Something went wrong with that request. Please try again.