2010-01-10 10 views
6

Mam następującą funkcję Pythona rekursywnie Znajdź wszystkie rozbicie zbioru:Przełożenie na znalezienie wszystkich rozbicie zbioru z 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) 

Czy ktoś może mi pomóc przetłumaczyć ten w Ruby? Oto, co mam do tej pory:

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) 

Otrzymuję błąd "LocalJumpError: no block given". Sądzę, że dzieje się tak dlatego, że funkcje wydajności działają inaczej w Pythonie i Ruby.

+0

Gdzie znalazłaś partycje funkcji Python? Aby kontekstualizować rzeczy i uczyć się, chciałbym przeczytać wpis w blogu lub rozdział, w którym go znalazłeś. Dzięki. –

Odpowiedz

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]] 

Czym różni:

  • Strażnik nazywa set.empty? zamiast (niejawnie) testowanie dla set.nil?
  • Pozostawić na zewnątrz .each Dzwoniąc partycje
  • Zastosowanie macierzy zamiast Zestaw
  • filtru zbiór pusty Spośród uzyskanych wyniku
+0

Dziękuję bardzo! – tom

0

Będziesz musiał pomyśleć o Ruby yield jak połączenie z operacją zdefiniowaną przez użytkownika.

def twice 
    yield 
    yield 
end 

twice { puts "Hello" } 

Zawsze, gdy kod wygeneruje wartość, zostanie wywołana funkcja przetwarzania tego elementu.

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

Ten kod wcale nie generuje listy.

Powiązane problemy