Skip to content

Instantly share code, notes, and snippets.

@Karamell
Created December 24, 2020 07:34
Show Gist options
  • Select an option

  • Save Karamell/253ee9a814f8a4a04ba04008915e829d to your computer and use it in GitHub Desktop.

Select an option

Save Karamell/253ee9a814f8a4a04ba04008915e829d to your computer and use it in GitHub Desktop.
Advent of Code 2020 day 24 in F#
#time "on"
let txt = System.IO.File.ReadLines( __SOURCE_DIRECTORY__ + "/input.txt") |> Seq.toList
type Directions = E | SE | SW | W | NW | NE
type P = {x : int; y : int}
module Directions =
let move p = function
| E -> {p with x = p.x + 2}
| SE -> {x = p.x + 1; y = p.y - 1}
| SW -> {x = p.x - 1; y = p.y - 1}
| W -> {p with x = p.x - 2}
| NW -> {x = p.x - 1; y = p.y + 1}
| NE -> {x = p.x + 1; y = p.y + 1}
module P =
let adjacent p =
[E; SE; SW; W; NW; NE] |> List.map (Directions.move p)
let isAdjacent p1 p2 =
let diffx = abs(p1.x - p2.x)
let diffy = abs(p1.y - p2.y)
(diffx = 2 && diffy = 0) || (diffx = 1 && diffy = 1)
let readline (l:string) =
let rec read ret = function
| [] -> ret
| 'e' :: t -> read (E :: ret) t
| 's' :: 'e' :: t -> read (SE :: ret) t
| 's' :: 'w' :: t -> read (SW :: ret) t
| 'w' :: t -> read (W :: ret) t
| 'n' :: 'w' :: t -> read (NW :: ret) t
| 'n' :: 'e' :: t -> read (NE :: ret) t
l |> Seq.toList |> read [] |> List.rev
let flipTiles directions =
let rec flips pos tasks =
match tasks with
| [] -> pos
| h :: t ->
let pos' = Directions.move pos h
flips pos' t
flips {x=0;y=0} directions
let tasks = txt |> List.map readline
let blackTiles =
tasks |> List.map( flipTiles )
|> List.countBy id |> List.map(fun (p, c) -> p, c % 2 <> 0)
|> List.filter snd
blackTiles |> List.length |> printfn "part 1: %d"
let passDay day =
let points = day |> Set.toList
let toCheck = points @ (points |> List.collect(P.adjacent)) |> List.distinct
let adjacency = toCheck |> List.map(fun p -> p, points |> List.filter(P.isAdjacent p) |> List.length)
let actions =
adjacency |> List.map(fun (p, a) ->
match a, Set.contains p day with
| 2, false -> Set.add p
| a, true when a = 0 || 2 < a -> Set.remove p
| _, _ -> id)
actions |> List.fold(fun s fn -> fn s) day
let day0 = blackTiles |> List.map fst |> Set
let day100 = [1 .. 100] |> List.fold(fun d _ -> passDay d) day0
day100 |> Set.count |> printfn "part 2: %d"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment