Futhark
Only part 1 so far, I want to do part 2 later too.
This is my first ever futhark program. I have not yet figured out whether string parsing is possible or intended with this language. I used a combination of sed and vim to bring the input into a form futhark can read.
def neighbors (x: i32, y: i32): [8](i32, i32) = [(x+1, y+1), (x+1, y), (x+1, y-1), (x, y+1), (x, y-1), (x-1, y+1), (x-1, y), (x-1, y-1)]
def count 't (p: t -> bool) (xs: []t) : i32 = reduce (+) 0 (map (\ x -> i32.bool (p x)) xs)
def count2 't (p: t -> bool) (xs: [][]t) : i32 = reduce (+) 0 (map (count p) xs)
def zipIndices [n] 't (xs: [n]t): [n](i32, t) = zip (map i32.i64 (indices xs)) xs
def zipIndices2 [n][m] 't (xs: [m][n]t): [m][n]((i32, i32), t) =
let innerIndices = map zipIndices xs in
let innerAndOuterIndices = zipIndices innerIndices in
map (\ (r, a) -> map (\ (c, x) -> ((r, c), x)) a) innerAndOuterIndices
def countIndexed2 't (p: (i32, i32) -> t -> bool) (xs: [][]t): i32 =
let withIndices = zipIndices2 xs in
count2 (\ (i, x) -> p i x) withIndices
type option 't
= #single t
| #empty
def safeIndex 't (xs: []t) (i: i32): option t = if i32.i64 (length xs) > i && i >= 0
then #single xs[i]
else #empty
def safeIndex2 't (xs: [][]t) ((r, c): (i32, i32)): option t =
match safeIndex xs r
case #single a -> safeIndex a c
case #empty -> #empty
def orElse 't (o: option t) (d: t): t =
match o
case #single x -> x
case #empty -> d
def isAccessible (grid: [][]bool) (p: (i32, i32)) (x:bool): bool =
let neighborsOptions = map (safeIndex2 grid) (neighbors p) in
let neighborsFilled = map (`orElse` false) neighborsOptions in
x && count id neighborsFilled < 4
def mapIndexed2 'a 'b (f: (i32, i32) -> a -> b) (xs: [][]a): [][]b =
let withIndices = zipIndices2 xs in
map (map (\ (i, x) -> f i x)) withIndices
def removeAccessibles (grid: [][]bool): [][]bool = mapIndexed2 (\ p x -> x && not (isAccessible grid p x)) grid
def part1 (grid: [][]bool): i32 = countIndexed2 (isAccessible grid) grid
def part2 (grid: [][]bool): i32 =
let (reducedGrid, _) =
loop (current, last) = (removeAccessibles grid, grid)
while current != last
do
let current' = removeAccessibles current in
let last' = copy current in
(current', last')
in count2 id grid - count2 id reducedGrid
def main (grid: [][]bool) = (part1 grid, part2 grid)
The highlighting is a bit off because I used ocaml as the language. There is no futhark highlighter (at least in Web UI) yet.
Edit: Part2
Also, it runs blazingly fast ๐ :O, even in sequential C mode