Skip to content

Instantly share code, notes, and snippets.

@Zeroto
Created December 3, 2023 06:51
Show Gist options
  • Save Zeroto/e6ac98e700805feb0a840a7d0d5e7ec3 to your computer and use it in GitHub Desktop.
Save Zeroto/e6ac98e700805feb0a840a7d0d5e7ec3 to your computer and use it in GitHub Desktop.
let mapWidth = day3input.IndexOf("\n")
let mapHeight = day3input.Length / mapWidth
let findSymbols input =
let rec iter (input:string) index x y output =
if index < input.Length then
let c = input.[index]
match c with
| c when (c < '0' || c > '9') && c <> '.' && c <> '\n' -> iter input (index + 1) (x + 1) y ((x,y,c) :: output)
| '\n' -> iter input (index + 1) 0 (y + 1) output
| _ -> iter input (index + 1) (x + 1) y output
else
output
iter input 0 0 0 []
let findTouchingDigits (input:string) (x,y,_) =
let toIndex x y = (y * (mapWidth + 1)) + x
let adjacentCoords = [
if x > 0 then (x - 1, y)
if x < mapWidth then (x + 1, y)
if y > 0 then (x, y - 1)
if y < mapHeight then (x, y + 1)
if x > 0 && y > 0 then (x - 1,y - 1)
if x < mapWidth && y > 0 then (x + 1, y - 1)
if x > 0 && y < mapHeight then (x - 1, y + 1)
if x < mapWidth && y < mapHeight then (x + 1,y + 1)
]
let rec expand (input:string) x y dir fn =
if x < 0 || x >= mapWidth then []
else
let c = input.[toIndex x y]
if (c >= '0' && c <= '9') then
fn [(x,y,c)] (expand input (x + dir) y dir fn)
else
[]
let expandLeft (input:string) x y =
expand input x y -1 (fun a b -> b @ a)
let expandRight (input:string) x y =
expand input x y 1 (fun a b -> a @ b)
adjacentCoords |> List.choose (fun (x,y) ->
let c = input.[toIndex x y]
if (c >= '0' && c <= '9') then
let left = expandLeft input (x - 1) y
let right = expandRight input (x + 1) y
Some (left @ [(x,y,c)] @ right)
else
None
)
|> List.distinct
|> List.map (fun xs -> xs |> List.map (thrd) |> List.toArray |> String |> int)
let partNumbers =
(findSymbols day3input)
|> List.map (findTouchingDigits day3input)
|> List.collect id
printfn "Part1: %A" (partNumbers |> List.sum)
let gears =
(findSymbols day3input)
|> List.filter (fun (_,_,s) -> s = '*')
|> List.map (findTouchingDigits day3input)
|> List.filter (fun ds -> (ds |> List.length) = 2)
printfn "Part2: %A" (gears |> List.map (fun [a;b] -> a*b) |> List.sum)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment