|
| 1 | +# Pretty slow solution. Both part 1 and 2 take around 20 seconds |
| 2 | +using DataStructures |
| 3 | +function solve(game::Vector{Vector{Char}}) |
| 4 | + game = [line[2:end-1] for line in game[2:end-1]] |
| 5 | + sy, sx = length(game), length(game[1]) |
| 6 | + depth = sy - 1 |
| 7 | + nswe = [(-1, 0), (1, 0), (0, 1), (0, -1)] |
| 8 | + adjacent(y, x) = [(y+ya, x+xa) for (ya, xa)=nswe if (y+ya)∈1:sy && (x+xa)∈1:sx] |
| 9 | + is_legal(yx) = occursin(game[yx[1]][yx[2]], ".ABCD") |
| 10 | + adjacent_legal = Dict() |
| 11 | + legal_coords = [] |
| 12 | + target_lookup = Dict(a => ("."^i * a^(depth-i) for i=1:depth) for a in "ABCD") |
| 13 | + allowed_lookup = [Set(), Set((1, xa) for xa in (1, 2, 4, 6, 8, 10, 11))] |
| 14 | + |
| 15 | + for y=1:sy, x=1:sx |
| 16 | + if is_legal((y, x)) |
| 17 | + adjacent_legal[(y, x)] = filter(is_legal, adjacent(y, x)) |
| 18 | + (game[y][x] != '.' || game[y+1][x] == '#') && push!(legal_coords, (y, x)) |
| 19 | + end |
| 20 | + end |
| 21 | + state_queue = PriorityQueue(game => 0) |
| 22 | + states_visited = Set{UInt64}() |
| 23 | + while !isempty(state_queue) |
| 24 | + state, cost = dequeue_pair!(state_queue) |
| 25 | + push!(states_visited, hash(state)) |
| 26 | + if all(state[ys][xs] == ('A'+(xs-3)÷2) for (ys, xs) in legal_coords[end-(4*depth-1):end]) |
| 27 | + return cost |
| 28 | + end |
| 29 | + for (y, x) in legal_coords |
| 30 | + if (a = state[y][x]) != '.' |
| 31 | + target = target_lookup[a] |
| 32 | + allowed = allowed_lookup[(y != 1) + 1] |
| 33 | + target_x = 3 + 2(a - 'A') |
| 34 | + slot = join(state[2+d][target_x] for d=0:depth-1) |
| 35 | + slot_pos = slot ∈ target ? (1 + sum(collect(slot) .== '.'), target_x) : (0, 0) |
| 36 | + isempty(allowed) && slot_pos == (0, 0) && continue |
| 37 | + visited = Set{Tuple{Int64, Int64}}() |
| 38 | + queue = Queue{Tuple{Int64, Int64, Int64}}() |
| 39 | + enqueue!(queue, (cost, y, x)) |
| 40 | + while !isempty(queue) |
| 41 | + new_cost, yc, xc = dequeue!(queue) |
| 42 | + if slot_pos == (yc, xc) || (yc, xc) ∈ allowed |
| 43 | + new_state = deepcopy(state) |
| 44 | + new_state[yc][xc] = a |
| 45 | + new_state[y][x] = '.' |
| 46 | + if hash(new_state) ∉ states_visited |
| 47 | + state_queue[new_state] = min(new_cost, get(state_queue, new_state, typemax(Int))) |
| 48 | + end |
| 49 | + end |
| 50 | + push!(visited, (yc, xc)) |
| 51 | + for (ya, xa) in adjacent_legal[(yc, xc)] |
| 52 | + if state[ya][xa] == '.' && (ya, xa) ∉ visited |
| 53 | + adj_cost = new_cost + (10^(a - 'A')) |
| 54 | + push!(visited, (ya, xa)) |
| 55 | + enqueue!(queue, (adj_cost, ya, xa)) |
| 56 | + end |
| 57 | + end |
| 58 | + end |
| 59 | + end |
| 60 | + end |
| 61 | + end |
| 62 | +end |
| 63 | + |
| 64 | +function main() |
| 65 | + game = readlines() .|> collect |
| 66 | + println(solve(game)) |
| 67 | + |
| 68 | + insert!(game, length(game)-1, collect(" #D#C#B#A# ")) |
| 69 | + insert!(game, length(game)-1, collect(" #D#B#A#C# ")) |
| 70 | + println(solve(game)) |
| 71 | +end |
| 72 | +main() |
| 73 | + |
0 commit comments