1

Please do not suggest using any gems or creating classes for unsigned integers.

Input data - strings that represent 4 byte sequence. Output data should be the same type of string.

This is what I've got so far:

def addition(augend, addend)
    sum = augend.to_i(16)+addend.to_i(16)
    sum -= 2**32 if sum >= 2**32
    sum = "%08X" % sum
    return(sum)
end

def subtraction(minuend, subtrahend)
    difference = 0

    # Some magic here.

    difference = "%08X" % difference
    return(difference)
end

puts addition('FFFFFFFF', '00000002')       # 00000001
puts addition('B1B0AFBA', 'FEEE302D')       # B09EDFE7

puts subtraction('00000055', '00000005')    # 00000000, expected 00000050
puts subtraction('B1B0AFBA', 'FEEE302D')    # 00000000, expected B2C27F8D

How should subtraction() be implemented? And could addition() be improved?

MOPO3OB
  • 383
  • 3
  • 16
  • "Please do not suggest using any gems or creating classes for unsigned integers." – Why? Not re-inventing the wheel is one of the most basic skills of any good programmer. And Ruby is an OO language, you cannot do *anything* without using objects, and classes are the way to create objects. You ask about improving `addition`, and the most important improvement I can see, would be to make it a method of an appropriate object. – Jörg W Mittag Mar 23 '18 at 00:19
  • @JörgWMittag agree, although re-inventing bicycle might be a valuable experience in some cases. I asked not to suggest using objects or gems for 2 reasons. First, to help anyone who will be seeking an algorithm for this (say for Lua, which got no support for objects). Second, I personally need to do such calculation only once, so using gem or objects would be irrational in my case. – MOPO3OB Mar 23 '18 at 00:35

1 Answers1

0

Basically just do opposite of addition. Also in ruby last line of method is returned and no need to reassign variable on last line since it's eval will be returned.

def subtraction(minuend, subtrahend)
  difference = minuend.to_i(16) - subtrahend.to_i(16)
  difference += 2**32 if difference < 0
  "%08X" % difference
end

Performance seems fine:

puts Benchmark.measure{ 1000.times {subtraction('B1B0AFBA', 'FEEE302D')} }
#=>  0.010000   0.000000   0.010000 (  0.001853)

Since these methods are only different by 3 characters I thought, "why not try some meta programming to dry it up?":

subber = lambda {|str, a, b, c| str.gsub('A', a).gsub('B', b).gsub('C', c)}

meth_def = <<EOF
  n = arg1.to_i(16) A arg2.to_i(16)
  n B= 2**32 if n C= 2**32
  "%08X" % n
EOF

define_method(:addition){|arg1, arg2| eval subber.call(meth_def, '+','-', '>')}
define_method(:subtraction){|arg1, arg2| eval subber.call(meth_def, '-','+', '<')}

This could probably be DRYed up more but you get the idea.

lacostenycoder
  • 10,623
  • 4
  • 31
  • 48
  • 1
    Thank you for the answer! I'm aware of that using `return()` is unnecessary, that's just my style of organazing code. Very interesting idea of using meta programming here. But I'm afraid that `subtraction()` doesn't work correctly, not yet. Also could you please rename variables used in `subtraction()` method to those names given in the question. And one more question: is there a way to make lines `2` and `3` in the method more compact? – MOPO3OB Mar 22 '18 at 23:13
  • 1
    I get the same answer you posted as expected answer in subtraction. Other than that I have done no other testing. In answer to your question in making lines 2/3 any more concise, I tried but it was actually adding overhead when I benchmarked it. – lacostenycoder Mar 23 '18 at 03:51
  • Sorry for editing your own answer, but I’m glad that you have approved the edit. You haven’t tested your code when no overflow should be happening, e.g. `subtraction('00000055', '00000005')` would perform incorrectly. Could you also modify meta programming, I mean the check for overflow. – MOPO3OB Mar 23 '18 at 11:25
  • @IanStapletonCordasco your explanation why you have rejected the edit is completely illogical. – MOPO3OB Mar 23 '18 at 11:43
  • @ IanStapletonCordasco I'm not sure which edit you're referring to, it may have been an accident. – lacostenycoder Mar 23 '18 at 13:16
  • Another user did reject my edit, after that you have accepted it. The meta section is still incorrect I believe. Check the signs. – MOPO3OB Mar 23 '18 at 20:02
  • @MOPO3OB what should the signs be in the meta part? – lacostenycoder Mar 23 '18 at 20:04
  • 1
    Checks for overflow are `if sum >= 2**32` and `if difference < 0`. – MOPO3OB Mar 23 '18 at 21:47
  • @MOPO3OB Is the logic in my subtraction method correct? If so, I think the meta does what it's supposed to. – lacostenycoder Mar 23 '18 at 21:52
  • I have modified that logic in the method. Compare it’s check for overflowing with meta. – MOPO3OB Mar 23 '18 at 22:18
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/167443/discussion-between-lacostenycoder-and-mopo3ob). – lacostenycoder Mar 23 '18 at 22:27