Skip to content

Commit 2bef86d

Browse files
committed
[Day 7] Optimize
1 parent 6e73063 commit 2bef86d

File tree

1 file changed

+41
-25
lines changed

1 file changed

+41
-25
lines changed

src/day07.jl

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,62 @@ module Day07
22

33
using AdventOfCode2024
44

5-
65
function day07(input::String = readInput(joinpath(@__DIR__, "..", "data", "day07.txt")))
7-
test_values, numbers = parse_input(input)
8-
solve(test_values, numbers)
6+
test_values, numbers, concat_factors = parse_input(input)
7+
return solve(test_values, numbers, concat_factors)
98
end
109

1110
function parse_input(input)
12-
data = [(x, y) for (x, y) eachsplit.(eachsplit(rstrip(input), '\n'), ':')]
13-
test_values = [parse(Int, x[1]) for x data]
14-
numbers = [parse.(Int, split(lstrip(x[2]))) for x data]
15-
return test_values, numbers
11+
lines = split(rstrip(input), '\n')
12+
test_values = Int[]
13+
numbers = Vector{Int}[]
14+
concat_factors = Vector{Int}[]
15+
16+
for line in lines
17+
left, right = split(line, ':')
18+
nums = parse.(Int, split(right))
19+
factors = [10^ndigits(n) for n in nums]
20+
push!(test_values, parse(Int, left))
21+
push!(numbers, nums)
22+
push!(concat_factors, factors)
23+
end
24+
25+
return test_values, numbers, concat_factors
1626
end
1727

18-
function solve(test_values::Vector{Int}, numbers::Vector{Vector{Int}})
28+
function solve(test_values::Vector{Int}, numbers::Vector{Vector{Int}}, concat_factors::Vector{Vector{Int}})
1929
p1 = p2 = 0
20-
for (test_value, nl) zip(test_values, numbers)
21-
if valid_p1(test_value, nl[1], @view nl[2:end])
22-
p1 += test_value
23-
p2 += test_value
24-
elseif valid_p2(test_value, nl[1], @view nl[2:end])
25-
p2 += test_value
26-
end
30+
for i in eachindex(test_values)
31+
nums = numbers[i]
32+
isempty(nums) && continue
33+
tv = test_values[i]
34+
cf = concat_factors[i]
35+
36+
valid1 = _valid_p1(tv, nums[1], 2, nums)
37+
valid2 = valid1 ? true : _valid_p2(tv, nums[1], 2, nums, cf)
38+
39+
p1 += valid1 * tv
40+
p2 += (valid1 || valid2) * tv
2741
end
2842
return [p1, p2]
2943
end
3044

31-
function valid_p1(goal::Int, curr::Int, remaining::AbstractArray{Int})
32-
isempty(remaining) && curr != goal && return false
45+
@inline function _valid_p1(goal::Int, curr::Int, idx::Int, numbers::Vector{Int})
46+
idx > length(numbers) && return curr == goal
3347
curr > goal && return false
34-
curr == goal && isempty(remaining) && return true
35-
return valid_p1(goal, curr + remaining[1], @view remaining[2:end]) || valid_p1(goal, curr * remaining[1], @view remaining[2:end])
48+
@inbounds next_num = numbers[idx]
49+
return _valid_p1(goal, curr + next_num, idx + 1, numbers) ||
50+
_valid_p1(goal, curr * next_num, idx + 1, numbers)
3651
end
3752

38-
function valid_p2(goal::Int, curr::Int, remaining::AbstractArray{Int})
39-
isempty(remaining) && curr != goal && return false
53+
@inline function _valid_p2(goal::Int, curr::Int, idx::Int, numbers::Vector{Int}, concat_factors::Vector{Int})
54+
idx > length(numbers) && return curr == goal
4055
curr > goal && return false
41-
curr == goal && isempty(remaining) && return true
42-
return valid_p2(goal, curr + remaining[1], @view remaining[2:end]) || valid_p2(goal, curr * remaining[1], @view remaining[2:end]) || valid_p2(goal, concat(curr, remaining[1]), @view remaining[2:end])
56+
@inbounds next_num = numbers[idx]
57+
@inbounds cf = concat_factors[idx]
58+
return _valid_p2(goal, curr + next_num, idx + 1, numbers, concat_factors) ||
59+
_valid_p2(goal, curr * next_num, idx + 1, numbers, concat_factors) ||
60+
_valid_p2(goal, curr * cf + next_num, idx + 1, numbers, concat_factors)
4361
end
4462

45-
concat(x::Int, y::Int) = x * 10^(length(digits(y))) + y
46-
4763
end # module

0 commit comments

Comments
 (0)