package com.nurkiewicz.lazyseq.samples;
import com.nurkiewicz.lazyseq.AbstractBaseTestCase;
import com.nurkiewicz.lazyseq.LazySeq;
import com.google.common.collect.ImmutableMap;
import org.testng.annotations.Test;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static com.nurkiewicz.lazyseq.LazySeq.cons;
import static com.nurkiewicz.lazyseq.LazySeq.of;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
/**
* See: http://en.wikipedia.org/wiki/Collatz_conjecture
*
* @author Tomasz Nurkiewicz
* @since 5/12/13, 4:01 PM
*/
public class CollatzConjectureTest extends AbstractBaseTestCase {
@Test
public void shouldProduceWholeCollatzConjecture() throws Exception {
final LazySeq<Long> collatz = collatz(10);
assertThat(collatz.startsWith(asList(10L, 5L, 16L))).isTrue();
assertThat(collatz).isEqualTo(of(10L, 5L, 16L, 8L, 4L, 2L, 1L));
}
@Test
public void veryLongProgression() throws Exception {
final LazySeq<Long> collatz = collatz(63_728_127);
assertThat(collatz).hasSize(950);
}
@Test
public void veryLongProgressionCached() throws Exception {
//given
final LazySeq<Long> collatz = cachedCollatz(63_728_127);
//when
assertThat(collatz).hasSize(950);
//then
assertThat(collatzCache).
containsKey(63_728_127L).
containsKey(16L).
containsKey(8L);
}
private LazySeq<Long> collatz(long from) {
if (from > 1) {
final long next = from % 2 == 0 ? from / 2 : from * 3 + 1;
return cons(from, () -> collatz(next));
} else {
return of(1L);
}
}
private final Map<Long, LazySeq<Long>> collatzCache = new ConcurrentHashMap<>(ImmutableMap.of(1L, of(1L)));
private LazySeq<Long> cachedCollatz(long from) {
if (collatzCache.containsKey(from)) {
return collatzCache.get(from);
}
final long next = from % 2 == 0 ? from / 2 : from * 3 + 1;
final LazySeq<Long> coll = cons(from, () -> cachedCollatz(next));
collatzCache.put(from, coll);
return coll;
}
}