使用Number shuffle排序数组

时间:2015-04-02 16:20:32

标签: ruby

我询问有关号码洗牌https://rubymonk.com/learning/books/1-ruby-primer/problems/154-permutations的问题,并收到满意的答案,但这项练习对我来说还不是很清楚。练习要求:

  

给定具有不同数字的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

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

  1. no_of_combinations变量我解释如此:如果number.to_s.size等于3位数,那么组合数应该是6,否则24.我是对还是不对?

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

4 个答案:

答案 0 :(得分:1)

  
      
  1. ...如果number.to_s.size等于3位数,则组合数应为6,否则为24。我是对还是不对?
  2.   

正确,因为有6种方法可以排列3位数,24种方式可以排列4位数。

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

重复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

...此组合已添加到combinations数组中,直到数组包含no_of_combinations个唯一元素。

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

答案 1 :(得分:1)

您可以在一行中完成:

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

不要这样做。

答案 2 :(得分:0)

关于第一个问题:

鉴于具有DISTINCT DIGITS的数字的数字的排列数为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_code为真时执行代码boolean_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的工作原理。

答案 3 :(得分:0)

<强> Q1

你不需要被告知。想办法。设p(n)为您可以安排(“置换”)具有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]