Advent of Code 2024 Day6
Tips for Q2:
If the Guard moving to the same direction at same position twice
, that means Guard is in a loop.
type Day6(lines: string[]) =
let R = lines.Length
let C = lines[0].Length
let getStart (lines: string[]) =
lines
|> Array.indexed
// |> Array.pick (fun (i, s) -> s |> Seq.tryFindIndex ((=) '^') |> Option.map (fun j -> (i, j)))
|> Array.pick (fun (i, s) ->
let j = s.IndexOf("^")
if j <> -1 then Some(i, j) else None)
let ops = [ (-1, 0); (0, 1); (1, 0); (0, -1) ]
let rec moving i j op (pos_set: HashSet<Index>) =
pos_set.Add((i, j)) |> ignore
let next_i = i + fst ops[op]
let next_j = j + snd ops[op]
if next_i < 0 || next_i >= R || next_j < 0 || next_j >= C then
pos_set
elif lines[next_i][next_j] = '#' then
moving i j ((op + 1) % 4) pos_set
else
moving next_i next_j op pos_set
member this.Q1() =
let start: Index = getStart lines
let post_set = moving (fst start) (snd start) 0 (HashSet())
post_set.Count
member this.Q2() =
let start: Index = getStart lines
let pos_set = moving (fst start) (snd start) 0 (HashSet())
pos_set.Remove(start) |> ignore
let isInLoop (pos_set: HashSet<int * int * int>) i j op = pos_set.Add((i, j, op)) = false
let rec checkLoop i j op (pos_set: HashSet<int * int * int>) =
let next_i = i + fst ops[op]
let next_j = j + snd ops[op]
if next_i < 0 || next_i >= R || next_j < 0 || next_j >= C then
false
elif lines[next_i][next_j] = '#' then
if isInLoop pos_set i j op then
true
else
checkLoop i j ((op + 1) % 4) pos_set
else
checkLoop next_i next_j op pos_set
pos_set
|> Seq.filter (fun (i, j) ->
let old = lines[i]
let str = old.ToCharArray()
str[j] <- '#'
lines[i] <- String(str)
let rst = checkLoop (fst start) (snd start) 0 (HashSet())
lines[i] <- old
rst)
|> Seq.length
You can find the source code at https://github.com/zangruizhe/AoC