2014-02-25 43 views
1

我有一個奇怪的問題,在我的代碼來回答這個:IntStream.range(0,1_000_000)停止在113383(項目歐拉:最長在Collat​​z序列)

以下迭代序列的一套定義正整數:

ñ→N/2(n爲偶數)
ñ→3N + 1(n爲奇數)

使用上述規則,並用13開始,我們產生以下序列:
13→40→20→10 5→16→8→4→2→1

可以看出,這一序列(開始於13,在1精加工)包含10個術語。儘管尚未證明(Collat​​z問題),但可以認爲所有起始數字都是1.

哪一個起始數字低於100萬,會產生最長的鏈?

注:一旦鏈條開始,條款允許超過100萬。

public class Problem14 extends Problem<Integer> { 
    private final int maximum; 

    public Problem14(final int maximum) { 
     this.maximum = maximum; 
    } 

    @Override 
    public void run() { 
     result = IntStream.range(1, maximum).boxed() 
       .peek(System.out::println) 
       .collect(Collectors.toMap(i -> i, i -> (int)Iterators.intStream(new CollatzGenerator(i)).count())) 
       .entrySet().stream() 
       .peek(System.out::println) 
       .max(Comparator.comparingInt(Map.Entry::getValue)) 
       .get().getKey(); 
    } 

    @Override 
    public String getName() { 
     return "Problem 14"; 
    } 
} 

public abstract class Problem<T> implements Runnable { 
    protected T result; 

    public String getResult() { 
     return String.valueOf(result); 
    } 

    abstract public String getName(); 
} 

public class CollatzGenerator implements PrimitiveIterator.OfInt { 
    private int current; 

    public CollatzGenerator(final int start) { 
     if (start < 1) { 
      throw new IllegalArgumentException("generators.CollatzGenerator: start < 1: start = " + start); 
     } 
     this.current = start; 
    } 

    @Override 
    public boolean hasNext() { 
     return (current != 1); 
    } 

    @Override 
    public int nextInt() { 
     int returnInt = current; 
     if (current % 2 == 0) { 
      current /= 2; 
     } 
     else { 
      current = 3 * current + 1; 
     } 
     return returnInt; 
    } 
} 

public abstract class Iterators { 
    //... 

    public static IntStream intStream(final PrimitiveIterator.OfInt iterator) { 
     return StreamSupport.intStream(
       Spliterators.spliteratorUnknownSize(iterator, 0), false 
     ); 
    } 

    //... 
} 

調用代碼是沿着線:

new Problem14(1_000_000).run(); 

所以要重新表述,問題是程序永遠不會終止,我所看到的是它打印從1到113383的所有整數,大概是從第一個.peek(System.out::println)調用中打印的。

也是一個額外的問題是,目前我選中我IntStreamStream<Integer>能夠做到.collect(Collectors.toMap(i -> i, i -> (int)Iterators.intStream(new CollatzGenerator(i)).count())) ...
我想擺脫拳擊和使用IntStream::collect方法,但是我不知道了解如何做到這一點。

+0

那麼問題是什麼? –

+0

@EdCottrell問題出在標題上,我會更清楚地向我更新身體。 – skiwi

+0

@skiwi請張貼'問題'類。 –

回答

3

所以要改一下,問題是程序永遠不會終止,我做什麼看到的是,它打印的所有整數從1到113383,大概從第一.peek(System.out::println)電話。

發生這種情況是因爲您假設在collat​​z中將生成的所有數字將在int類型的範圍內。但事實並非如此。這就是它失敗的原因。嘗試使所有內容都變爲long - PrimitiveIterator.OfLongStreamSupport.longStream等,並且它將起作用。

我想擺脫拳擊和使用IntStream::collect方法,但我不明白該怎麼做。

我不明白你爲什麼想這樣做。拳擊仍然會在某處完成,因爲您無法創建原始intMap。不過,如果你願意,你實際上需要做更多的工作。下面是你如何做到這一點:

@Override 
public void run() { 

    ObjIntConsumer<Map<Integer, Long>> objIntConsumer = 
      (map, value) -> map.put(value, Iterators.longStream(new CollatzGenerator(value)).count()); 

    BiConsumer<Map<Integer, Long>, Map<Integer, Long>> biConsumer = 
      (targetMap, accumulatorMap) -> targetMap.putAll(accumulatorMap); 

    result = IntStream.range(1, maximum) 
      .collect(LinkedHashMap::new, objIntConsumer, biConsumer) 
      .entrySet().stream() 
      .peek(System.out::println) 
      .max(Comparator.<Entry<Integer, Long>>comparingLong(entry -> entry.getValue())) 
      .get().getKey(); 
}