Day 4: Printing Department

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

you are viewing a single comment's thread
view the rest of the comments
[โ€“] 2 points 10 months ago* (last edited 10 months ago)

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

  • source