Skip to content

Commit f450402

Browse files
committed
[Day 9] Optimize
1 parent 952bc43 commit f450402

File tree

4 files changed

+86
-111
lines changed

4 files changed

+86
-111
lines changed

Manifest.toml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
julia_version = "1.11.2"
44
manifest_format = "2.0"
5-
project_hash = "de21728373435a74a0063d7145395fc5e7638053"
5+
project_hash = "67d09955ce37c184a2211c7b5e7d56378cf23347"
66

77
[[deps.Artifacts]]
88
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
@@ -139,6 +139,25 @@ version = "1.11.0"
139139
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
140140
version = "0.7.0"
141141

142+
[[deps.StaticArrays]]
143+
deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"]
144+
git-tree-sha1 = "47091a0340a675c738b1304b58161f3b0839d454"
145+
uuid = "90137ffa-7385-5640-81b9-e52037218182"
146+
version = "1.9.10"
147+
148+
[deps.StaticArrays.extensions]
149+
StaticArraysChainRulesCoreExt = "ChainRulesCore"
150+
StaticArraysStatisticsExt = "Statistics"
151+
152+
[deps.StaticArrays.weakdeps]
153+
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
154+
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
155+
156+
[[deps.StaticArraysCore]]
157+
git-tree-sha1 = "192954ef1208c7019899fbf8049e717f92959682"
158+
uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
159+
version = "1.4.3"
160+
142161
[[deps.Statistics]]
143162
deps = ["LinearAlgebra"]
144163
git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0"

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
1010
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1111
Memoize = "c03570c3-d221-55d1-a50c-7939bbd78826"
1212
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
13+
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1314

1415
[compat]
1516
BenchmarkTools = "1.5.0"
@@ -18,6 +19,7 @@ IterTools = "1.10.0"
1819
LinearAlgebra = "1.11.0"
1920
Memoize = "0.4.4"
2021
Printf = "1.11.0"
22+
StaticArrays = "1.9.10"
2123
julia = "1.6.7"
2224

2325
[extras]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ This Julia package contains my solutions for [Advent of Code 2024](https://adven
1818
| 6 | [:white_check_mark:](https://adventofcode.com/2024/day/6) | 592.911 ms | 52.99 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day06.jl) |
1919
| 7 | [:white_check_mark:](https://adventofcode.com/2024/day/7) | 218.393 ms | 212.72 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day07.jl) |
2020
| 8 | [:white_check_mark:](https://adventofcode.com/2024/day/8) | 316.122 μs | 671.41 KiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day08.jl) |
21-
| 9 | [:white_check_mark:](https://adventofcode.com/2024/day/9) | 1.099 s | 6.49 GiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day09.jl) |
21+
| 9 | [:white_check_mark:](https://adventofcode.com/2024/day/9) | 32.603 ms | 9.58 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day09.jl) |
2222
| 10 | [:white_check_mark:](https://adventofcode.com/2024/day/10) | 578.868 μs | 633.67 KiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day10.jl) |
2323
| 11 | [:white_check_mark:](https://adventofcode.com/2024/day/11) | 16.464 ms | 13.70 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day11.jl) |
2424
| 12 | [:white_check_mark:](https://adventofcode.com/2024/day/12) | 12.506 ms | 10.00 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2024.jl/blob/main/src/day12.jl) |

src/day09.jl

Lines changed: 63 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,96 @@
11
module Day09
22

33
using AdventOfCode2024
4+
using StaticArrays
45

56

67
function day09(input::String = readInput(joinpath(@__DIR__, "..", "data", "day09.txt")))
7-
data, filelist, spacelist = parse_data(input)
8-
p1 = part1!(copy(data))
9-
p2 = part2!(data)
8+
blocks = parse_input(input)
9+
p1 = part1!(deepcopy(blocks))
10+
p2 = part2!(blocks)
1011
return [p1, p2]
1112
end
1213

13-
function parse_data(input)
14-
data = Int[]
15-
filelist = Tuple{Int,Int}[]
16-
spacelist = Tuple{Int,Int}[]
17-
id = 0
18-
isfile = true
19-
index = 1
20-
for d rstrip(input)
21-
n = parse(Int, d)
22-
if isfile
23-
push!(data, (id * ones(Int, n))...)
24-
push!(filelist, (index, n))
25-
id += 1
26-
else
27-
push!(data, (-1 * ones(Int, n))...)
28-
push!(spacelist, (index, n))
29-
end
30-
isfile = !isfile
31-
index += n
14+
function parse_input(input)
15+
digits = parse.(Int, split(rstrip(input), ""))
16+
if length(digits) % 2 == 1
17+
push!(digits, 0)
3218
end
33-
return data, filelist, spacelist
34-
end
3519

36-
function part1!(data)
37-
ispace, inumber = 1, length(data)
38-
while ispace < inumber
39-
while ispace < length(data) && data[ispace] != -1
40-
ispace += 1
41-
end
42-
while inumber > 0 && data[inumber] == -1
43-
inumber -= 1
44-
end
45-
ispace > inumber && break
46-
data[ispace], data[inumber] = data[inumber], data[ispace]
47-
ispace += 1
48-
inumber -= 1
20+
# start index of block, capacity, used space, original id
21+
disk = Vector{MVector{4,Int}}()
22+
current_id = 0
23+
current_index = 1
24+
i = 1
25+
while i < length(digits)
26+
push!(disk, (current_index, digits[i] + digits[i+1], digits[i], current_id))
27+
current_index += digits[i] + digits[i+1]
28+
current_id += 1
29+
i += 2
4930
end
50-
return checksum(data)
31+
return disk
5132
end
5233

53-
function checksum(data)
54-
s, i = 0, 1
55-
while i < length(data)
56-
if data[i] == -1
34+
function part1!(blocks::Vector{MVector{4,Int}})
35+
data = generate_disk(blocks)
36+
i, j = 1, length(blocks)
37+
while i < j
38+
freeindex = blocks[i][1] + blocks[i][3]
39+
free = blocks[i][2] - blocks[i][3]
40+
maxtransfer = blocks[j][3]
41+
transfer = free >= maxtransfer ? maxtransfer : free
42+
data[freeindex:freeindex+transfer-1] .= blocks[j][4]
43+
data[blocks[j][1]+blocks[j][3]-transfer:blocks[j][1]+blocks[j][3]-1] .= -1
44+
blocks[i][3] += transfer
45+
blocks[j][3] -= transfer
46+
if blocks[i][2] == blocks[i][3]
5747
i += 1
58-
continue
5948
end
60-
s += data[i] * (i - 1)
61-
i += 1
49+
if blocks[j][3] == 0
50+
j -= 1
51+
end
6252
end
63-
return s
53+
return data |> checksum
6454
end
6555

66-
# TODO: Debug: Why is this wrong?
67-
function part2!(data, filelist, spacelist)
68-
for (ifilestart, ifilelength) reverse(filelist)
69-
for (i, (ispacestart, ispacelength)) enumerate(spacelist)
70-
if ispacelength >= ifilelength
71-
data[ispacestart:ispacestart + ifilelength - 1] .= data[ifilestart]
72-
data[ifilestart:ifilestart + ifilelength - 1] .= -1
73-
spacelist[i] = (ispacestart + ifilelength, ispacelength - ifilelength)
56+
function part2!(blocks::Vector{MVector{4,Int}})
57+
data = generate_disk(blocks)
58+
original_usage = [b[3] for b blocks]
59+
for j reverse(axes(blocks, 1))
60+
transfer = original_usage[j]
61+
for i 1:j-1
62+
free = blocks[i][2] - blocks[i][3]
63+
if free >= transfer
64+
data[blocks[i][1]+blocks[i][3]:blocks[i][1]+blocks[i][3]+transfer-1] .= blocks[j][4]
65+
data[blocks[j][1]:blocks[j][1]+transfer-1] .= -1
66+
blocks[i][3] += transfer
67+
blocks[j][3] -= transfer
7468
break
7569
end
7670
end
77-
println(string(data))
78-
end
79-
return checksum(data)
80-
end
81-
82-
function part2!(data)
83-
ifile = length(data)
84-
while true
85-
ifile, lenfile = prev_file(data, ifile)
86-
ifile == 0 && return checksum(data)
87-
ispace, lenspace = free_space(data, lenfile, ifile)
88-
if ispace == 0
89-
ifile -= 1
90-
continue
91-
else
92-
data[ispace:ispace+lenfile-1] .= data[ifile]
93-
data[ifile:ifile+lenfile-1] .= -1
94-
ifile -= 1
95-
end
9671
end
97-
72+
return data |> checksum
9873
end
9974

100-
function prev_file(data, i)
101-
i <= 0 && return 0, 0
102-
if data[i] == -1
103-
while data[i] == -1
104-
if i == 0
105-
return 0, 0
106-
end
107-
i -= 1
108-
end
109-
end
110-
id = data[i]
111-
while i > 0 && data[i] == id
112-
i -= 1
75+
function generate_disk(blocks::Vector{MVector{4,Int}})
76+
data = -1 * ones(Int, blocks[end][1] + blocks[end][2] - 1)
77+
for block blocks
78+
data[block[1]:block[1]+block[3]-1] .= block[4]
11379
end
114-
istart = i + 1
115-
iend = istart
116-
while iend <= length(data) && data[iend] == data[istart]
117-
iend += 1
118-
end
119-
iend -= 1
120-
return istart, iend - istart + 1
80+
return data
12181
end
12282

123-
function free_space(data, len, imax)
124-
free_indices = findall(x -> x == -1, data)
125-
visited = similar(data, Bool)
126-
visited .= false
127-
for i free_indices
128-
i >= imax && return 0, 0
129-
visited[i] && continue
130-
istart = iend = i
131-
while iend <= length(data) && data[iend] == -1
132-
visited[iend] = true
133-
iend += 1
83+
function checksum(data::Vector{Int})
84+
s, i = 0, 1
85+
while i < length(data)
86+
if data[i] == -1
87+
i += 1
88+
continue
13489
end
135-
iend -= 1
136-
l = iend - istart + 1
137-
l >= len && return istart, l
90+
s += data[i] * (i - 1)
91+
i += 1
13892
end
139-
return 0, 0
93+
return s
14094
end
14195

14296
end # module

0 commit comments

Comments
 (0)