-
Notifications
You must be signed in to change notification settings - Fork 0
/
day22.jl
64 lines (57 loc) · 1.79 KB
/
day22.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
function combatstep!(p1::Vector{Int}, p2::Vector{Int})
c1 = popfirst!(p1)
c2 = popfirst!(p2)
c1 > c2 ? append!(p1, [c1, c2]) : append!(p2, [c2, c1])
end
function playcombat!(p1::Vector{Int}, p2::Vector{Int})
while length(p1) > 0 && length(p2) > 0
combatstep!(p1, p2)
end
end
function readdeck(file::String)
deckspec = read(file, String)
p1spec = match(r"Player 1:\n([0-9\n]+)", deckspec)[1]
p1 = parse.(Int, split(p1spec))
p2spec = match(r"Player 2:\n([0-9\n]+)", deckspec)[1]
p2 = parse.(Int, split(p2spec))
ncards = length(p1)+length(p2)
ncards, p1, p2
end
function playcombat(file::String)
(ncards, p1, p2) = readdeck(file)
playcombat!(p1,p2)
sum([p1;p2].*(ncards:-1:1))
end
VSet = Set{NTuple{2,Vector{Int}}}
function recursivecombatgame!(p1::Vector{Int}, p2::Vector{Int}; sub = true)
mp1 = maximum(p1)
mp2 = maximum(p2)
ncards = length(p1) + length(p2)
if sub && mp1 > mp2 && mp1 > ncards
return true
end
visited = VSet()
while length(p1) > 0 && length(p2) > 0
p1card = popfirst!(p1)
p2card = popfirst!(p2)
p1wins = false
if (p1, p2) in visited
return true
elseif length(p1) >= p1card && length(p2) >= p2card
p1wins = recursivecombatgame!(p1[1:p1card], p2[1:p2card])
else
p1wins = p1card > p2card
end
push!(visited, (copy(p1), copy(p2)))
prize = p1wins ? [p1card, p2card] : [p2card, p1card]
append!(p1wins ? p1 : p2, prize)
end
p1winsgame = (length(p1) > 0)
return p1winsgame
end
function playrecursivecombat(file::String)
(ncards, p1, p2) = readdeck(file)
recursivecombatgame!(p1, p2, sub = false)
score([p1;p2])
end
score(deck::Vector{Int}) = sum(deck .* (length(deck):-1:1))