Created
November 18, 2014 16:22
-
-
Save timyates/1f2a35934a24ea868c52 to your computer and use it in GitHub Desktop.
First pass at the Game of Life in Java 8 Streams
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.*; | |
import java.util.Arrays; | |
import java.util.List; | |
import java.util.function.Consumer; | |
import java.util.function.Function; | |
import java.util.function.Predicate; | |
import java.util.stream.Collectors; | |
import java.util.stream.IntStream; | |
import java.util.stream.Stream; | |
public class FunctionalGameOfLife { | |
@FunctionalInterface | |
interface F3<T,U,V,R> { | |
public R apply(T t, U u, V v); | |
} | |
public static void main(String[] args) { | |
// Some stats about the playfield | |
int width = 6; | |
int height = 6; | |
// The initial state and something to load it into a List of Integers | |
String initial = | |
"......" + | |
"......" + | |
"..###." + | |
".###.." + | |
"......" + | |
"......"; | |
Function<String,Integer> isAlive = s -> s.equals("#") ? 1 : 0; | |
List<Integer> state = Arrays.asList(initial.split("(?!^)")).stream().map(isAlive).collect(Collectors.toList()); | |
// Something to print out out playfield | |
Consumer<List<Integer>> printer = l -> Stream.iterate(0, i -> i + width) | |
.limit(l.size()/width) | |
.map(i -> l.stream().skip(i).limit(width).map(c -> c > 0 ? "#" : ".").collect(Collectors.joining())) | |
.forEach(System.out::println); | |
// Given a playfield, a index, and the score for it's neighbours, decide if a cell is dead or alive | |
F3<List<Integer>, Integer, Long, Integer> rules = (cells, pos, score) -> score < 2 || score > 3 ? 0 : (cells.get(pos) == 1 || score == 3 ? 1 : 0); | |
// Is a point outside the playfield? | |
Predicate<Point> inRange = p -> p.x >= 0 && p.x < width && p.y >= 0 && p.y < height; | |
// Create a new list of integers from the existing one | |
Function<List<Integer>,List<Integer>> generation = cells -> | |
IntStream.range(0, cells.size()) | |
.mapToObj(idx -> rules.apply(cells, idx, IntStream.range(0, 9) | |
.mapToObj(off -> new Point((idx % width) + (off % 3) - 1, (idx / width) + (off / 3) - 1)) | |
.filter(inRange) | |
.filter(p -> p.x + p.y * height != idx) | |
.mapToInt(p -> cells.get(p.x + p.y * height)) | |
.summaryStatistics() | |
.getSum())).collect(Collectors.toList()); | |
// run for 10 generations | |
for(int i = 0; i < 10; i++) { | |
System.out.println("Generation " + i); | |
printer.accept(state); | |
state = generation.apply(state); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment