Published: May 04, 2017 • 2 min read
This week I wrote a small algorithm in Ruby to convert binary numbers into decimal numbers. Here’s the problem description, from Exercism:
“Convert a binary number, represented as a string (e.g. ‘101010’), to its decimal equivalent using first principles. Implement binary to decimal conversion. Given a binary input string, your program should produce a decimal output. The program should handle invalid inputs.”
If this was a real-world Ruby problem, I’d use
> '101010'.to_i(2) => 42
And go back to binary with
> 42.to_s(2) => '101010'
But this is an algorithm challenge, so here’s my algorithm.
class Binary def self.to_decimal(binary) raise ArgumentError if binary.match?(/[^01]/) binary.reverse.chars.map.with_index do |digit, index| digit.to_i * 2**index end.sum end end
And the usage:
> Binary.to_decimal('101010') => 42
What’s going on here? Examining each line:
Binary, a container for our code.
ArgumentErrorif the string does not match the binary format.
.mapover each with index included.
I like that my solution matches for
ArgumentError positively, covering a
range of bad inputs not specified by the Exercism test cases. I like that it
reverses the string so that index can be used as the incrementing exponent.
And, I like that it uses
.map to return a result without an accumulator
I may have golfed this down a little too much. In general, I think mathematical functions can get away with terser syntax than ordinary functions, because the principles are well-defined in another domain.
✉️ Get better at programming by learning with me. Subscribe to Jake Worth's Newsletter for bi-weekly ideas, creations, and curated resources from across the world of programming. Join me today!
Blog of Jake Worth, software engineer in Maine.