2023 day 18 in F#

Real: 00:00:00.153, CPU: 00:00:00.150, GC gen0: 0, gen1: 0, gen2: 0
This commit is contained in:
aru 2023-12-20 17:58:52 +01:00
parent 446e09a44b
commit 4138b9d0f1
2 changed files with 119 additions and 0 deletions

14
2023/data/18/example Normal file
View File

@ -0,0 +1,14 @@
R 6 (#70c710)
D 5 (#0dc571)
L 2 (#5713f0)
D 2 (#d2c081)
R 2 (#59c680)
D 2 (#411b91)
L 5 (#8ceee2)
U 2 (#caa173)
L 1 (#1b58a2)
U 2 (#caa171)
R 2 (#7807d2)
U 3 (#a77fa3)
L 2 (#015232)
U 2 (#7a21e3)

105
2023/fsharp/day18.fsx Normal file
View File

@ -0,0 +1,105 @@
#time
open System
open System.Text.RegularExpressions
let (|Regex|_|) pattern input =
let m = Regex.Match(input, pattern)
if m.Success then
Some(List.tail [ for g in m.Groups -> g.Value ])
else
None
type Direction =
| L
| R
| U
| D
type Instruction = Direction * int * string
let parseDirection =
function
| "L" -> L
| "R" -> R
| "U" -> U
| "D" -> D
| _ -> failwith "Unreachable"
let parsePart line =
match line with
| Regex @"([LRUD])\s+(\d+)\s+\(#([^)]+)\)" (dir :: n :: color :: []) -> (parseDirection dir, int n, color)
| _ -> failwith "Unreachable"
let parseInput = Seq.map parsePart
let pointAdd (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
let pointInDirection (x, y) ins =
match ins with
| (L, n, _) -> (0, -n)
| (R, n, _) -> (0, n)
| (U, n, _) -> (-n, 0)
| (D, n, _) -> (n, 0)
|> pointAdd (x, y)
let walk input =
let rec walk' input point points length =
match input with
| [] -> (points, length)
| x :: xs ->
let (_, n, _) = x
let p = pointInDirection point x
walk' xs p (Seq.append points [ p ]) (length + n)
walk' input (0, 0) [ (0, 0) ] 0
let shoelaceArea points : int64 =
let double =
points
|> Seq.skip 1
|> Seq.zip points
|> Seq.sumBy (fun ((x1, y1), (x2, y2)) -> int64 x1 * int64 y2 - int64 x2 * int64 y1)
|> abs
double / 2L
let part1 input =
let (points, length) = walk input
let area = shoelaceArea points
area + (int64 length / 2L) + 1L
let directionFromHex =
function
| '0' -> R
| '1' -> D
| '2' -> L
| '3' -> U
| _ -> failwith "Unreachable"
let hexValue c =
match c with
| _ when System.Char.IsAsciiDigit(c) -> int c - int '0'
| _ when System.Char.IsAsciiHexDigit(c) -> int c - int 'a' + 10
| _ -> failwith "Unreachable"
let fromHex = Seq.fold (fun acc cur -> acc * 16 + hexValue cur) 0
let parseColor ((_, _, s): Instruction) =
let n = s |> Seq.take 5 |> fromHex
let d = directionFromHex s.[5]
(d, n, "")
let part2 input =
input |> Seq.map parseColor |> Seq.toList |> part1
let main f =
let input = f |> IO.File.ReadLines |> Seq.toList |> parseInput |> Seq.toList
printfn "Part 1: %d" (part1 input)
printfn "Part 2: %d" (part2 input)
0
main fsi.CommandLineArgs.[1]