Sort shuffle

问题描述:

我问了关于Number shuffle https://rubymonk.com/learning/books/1-ruby-primer/problems/154-permutations问题并收到了满意的答案,但是这个练习对我来说还不完全清楚。练习题要求:Sort shuffle

给定一个3位或4位数字以不同的数字,返回一个所有可以用这些数字构成的唯一数字的排序数组。

例子:

考虑:123

返回:[123, 132, 213, 231, 312, 321]

有锻炼低于溶液(见解决方案),看起来像这样:

def number_shuffle(number) 
    no_of_combinations = number.to_s.size == 3 ? 6 : 24 
    digits = number.to_s.split(//) 
    combinations = [] 
    combinations << digits.shuffle.join.to_i while combinations.uniq.size!=no_of_combinations 
    combinations.uniq.sort 
end 

我有2个问题stions,任何人都可以给我解释一下:

  1. no_of_combinations变量i解释这样:如果number.to_s.size等于3个位数,那么组合的数量应该是6,否则24 am我正确与否?

  2. 这是什么意思:combinations.uniq.size!=no_of_combinations。我知道运营商!=指定“不等于”,但不明白总体意义。

  1. ...如果number.to_s.size等于3个位数,那么组合的数量应该是6,否则24 am我正确与否?

正确的,因为有6种方法来安排3位和24点的方式,安排4位。

  1. 这是什么意思:combinations.uniq.size!=no_of_combinations

while之前的部分被重复,直到该方程被满足,即一个随机组合被创建:

digits = [1, 2 ,3] 
digits.shuffle.join.to_i #=> 123 
digits.shuffle.join.to_i #=> 132 
digits.shuffle.join.to_i #=> 321 
digits.shuffle.join.to_i #=> 123 

...,直到该数组包含这种组合被添加到阵列combinationsno_of_combinations独特的元素。

当然,这远非理想,因为可以一次又一次创建相同的组合。

+1

“号是远非理想,因为可以一遍又一遍地创建相同的组合。“绝对的,所以看起来OP提供的解决方案根本不是解决方案。这就是对教程的一个声明。 : -/ – 2015-04-02 16:56:01

+1

给予练习和方法名称的教程 – steenslag 2015-04-02 18:46:01

你能做到在同一行:

def number_shuffle(i) 
    i.to_s.chars.permutation.map(&:join).map(&:to_i) 
end 

输出:

number_shuffle(123) 
# => [123, 132, 213, 231, 312, 321] 

number_shuffle(1234) 
# => [1234, 1243, 1324, 1342, 1423, 1432, 2134, 2143, 2314, 2341, 2413, 2431, 3124, 3142, 3214, 3241, 3412, 3421, 4123, 4132, 4213, 4231, 4312, 4321] 

在这个问题的解决方案是错误和低效。它会生成随机排列,直到找到适当的唯一组合数。这就像通过替换随机值求解方程:

# x - 5 should be 0. Let's find x! 
x = rand() unless x - 5 == 0 

不要那样做。

+1

令人震惊的错误代码,Ruby-Monk显然不想要最好的解决方案。但要向学习者展示'Array#shuffle'是如何工作的。所以本质上你是对的,但这在这里与IMO毫不相干。 – astreal 2015-04-02 16:50:21

+0

@astreal是的,你已经给出了一个非常精确的函数解释。我只是想提醒作者,他提供的解决方案与问题无关。 “Shuffle”可以用于彩票游戏,但不能用于组合游戏。 – 2015-04-02 17:04:14

关于第一个问题:

鉴于的具有不同位的号码的数字排列的数量是n!1 * 2 * ... * n)。

如果数字有3个数字那么置换的数量为3! = 1 * 2 * 3 = 6

如果数字有4个数字,然后置换的数量是4! = 1 * 2 * 3 * 4 = 24

因此,在这种特殊情况下,你是对的。请注意,如果您的数字在该数字中重复,则这不起作用。

关于第二个问题:

combinations.uniq.size!=no_of_combinations是一个布尔测试,它返回truefalse。结合while声明:some_code while boolean_test,这意味着执行代码some_codeboolean_test为真。

在你的情况:

combinations << digits.shuffle.join.to_i while 
combinations.uniq.size!=no_of_combinations 

指:

digits.shuffle.join.to_i到可变combinations(这是一个数组) 而combinations.uniq.size!=no_of_combinations是真,也就是说,可以在阵列的大小(combinations)是小于预期长度(这是之前计算的)。

这里的算法首先确定预期的解决方案的数量(6或24),然后它挑选一个随机的数字混洗,如果它不存在,则将其添加到解决方案中,并且只在解决方案的数量严格时停止等于预期的解决方案数量。

这显然不是最好的解决方案(请参阅@ Oleg K.答案),但是我猜这里的目标是告诉你Array#shuffle是如何工作的。

Q1

你不需要被告知。想办法。假设p(n)是您可以安排(“置换”)具有不同数字的数字的数字的方式的数量。首先,假设n=1。那么很明显,

p(1) = 1 

现在假设n=2。第一个数字可以之前或之后的第二位,所以:

p(2) = 2*p(1) = 2 

现在让n是任意整数比2更大。对于最后一个n-1数字的每个排列,第一个数字可以插入n的任意位置。例如,假设数字是1234。最后三位数字的一种排列是423。第一个数字1可插入4位置的任何一个:1423, 4123, 4213, 4231

因此:

p(n) = n*p(n-1) 

看来:

p(n) = n! 

我们可以很容易地证明,通过感应是正确的:

p(1) = 1 
p(2) = 2*1 = 2! 
p(n) = n*p(n-1) 
    = n*(n-1)! 
    = n! 

所以:

p(3) = 3! = 6 
p(4) = 4! = 4*3! = 4*6 = 24 

现在你已经知道了这个公式,并知道为什么它是真的,你不会忘记它。

Q2

让我们重写方法与一些puts补充:

def number_shuffle(number) 
    no_of_combinations = number.to_s.size == 3 ? 6 : 24 
    puts "no_of_combinations = #{no_of_combinations}" 
    digits = number.to_s.split(//) 
    puts "digits = #{digits}\n\n" 
    combinations = [] 
    while true 
    a = digits.shuffle.join.to_i 
    puts "digits.shuffle.join.to_i = #{a}" 
    combinations << a 
    puts "combinations = #{combinations}" 
    b = combinations.uniq 
    puts " combinations.uniq = #{b}" 
    c = b.size 
    puts " combinations.uniq.size = #{c}" 
    puts " combinations.uniq.size==no_of_combos = #{c==no_of_combinations}" 
    break if c==no_of_combinations 
    end 
    combinations.uniq.sort 
end 

和尝试:

number_shuffle(123) 

no_of_combinations = 6 
digits = ["1", "2", "3"] 

digits.shuffle.join.to_i = 123 
combinations = [123] 
    combinations.uniq = [123] 
    combinations.uniq.size = 1 
    combinations.uniq.size==no_of_combinations = false 

digits.shuffle.join.to_i = 321 
combinations = [123, 321] 
    combinations.uniq = [123, 321] 
    combinations.uniq.size = 2 
    combinations.uniq.size==no_of_combinations = false 

digits.shuffle.join.to_i = 123 
combinations = [123, 321, 123] 
    combinations.uniq = [123, 321] 
    combinations.uniq.size = 2 
    combinations.uniq.size==no_of_combinations = false 

digits.shuffle.join.to_i = 312 
combinations = [123, 321, 123, 312] 
    combinations.uniq = [123, 321, 312] 
    combinations.uniq.size = 3 
    combinations.uniq.size==no_of_combinations = false 

digits.shuffle.join.to_i = 321 
combinations = [123, 321, 123, 312, 321] 
    combinations.uniq = [123, 321, 312] 
    combinations.uniq.size = 3 
    combinations.uniq.size==no_of_combinations = false 

digits.shuffle.join.to_i = 132 
combinations = [123, 321, 123, 312, 321, 132] 
    combinations.uniq = [123, 321, 312, 132] 
    combinations.uniq.size = 4 
    combinations.uniq.size==no_of_combinations = false 

digits.shuffle.join.to_i = 321 
combinations = [123, 321, 123, 312, 321, 132, 321] 
    combinations.uniq = [123, 321, 312, 132] 
    combinations.uniq.size = 4 
    combinations.uniq.size==no_of_combinations = false 

digits.shuffle.join.to_i = 213 
combinations = [123, 321, 123, 312, 321, 132, 321, 213] 
    combinations.uniq = [123, 321, 312, 132, 213] 
    combinations.uniq.size = 5 
    combinations.uniq.size==no_of_combinations = false 

digits.shuffle.join.to_i = 213 
combinations = [123, 321, 123, 312, 321, 132, 321, 213, 213] 
    combinations.uniq = [123, 321, 312, 132, 213] 
    combinations.uniq.size = 5 
    combinations.uniq.size==no_of_combinations = false 

digits.shuffle.join.to_i = 123 
combinations = [123, 321, 123, 312, 321, 132, 321, 213, 213, 123] 
    combinations.uniq = [123, 321, 312, 132, 213] 
    combinations.uniq.size = 5 
    combinations.uniq.size==no_of_combinations = false 

digits.shuffle.join.to_i = 231 
combinations = [123, 321, 123, 312, 321, 132, 321, 213, 213, 123, 231] 
    combinations.uniq = [123, 321, 312, 132, 213, 231] 
    combinations.uniq.size = 6 
    combinations.uniq.size==no_of_combinations = true 

#=> [123, 132, 213, 231, 312, 321]