我正在与Ruby一起工作,并试图编写将接受数字输入并返回具有相同数字的下一个最大数字的代码。
我以前在这里看到过同样的问题,但是代码相差太大,无法帮助我解决自己的特殊问题。
def next_smaller n
ndigitsarray=n.digits.reverse
bigdigitsarray=ndigitsarray.sort.reverse
bigdigitsjoint=bigdigitsarray.join.to_i
while bigdigitsjoint>n do
bigdigitsarray.insert(1, bigdigitsarray.delete_at(0))
end
return bigdigitsarray.join.to_i
end
代码超时;我不确定为什么无法正确循环。任何帮助将不胜感激!
编辑-我已经弄清了为什么存在无限循环,但是如果有人对解决更大的问题有任何建议,我现在暂时不作讨论!
答案 0 :(得分:0)
如果您没有自己创建数字数组的任务,可以使用Array#permutation方法根据原始数字生成所有数字组合。
然后,在进行一些清理和排序后,您可以找到电话号码的索引,然后加1以查找下一个最高的电话号码。
def next_number(i)
puts "Your number is #{i}"
permutations = i.to_s.split('').permutation.to_a.map(&:join).map(&:to_i).uniq.sort
index = (permutations.find_index(i) + 1)
puts "Next highest is #{permutations[index]}"
end
# Usage
next_number(4357)
next_number(81541)
注意事项:
next_number(999)
),则不会解决答案 1 :(得分:0)
您正在使用while循环,其中while条件中使用的变量在循环内不会更改。
一种通过蛮力解决问题的方法是在Array#permutation数组上使用Integer#digits:
n = 1231
n.digits.permutation.uniq.map { |e| e.join.to_i }.sort.keep_if { |k| k > n }.first
#=> 1312
它使用Array#keep_if来使所有数字(k
)大于n
。
如果没有最大数量,则返回nil
。
n.digits.permutation.uniq.map { |e| e.join.to_i }.sort.partition { |k| k > n }
#=> [[1312, 1321, 2113, 2131, 2311, 3112, 3121, 3211], [1123, 1132, 1213, 1231]]
答案 2 :(得分:0)
让我们开始创建一个方法,该方法的参数digits
是一个数字数组,并返回一个(“计数”)哈希,其键是数字0-9
,其值是digits.count(d)
每个键d
。
def count_digits(digits)
digits.each_with_object((0..9).to_a.product([0]).to_h) { |d,h| h[d] += 1 }
end
例如,
digits = 35145.digits
#=> [5, 4, 1, 5, 3]
digit_counts = count_digits(digits)
#=> {0=>0, 1=>1, 2=>0, 3=>1, 4=>1, 5=>2, 6=>0, 7=>0, 8=>0, 9=>0}
(请参见Array#product和Integer#digits)。现在,我们可以编写一个返回所需结果的方法。
def next_smallest(n)
digits = n.digits
digit_counts = count_digits(digits)
(n-1).downto(0).find { |m| count_digits(m.digits) == digit_counts }
end
require 'time'
def doit(n)
t = Time.now
n = next_smallest(n)
puts "Elapsed time in seconds = #{(Time.now-t).round(7)}"
n
end
doit 44444
# Elapsed time in seconds = 0.2008061
#=> nil
doit 35154
# Elapsed time in seconds = 5.18e-05
#=> 35145
doit 35154217464215716524742391453862
# Elapsed time in seconds = 0.0005618
#=> 35154217464215716524742391453826
doit 351542174642157165247423914538623999
# Elapsed time in seconds = 3.4207082
#=> 351542174642157165247423914538399962
尽管可能有些学术性,但我们可以做得更好。根据上文的digits
和digit_counts
,为
digits
n = 35153
我们可以写(因为最后一位大于零):
digits[0] -= 1
digits
#=> [4, 4, 1, 5, 3]
类似地,在复制digit_counts
的深层副本之后:
h = digit_counts.transform_values(&:itself)
#=> {0=>0, 1=>1, 2=>0, 3=>1, 4=>1, 5=>2, 6=>0, 7=>0, 8=>0, 9=>0}
我们可以通过编写以下内容来更新此哈希:
d0 = digits.first
#=> 4
h[d0] += 1
h[d0+1] -= 1
h #=> {0=>0, 1=>1, 2=>0, 3=>1, 4=>2, 5=>1, 6=>0, 7=>0, 8=>0, 9=>0}
而不是调用count_digits
。 (请参见Hash#transform_values)。现在,让我们对方法进行如下修改。
def next_smallest(n)
digits = n.digits
digit_counts = count_digits(digits)
h = digit_counts.transform_values(&:itself)
(n-1).downto(10).find do |m|
d0 = digits.first
if d0 > 0
digits[0] -= 1
h[d0] -= 1
h[d0-1] += 1
else
digits = m.digits
h = count_digits(digits)
end
h == digit_counts
end
end
doit 44444
# Elapsed time in seconds = 0.0607323
#=> nil
doit 35154
# Elapsed time in seconds = 0.0001582
#=> 35145
doit 35154217464215716524742391453862
# Elapsed time in seconds = 0.000216
#=> 35154217464215716524742391453826
doit 351542174642157165247423914538623999
# Elapsed time in seconds = 0.5180595
#=> 351542174642157165247423914538399962
在最后一位为零的情况下,可以进一步改进(避免调用count_digits
)。例如,如果
n = 2130
digits = n.digits
#=> [0, 3, 1, 2]
h = count_digits(digits)
#=> {0=>1, 1=>1, 2=>1, 3=>1, 4=>0, 5=>0, 6=>0, 7=>0, 8=>0, 9=>0}
digits
和h
可以为n = 2129
进行如下更新:
n -= 1
#=> 2129
d1 = digits[1]
#=> 3
digits
#=> [9, 2, 1, 2]
h[0] -= 1
h[9] += 1
h[d1] -= 1
h[d1-1] += 1
h #=> {0=>0, 1=>1, 2=>2, 3=>0, 4=>0, 5=>0, 6=>0, 7=>0, 8=>0, 9=>1}
如果使用n = 2100
或2000
,则可以执行类似的操作,但是仅调用count_digits
就会很快变得更快