6

I am working on a program that requires me to read in and validate a number, but in doing so I need to take a two digit integer (for example we'll say 18) and add it 1 + 8. Now I have it working where I do a conditional check if it is greater than 10 and subtract, but that's kind of an ugly solution in my opinion and was wondering if there is a cleaner way of doing it?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Zubatman
  • 1,235
  • 3
  • 17
  • 34
  • 1
    Are you saying that you want to read in a string representation of a number and compute the sum of the last two digits of that number? If so, is it guaranteed that the number has at least two digits? – Cary Swoveland Nov 26 '14 at 05:47

6 Answers6

16

You can use the modulo operator n % 10, to get the rightmost digit. For example:

18 % 10
# => 8 
9 % 10
# => 9 
0 % 10
# => 0
(-123).abs % 10
# => 3 

To handle negative numbers, use Integer#abs.

EDIT

Ruby 2.4 has a Integer#digits method. It will give you the digits as an array, starting from unit's place. And if you want to add the digits, you can use Enumerable#sum.

123.digits
# =>[3, 2, 1]

123.digits.first
# => 3

123.digits.sum
# => 6 
Santhosh
  • 28,097
  • 9
  • 82
  • 87
1

To add all digits from a number, you can use the following:

18.to_s.chars.map(&:to_i).reduce(:+)

It transforms the number into a string, splits it into digits, transforms each into an integer and adds them all together.

Works with numbers of any length.

mbillard
  • 38,386
  • 18
  • 74
  • 98
0

This is how I would do it:

any_number = 1234

# Ensure your input is at most a two digit number (might not be needed)
two_digit_number = any_number % 100                    #=> 34

# Calculate the final addition
total = two_digit_number / 10 + two_digit_number % 10  #=> 7
Gabriel de Oliveira
  • 1,046
  • 7
  • 10
0

For two digit integers, there is at least another method we could use: Numeric#divmod, which returns the quotient and modulus in an array. And here's a look at the speed of the different approaches to sum up the digits:

b = 18
n = 1_000_000
Benchmark.bmbm do |x|
  x.report('to_s:') { n.times { b.to_s.chars.map(&:to_i).reduce(:+) }}
  x.report('divmod:') { n.times { b.divmod(10).reduce(:+) }}
  x.report('direct division:') { n.times { b/10 + b%10 } }
  x.report('digits:') { n.times { a.digits.reduce(:+) } }
end

#####
                       user     system      total        real
to_s:              0.750000   0.000000   0.750000 (  0.750700)
divmod:            0.150000   0.000000   0.150000 (  0.153516)
direct division:   0.080000   0.000000   0.080000 (  0.076697)
digits:            0.560000   0.020000   0.580000 (  0.574687)
EJAg
  • 3,210
  • 2
  • 14
  • 22
  • I ran this benchmark with `ruby-2.6.0` and I get very different results, at least for the `digits` method. Also why the variable used in digits method is `a` instead of `b` thats used with every other method? – Santhosh Feb 20 '20 at 14:06
0

Here a hands on solution for the fun of it:

def get_digits(n)

  res=[]; i=0;

  while 10**i < n
    res.push( n/10**i%10 )
    i += 1
  end

  return res

end
Ekkstein
  • 771
  • 11
  • 20
-1
def  digits_sum(number,n)
  number_array=number.to_s.chars  
  n=[n,number_array.length].min
  number_array.slice(-n,n).map {|c| c.to_i }.reduce(:+) || 0
end

this method return the sum of N right-digits.

digits_sum 123456789,5 => 35
digits_sum 123456789,2 => 17

This will work if you give N greater then number length but wont work if negative count is provided

Qaisar Nadeem
  • 2,404
  • 13
  • 23