2010-04-27 4 views
8

another question에서 나는 중국 우체부 문제에 대한 특정 세트를 생성하는 것을 포함하여 훌륭한 답을 제공 받았다.재귀 파이썬 메소드를 자바로 변환하는 가장 좋은 방법은 무엇입니까?

대답은 제공을했다 :

def get_pairs(s): 
    if not s: yield [] 
    else: 
     i = min(s) 
     for j in s - set([i]): 
      for r in get_pairs(s - set([i, j])): 
       yield [(i, j)] + r 

for x in get_pairs(set([1,2,3,4,5,6])): 
    print x 

이 의지 출력의 욕망 결과 :이 거의 정확하게 내가 의사 쓰기 얼마나 때문에

[(1, 2), (3, 4), (5, 6)] 
[(1, 2), (3, 5), (4, 6)] 
[(1, 2), (3, 6), (4, 5)] 
[(1, 3), (2, 4), (5, 6)] 
[(1, 3), (2, 5), (4, 6)] 
[(1, 3), (2, 6), (4, 5)] 
[(1, 4), (2, 3), (5, 6)] 
[(1, 4), (2, 5), (3, 6)] 
[(1, 4), (2, 6), (3, 5)] 
[(1, 5), (2, 3), (4, 6)] 
[(1, 5), (2, 4), (3, 6)] 
[(1, 5), (2, 6), (3, 4)] 
[(1, 6), (2, 3), (4, 5)] 
[(1, 6), (2, 4), (3, 5)] 
[(1, 6), (2, 5), (3, 4)] 

이 정말 파이썬의 표현력을 보여줍니다 알고리즘에 대한 코드. 나는 특히 수확량의 사용법과 세트가 일류 시민으로 취급되는 방식을 좋아합니다.

그러나 거기에 내 문제가 있습니다.

1.Duplicate 자바로 구성 수율 반환의 기능 :

은 무엇에 가장 좋은 방법이 될 것입니다? 대신 목록을 유지하고이 목록에 부분 결과를 추가하는 것이 가장 좋을까요? yield 키워드를 어떻게 처리할까요?

2. 세트 취급에 대한 책임은 있습니까? 나는 아마도 Set 인터페이스를 구현 한 Java 콜렉션 중 하나를 사용할 수 있으며 removeAll()과 같은 것을 사용하여 설정의 차이를 줄 수 있다는 것을 알고있다. 이 경우에 당신이 무엇을 할 것입니까?

궁극적으로이 방법을 가능한 한 간결하고 직관적 인 방법으로 축소하려고합니다. 이 메서드의 java 버전의 반환 형식이 int 배열 또는 이와 유사한 목록을 반환 할 가능성이 있다고 생각합니다.

이 방법을 Java로 변환 할 때 위의 상황을 어떻게 처리합니까?

+1

불행히도 Java는 'yield'와 닮은 것이 없습니다. 스레드 및 메시지 전달을 사용하여 근사치를 계산할 수 있지만 그 결과는 매우 복잡하고 매우 비효율적이며 아마도 현재 수행중인 작업의 정신이 아닐 수도 있습니다. –

+0

@Marcelo : 스레드와 전혀 무슨 상관이 있습니까? – doublep

+0

실? 어떻게 이것을 재현하기 위해 스레드를 사용합니까? – Beothorn

답변

2

생성기 기능을 Java로 변환하려면 Iterable + Iterator로 다시 구현해야합니다.

def foo(x): 
    for i in xrange(10): 
     yield x * i 
... 
for x in foo(5): 
    print(x) 

가되다

예컨대 : (경고 : 코드는 테스트되지 않음) :

import java.util.Iterator; 
import java.util.Iterable; 

class Foo implements Iterable<Integer> { 
    public final int x; 

    public Foo(int x) { 
     this.x = x; 
    } 

    public Iterator<Integer> iterate() { 
     return new Iterator<Integer> { 
     int i = 0; 

     public boolean hasNext() { 
      return i < 10; 
     } 

     public Integer next() { 
      return x * (i ++); 
     } 
     }; 
    } 
} 
... 
for (int x : new Foo(5)) { 
    System.out.println(x); 
} 

을 나는 참으로 java.util.HashSet을 사용 세트 들어.

+1

와우. Java는 실제로 매우 장황하다.) – BalusC

+1

그것이 사람들이 java/C#와 함수형 프로그래밍을 혼합 할 때 나는 그것을 싫어한다. 그것은 나빠 보인다. 왜 그 간단한 루프를이 자바 괴물로 변환하겠습니까? –

+0

@MK C#은 FP 형식의 동작을 훨씬 잘 지원합니다. 이 경우 C#은 변환이 쉬울 것입니다. –

1

아마도 JVM에서 실행하고 싶을 것입니다. Scala를 사용하지 않는 이유는 무엇입니까?

파이썬 코드를 거의 동일한 종류의 스칼라 코드로 변환 할 수 있다고 생각합니다. verbose java stuff보다 훨씬 낫다. 그리고 결국 jvm 바이트 코드는 자바 응용 프로그램과 쉽게 융합/협력 할 것입니다.

0

이 그래서 여기에 LINQ를 사용하여 C#에서 솔루션입니다, 당신이 물어,하지만 난 그것을 밖으로 시도 싶어 것이 아니다 :

static IEnumerable<IEnumerable<int>> getPairs(IEnumerable<int> list) 
{ 
    if (!list.Any()) 
     return new [] { new int[0] }; 

    var first = list.First(); 
    return from second in list.Skip(1) 
      from pair in getPairs(list.Skip(1).Where(rest => rest != second)) 
      select Enumerable.Concat(new [] { first, second }, pair); 
} 

실제로 쌍을 반환하지 않습니다, 그냥, 정수의 목록을 주문 그러나 이것 후에 2 개로 그것을 잘게 잘랐다. 또한 C#이 파이썬의 간결함에 필적 할 수 있다는 것을 알았습니다.
테스트를 아웃 :

foreach (var p in getPairs(new [] { 1, 2, 3, 4, 5, 6 })) 
    Console.WriteLine("[" + 
     String.Join(",", p.Select(i => i.ToString()).ToArray()) + "]"); 

그리고 출력 : 몇 가지 아이디어에 대한 또 다른 LINQ의 질문에 Noldorin's answer

[1,2,3,4,5,6] 
[1,2,3,5,4,6] 
[1,2,3,6,4,5] 
[1,3,2,4,5,6] 
[1,3,2,5,4,6] 
[1,3,2,6,4,5] 
[1,4,2,3,5,6] 
[1,4,2,5,3,6] 
[1,4,2,6,3,5] 
[1,5,2,3,4,6] 
[1,5,2,4,3,6] 
[1,5,2,6,3,4] 
[1,6,2,3,4,5] 
[1,6,2,4,3,5] 
[1,6,2,5,3,4] 

신용.

관련 문제