寻找更优雅的解决方案

时间:2013-04-12 15:11:43

标签: ruby

我是ruby的新手,正在解决这个问题:

有n个编号的字母和n个编号的信封。字母x不能 放入信封x。(OP只需要x的值不在索引x-1的值)我想要的是打印出所有可能的信息 例。

Array + 1的索引--->信封的数量

Array的元素--->字母的数量

Input: n = 3.

Output: [2, 3, 1], [3, 1, 2]

Input: n = 4.

Output:   [2, 1, 4, 3], [2, 3, 4, 1], [2, 4, 1, 3], [3, 1, 4, 2],
          [3, 4, 1, 2], [3, 4, 2, 1], [4, 1, 2, 3], [4, 3, 1, 2],
          [4, 3, 2, 1]

这是我的代码:

$nums = []
def f( already, n, times )
  if n > times
    $nums << already.dup
    return
  else
    1.upto(times) do |i|
      next if ((already.include? i) || n == i)
      already << i
      f( already, n+1, times )
      already.pop
    end
  end
end

我正在寻找更优雅的解决方案。

1 个答案:

答案 0 :(得分:2)

使用permutation枚举器,拒绝索引为x-1的值与x匹配的所有内容:

def f(n, x)
  (1..n).to_a.permutation.reject{|p| p[x-1] == x}
end

> f 3, 3
  => [[1, 3, 2], [2, 3, 1], [3, 1, 2], [3, 2, 1]] 
> f 4, 4
  => [[1, 2, 4, 3], [1, 3, 4, 2], [1, 4, 2, 3], [1, 4, 3, 2], [2, 1, 4, 3], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1], [3, 1, 4, 2], [3, 2, 4, 1], [3, 4, 1, 2], [3, 4, 2, 1], [4, 1, 2, 3], [4, 1, 3, 2], [4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1]] 

<强>更新

再次查看您的问题,目前还不清楚您是否要使用特定的x,或者只是逻辑应该对x的任何值都适用。如果第二个猜测是您想要的,那么请改用:

def f(n)
  (1..n).to_a.permutation.reject{|p| p.any?{|x| p[x-1] == x}}
end

> f 3
  => [[2, 3, 1], [3, 1, 2]] 
> f 4
  => [[2, 1, 4, 3], [2, 3, 4, 1], [2, 4, 1, 3], [3, 1, 4, 2], [3, 4, 1, 2], [3, 4, 2, 1], [4, 1, 2, 3], [4, 3, 1, 2], [4, 3, 2, 1]]