1
\$\begingroup\$

My exercise was to take a string of numbers, such as "1234" and return them as an integer 1234. However, I wasn't allowed to use #to_i, #to_f, Integer, etc.

def convert(int)
 x = 0
 array = int.split('')
 array.each.with_index do |y, i|
 x = (x + (y.hex))
 x = x * 10 unless i == array.length-1
 end
 return x
end
p convert('1234')
p convert('3225')
p convert('4321') == 4321
p convert('570') == 570

When I first started on this exercise, I wondered if I would be able to convert the String into a binary, octal, or other type of representation. Then, take that representation and convert it into integers.

Unfortunately, using #pack and #unpack resulted in more strings, and I couldn't really understand some of the methods that I could use with pack/unpack. Right now I don't have much knowledge in programming, so I couldn't really figure out how to take those strings and parse them into the Integers that I wanted. (My math kinda sucks too...)

Then I read about hex some more and realized that the hex representation of numbers 0-9 are the same as the integers! So I simply converted each number to a hex, added it to a variable and multiplied it by 10 with each iteration of the loop.

I know there's probably a better way to do this, but this is what I came up with.

I know another way (and possibly simpler) is to make a hash of 10 numbers, 0 - 9, with the keys being the Stringed numbers and their values being Integers, then iterating through that.

Anyways, please let me know what you think of my code and my thought process, and suggest what you can.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Sep 12, 2017 at 2:54
\$\endgroup\$
1
  • \$\begingroup\$ Are you allowed to use hex? \$\endgroup\$ Commented Sep 19, 2017 at 7:50

2 Answers 2

3
\$\begingroup\$

So I think using hex isn't in the spirit of the challenge, but that part is easy anyway:

def to_i(digit)
 '0123456789'.index(digit)
end

Your hash idea would have worked fine here too, but the above is a bit terser.

The rest is a good fit for reduce:

def convert(str)
 str.split('').reduce(0) { |m,x| 10 * (m + to_i(x)) } / 10 
end

Or you can forget splitting the solution into 2 functions and just do a 1 liner:

def convert(str)
 str.split('').reduce(0) { |m,x| 10 * (m + '0123456789'.index(x)) } / 10 
end

Finally, another alternative which sacrifices some brevity to mirror the definition of what a number is even more closely:

def convert(str)
 str.split('').reverse().map.with_index { |x,i| to_i(x) * 10**i }.reduce(:+)
end
answered Sep 12, 2017 at 9:22
\$\endgroup\$
1
  • \$\begingroup\$ Thank you! I also found @MarcRohloff's answer to be helpful. Thank you for the comments and I will study these answers more. \$\endgroup\$ Commented Sep 14, 2017 at 2:56
1
\$\begingroup\$

I think you make it complex by the way you do your multiplication. Instead of

x = 0
array.each.with_index do |y, i|
 x = (x + (y.hex))
 x = x * 10 unless i == array.length-1
end

I would do:

x = 0
array.each.with do |y|
 x = x * 10 + y.hex
end

I would also agree that using hex is not what was wanted if you were asked not to use to_i et al. I would use Jonah's suggestion or possibly y.ord-'0'.ord.

If I wanted to handle multiple bases I would write something like:

DIGITS = '01234567890abcdefghijklmnopqrstuvwxyz';
def convert(string, base=10)
 digits = string.split('')
 digits.reduce(0) do |accumulator, digit|
 value = DIGITS.index(digit)
 raise "Invalid digit #{digit}" unless value && value < base
 accumulator * base + value
 end
end
answered Sep 12, 2017 at 15:56
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.