On Fri, Oct 10, 2008 at 10:13 AM, Matthew Moss <matt / moss.name> wrote: > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- > > The three rules of Ruby Quiz 2: > > 1. Please do not post any solutions or spoiler discussion for this > quiz until 48 hours have passed from the time on this message. > > 2. Support Ruby Quiz 2 by submitting ideas as often as you can! (A > permanent, new website is in the works for Ruby Quiz 2. Until then, > please visit the temporary website at > > <http://splatbang.com/rubyquiz/>. > > 3. Enjoy! > > Suggestion: A [QUIZ] in the subject of emails about the problem > helps everyone on Ruby Talk follow the discussion. Please reply to > the original quiz message, if you can. > > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- > > ## Modular Arithmetic (#179) > > _Quiz idea provided by Jakub Kua_ > > [Modular][1] [arithmetic][2] is integer-based arithmetic in which the > operands and results are constrained to a limited range, from zero to one > less than the modulus. Take, for example, the 24-hour clock. Hours on the > clock start at 0 and increase up to (and include) 23. But above that, we > must use the appropriate congruent value modulo 24. For example, if I wanted > to know what time it would be seven hours after 10pm, I would add 22 and 7 > to get 29. As that is outside the range `[0, 24)`, I take the congruent > value mod 24, which is 5. So seven hours after 10pm is 5am. > > Your task this week is to write a class `Modulo` that behaves in almost all > ways like an `Integer`. It should support all basic operations: addition, > subtraction, multiplication, exponentiation, conversion to string, etc. The > significant difference, of course, is that an instance of `Modulo` should > act modularly. > > For example: > > # The default modulus is 26. > > a = Modulo.new(15) > > b = Modulo.new(19) > > puts (a + b) > 8 > > puts (a - b) > 22 > > puts (b * 3) > 5 > > As noted in the example, you should use a modulus of 26 if none is specified > in the initializer. > > While most operations will be straightforward, modular division is a bit > trickier. [Here is one article][3] that explains how it can be done, but I > will leave division as extra credit. > > Enjoy this test file as you get started... > > require 'test/unit' > require 'modulo' > > class TestModulo < Test::Unit::TestCase > def test_modulo_equality > a = Modulo.new(23) > b = Modulo.new(23) > c = Modulo.new(179) > assert_equal(a, b) > assert_equal(a, c) > end > > def test_add_zero > a = Modulo.new(15) > b = Modulo.new(0) > assert_equal(a, a + b) > end > > def test_add > a = Modulo.new(15) > b = Modulo.new(19) > c = Modulo.new(8) > assert_equal(c, a + b) > end > > def test_add_int > a = Modulo.new(15) > c = Modulo.new(10) > assert_equal(c, a + 21) > end > > def test_sub > a = Modulo.new(15) > b = Modulo.new(19) > c = Modulo.new(22) > assert_equal(c, a - b) > end > > def test_sub_int > a = Modulo.new(15) > c = Modulo.new(1) > assert_equal(c, a - 66) > end > > def test_mul > a = Modulo.new(15) > b = Modulo.new(7) > c = Modulo.new(1) > assert_equal(c, a * b) > end > > def test_mul_int > a = Modulo.new(15) > c = Modulo.new(9) > assert_equal(c, a * 11) > end > > def test_mul_int_reverse > a = Modulo.new(15, 8) > assert_equal(77, 11 * a) > end > > def test_non_default_modulo > a = Modulo.new(15, 11) > b = Modulo.new(9, 11) > > assert_equal(2, a + b) > assert_equal(6, a - b) > assert_equal(3, a * b) > end > > def test_compare > assert_equal(1, Modulo.new(15) <=> Modulo.new(30)) > end > > def test_compare_int > assert_equal(-1, Modulo.new(15) <=> 35) > end > > def test_sort > x = [Modulo.new(15), Modulo.new(29), Modulo.new(-6), Modulo.new(57)] > y = [3, 5, 15, 20] > assert_equal(y, x.sort) > end > end Lazy, minimalistic version... class Modulo def initialize(v, b = 26); @v, @b = v % b, b; end def to_i; @v; end def == o; @v == o.to_i % @b; end def <=> o; @v <=> o.to_i; end [:+, :-, :*].each {|op| define_method(op) {|rh| instance_eval("Modulo.new((@v #{op} #{rh.to_i}) % @b)")}} end Error in test_mul_int_reverse, though. Todd