@@ -5,24 +5,49 @@ using AdventOfCode2024
55
66function day15(input:: String = readInput(joinpath(@__DIR__, " .." , " data" , " day15.txt" )))
77 world, instructions = parse_input(input)
8- part1(world, instructions)
8+ world_p1 = copy(world)
9+ execute_instructions_p1!(world_p1, instructions)
10+ p1 = total_gps(world_p1)
11+ world_p2 = fill(' .' , (size(world) .* (1 , 2 )). .. )
12+ for ind ∈ eachindex(IndexCartesian(), world)
13+ if world[ind] == ' #'
14+ world_p2[ind[1 ],2 * ind[2 ]- 1 ] = ' #'
15+ world_p2[ind[1 ],2 * ind[2 ]] = ' #'
16+ elseif world[ind] == ' O'
17+ world_p2[ind[1 ],2 * ind[2 ]- 1 ] = ' ['
18+ world_p2[ind[1 ],2 * ind[2 ]] = ' ]'
19+ elseif world[ind] == ' @'
20+ world_p2[ind[1 ],2 * ind[2 ]- 1 ] = ' @'
21+ end
22+ end
23+ execute_instructions_p2!(world_p2, instructions)
24+ return world_p2
925end
1026
1127function parse_input(input)
1228 wo, ins = split(input, " \n\n " )
13- return map(x -> x[1 ], reduce(vcat, permutedims.(map(x -> split(x, " " ), split(wo))))), rstrip (ins)
29+ return map(x -> x[1 ], reduce(vcat, permutedims.(map(x -> split(x, " " ), split(wo))))), replace (ins, ' \n ' => " " )
1430end
1531
16- function part1 (world, instructions)
32+ function execute_instructions_p1! (world, instructions)
1733 current = findall(x -> x == ' @' , world)[1 ]
18- world[start ] = ' .'
34+ world[current ] = ' .'
1935 for instruction ∈ instructions
2036 next = current + _to_dir(instruction)
2137 if world[next] == ' .'
2238 current = next
2339 elseif world[next] == ' O'
40+ while world[next] ∉ (' .' , ' #' )
41+ next += _to_dir(instruction)
42+ end
43+ world[next] == ' #' && continue
44+ while next != current
45+ pnext = next - _to_dir(instruction)
46+ world[next], world[pnext] = world[pnext], world[next]
47+ next = pnext
48+ end
49+ current = current + _to_dir(instruction)
2450 end
25-
2651 end
2752end
2853
@@ -33,4 +58,80 @@ function _to_dir(c::Char)
3358 c == ' <' && return CartesianIndex(0 , - 1 )
3459end
3560
61+ function total_gps(world:: Matrix{Char} )
62+ total = 0
63+ for index ∈ findall(x -> x == ' O' , world)
64+ total += 100 * (index[1 ] - 1 ) + index[2 ] - 1
65+ end
66+ return total
67+ end
68+
69+ function locate_box_complex!(tipping_positions:: Set{CartesianIndex{2}} , move_positions:: Set{CartesianIndex{2}} , world:: Matrix{Char} , dir:: CartesianIndex{2} )
70+ new_tipping_positions = Set{CartesianIndex{2 }}()
71+ for pos ∈ tipping_positions
72+ push!(move_positions, pos)
73+ if world[pos] == ' ['
74+ lockpos = CartesianIndex(pos[1 ], pos[2 ] + 1 )
75+ elseif world[pos] == ' ]'
76+ lockpos = CartesianIndex(pos[1 ], pos[2 ] - 1 )
77+ end
78+ push!(move_positions, lockpos)
79+ if world[pos + dir] == ' #' || world[lockpos + dir] == ' #'
80+ return false
81+ else
82+ if world[pos + dir] ∈ (' [' , ' ]' )
83+ push!(new_tipping_positions, pos + dir)
84+ end
85+ if world[lockpos + dir] ∈ (' [' , ' ]' )
86+ push!(new_tipping_positions, lockpos + dir)
87+ end
88+ end
89+ end
90+ if ! isempty(new_tipping_positions)
91+ return locate_box_complex!(new_tipping_positions, move_positions, world, dir)
92+ end
93+ return true
94+ end
95+
96+ function move!(move_positions:: Set{CartesianIndex{2}} , world:: Matrix{Char} , dir:: CartesianIndex{2} )
97+ if dir[1 ] == - 1
98+ mpsorted = sort(collect(move_positions), by= x-> x[1 ])
99+ else
100+ mpsorted = sort(collect(move_positions), by= x-> x[1 ], rev= true )
101+ end
102+ for pos ∈ mpsorted
103+ world[pos + dir], world[pos] = world[pos], world[pos + dir]
104+ end
105+ end
106+
107+ function execute_instructions_p2!(world, instructions)
108+ current = findall(x -> x == ' @' , world)[1 ]
109+ world[current] = ' .'
110+ for instruction ∈ instructions
111+ dir = _to_dir(instruction)
112+ next = current + dir
113+ if world[next] == ' .'
114+ current = next
115+ elseif world[next] ∈ (' [' ,' ]' )
116+ if instruction ∈ (' >' , ' <' )
117+ while world[next] ∉ (' .' , ' #' )
118+ next += dir
119+ end
120+ world[next] == ' #' && continue
121+ while next != current
122+ pnext = next - dir
123+ world[next], world[pnext] = world[pnext], world[next]
124+ next = pnext
125+ end
126+ current = current + dir
127+ else
128+ move_positions = Set{CartesianIndex{2 }}()
129+ if locate_box_complex!(Set([next]), move_positions, world, dir)
130+ move!(move_positions, world, dir)
131+ end
132+ end
133+ end
134+ end
135+ end
136+
36137end # module
0 commit comments