'Find the smallest 4-digit number that decreases by 27 when you move its last digit to the first position. (Use the find or detect method) in Ruby

I'm trying to run standard ruby training programs, but I had a problem with this program, please take a look. Thank you very much! Code:

q = 9999 #last 4-digit number

while q > 1000                  #from 9999 to 1000, for exemple, the cycle has arrived to 6784

    d = q.to_s.chars.map(&:to_i)        #transform 6784 to array [6, 7, 8, 4]

    p = d                   # create sample array with [6, 7, 8, 4]

    tmp = p[0];                 # tmp = 6;

    p[0] = p[3];                # 6 = 4;

    p[3] = tmp;                 # 4 = 6

    g = p.join.to_i             # transform [4, 7, 8, 6] to 4786

    f = q - g               # 6784 - 4786

    if f == 27              # i need to find the smallest 4-digit number that decreases by 27 when moving its last digit to the first position

        puts q              #print 4-digit number that decreases by 27 when moving its last digit to the first position

    end

    q = q - 1; 

end

But the result does not appear, it is because it is not, or somewhere a mistake.

In general, the condition of the task is: Find the smallest 4-digit number that decreases by 27 when you move its last digit to the first position. (Use the find or detect method). Thank You!



Solution 1:[1]

I would define a method to "rotate" the number using string manipulation.

def rotate_number_one_digit(n)
  s = n.to_s
  "#{s[-1]}#{s[0..-2]}".to_i
end

Then I would use #upto to deal with the iteration.

1000.upto(9999) do |x|

end

Each time around you'll check that the "rotated" number plus 27 equals x. If so, print it and break the loop to prevent further unnecessary iteration.

1000.upto(9999) do |x|
  if rotate_number_one_digit(x) + 27 == x then
    puts x
    break
  end
end

Or we can just use the #find method from Enumerable.

1000.upto(9999).find { |x| rotate_number_one_digit(x) + 27 == x }

Solution 2:[2]

I will first create a helper method to convert an array of digits to an integer.

def digits_to_int(arr)
  arr.reduce { |n,d| n*10 + d }
end

For example,

digits_to_int [1,2,3,4]
  #=> 1234

This tends to be faster than arr.join.to_i (see sawa's answer here).

We can then simply compute

(1..).find { |n| n-27 == digits_to_int(n.digits.rotate.reverse) }
  #=> 30

See Enumerable#reduce (a.k.a. inject), "Endless range", Integer#digits, Array#rotate and Array#reverse.


Here is an example calculation.

n = 243
a = n.digits
  #=> [3,4,2]
b = a.rotate
  #=> [4,2,3]
c = b.reverse
  #=> [3,2,4]
d = digits_to_int(c)
  #=> 324
n - 27 == d
  #=> 243 - 27 == 324 => false

and another

n = 30
a = n.digits
  #=> [0,3]
b = a.rotate
  #=> [3,0]
c = b.reverse
  #=> [0,3]
d = digits_to_int(c)
  #=> 3
n - 27 == d
  #=> 30 - 27 == 3 => true

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Cary Swoveland