Skip to content

Instantly share code, notes, and snippets.

@havenwood
Created December 2, 2024 16:52
Show Gist options
  • Save havenwood/e7dac3aff1ed73b0c90683813e9387f8 to your computer and use it in GitHub Desktop.
Save havenwood/e7dac3aff1ed73b0c90683813e9387f8 to your computer and use it in GitHub Desktop.
A Ruby implementation of Integer#each_digit
class Integer
def each_digit(base = 10, &block)
raise Math::DomainError, 'out of domain' if negative?
raise TypeError, "wrong argument type #{base.class} (expected Integer)" unless base.respond_to?(:to_int)
radix = base.to_int
raise ArgumentError, 'negative radix' if radix.negative?
raise ArgumentError, "invalid radix #{radix}" if radix < 2
return enum_for(__method__, base) unless block_given?
div = self
until div.zero?
div, mod = div.divmod(radix)
block.call(mod)
end
end
end
require 'minitest/autorun'
require 'minitest/pride'
class TestEachDigit < Minitest::Test
def test_without_block
enum = 42.each_digit
assert_kind_of Enumerator, enum
assert_equal [2, 4], enum.to_a
end
def test_base_without_block
assert_equal [0, 1, 0, 1, 0, 1], 42.each_digit(2).to_a
assert_equal [2, 5], 42.each_digit(8).to_a
assert_equal [10, 2], 42.each_digit(16).to_a
assert_equal [0, 17, 2], 4242.each_digit(42).to_a
end
def test_with_block
result = []
42.each_digit { |digit| result << digit * 2 }
assert_equal [4, 8], result
end
def test_base_with_block
result = []
42.each_digit(2) { |digit| result << digit + 1 }
assert_equal [1, 2, 1, 2, 1, 2], result
end
def test_negative_value
e = assert_raises(Math::DomainError) { -42.each_digit }
assert_equal 'out of domain', e.message
end
def test_non_integer_base
e = assert_raises(TypeError) { 42.each_digit(:x) }
assert_equal 'wrong argument type Symbol (expected Integer)', e.message
end
def test_negative_radix
e = assert_raises(ArgumentError) { 42.each_digit(-2) }
assert_equal 'negative radix', e.message
end
def test_invalid_radix0
e = assert_raises(ArgumentError) { 42.each_digit(0) }
assert_equal 'invalid radix 0', e.message
end
def test_invalid_radix1
e = assert_raises(ArgumentError) { 42.each_digit(1) }
assert_equal 'invalid radix 1', e.message
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment