Created
December 24, 2020 07:34
-
-
Save Karamell/253ee9a814f8a4a04ba04008915e829d to your computer and use it in GitHub Desktop.
Advent of Code 2020 day 24 in F#
This file contains hidden or 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
| #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