2010-01-10 45 views
6

我有以下Python函数递归找到一套的所有分区:翻译功能寻找一组所有分区在Python和Ruby

def partitions(set_): 
    if not set_: 
     yield [] 
     return 
    for i in xrange(2**len(set_)/2): 
     parts = [set(), set()] 
     for item in set_: 
      parts[i&1].add(item) 
      i >>= 1 
     for b in partitions(parts[1]): 
      yield [parts[0]]+b 

for p in partitions(["a", "b", "c", "d"]): 
print(p) 

有人可以帮我翻译成红宝石吗?这是我迄今为止:

def partitions(set) 
    if not set 
    yield [] 
    return 
    end 
    (0...2**set.size/2).each { |i| 
    parts = [Set.new, Set.new] 
    set.each { |item| 
     parts[i&1] << item 
     i >>= 1 
    } 
    partitions(parts[1]).each { |b| 
     yield [parts[0]] << b 
    } 
    } 
end 

p partitions([1, 2, 3, 4].to_set) 

我收到错误“LocalJumpError:no block given”。我想这是因为在Python和Ruby中yield函数的工作方式不同。

+0

你在哪里找到的Python功能分区的时候离开了。每个?为了让事情和学习情境化,我想阅读您发现它的博客条目或章节。谢谢。 – 2015-04-21 12:36:06

回答

4
#!/usr/bin/ruby1.8 

def partitions(set) 
    yield [] if set.empty? 
    (0 ... 2 ** set.size/2).each do |i| 
    parts = [[], []] 
    set.each do |item| 
     parts[i & 1] << item 
     i >>= 1 
    end 
    partitions(parts[1]) do |b| 
     result = [parts[0]] + b 
     result = result.reject do |e| 
     e.empty? 
     end 
     yield result 
    end 
    end 
end 

partitions([1, 2, 3, 4]) do |e| 
    p e 
end 

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

有什么不同:

  • 卫兵调用set.empty?而不是 (隐式)测试set.nil?
  • 调用 分区
  • 使用数组,而不是一套
  • 过滤空套出产生 结果
+0

非常感谢! – tom 2010-01-11 08:34:08

0

您将不得不考虑Ruby的yield,就像调用用户定义的操作一样。

def twice 
    yield 
    yield 
end 

twice { puts "Hello" } 

所以,只要你的代码产生一个值,这个元素的处理函数就会被调用。

partitions([1, 2, 3, 4].to_set) { |result| 
    # process result 
} 

此代码根本不会生成列表。