Boy, what a simple problem. And yet those details got complicated! I had to reread the values over and over! I did manage to solve part 1 in the top 1,000, so that’s nice. And I got a one-liner for part 2.
Solution Code
LOSE, DRAW, WIN = "XYZ"
POINTS = {LOSE: 0, DRAW: 3, WIN: 6}
def part1(self, parsed_input: InputType) -> int:
"""Score a tournament with the columns representing the choices."""
score = 0
for elf_move, my_move in parsed_input:
pos_a = "ABC".index(elf_move)
pos_b = "XYZ".index(my_move)
score += pos_b + 1
if pos_a == pos_b:
score += POINTS[DRAW]
elif pos_b == (pos_a + 1) % 3:
score += POINTS[WIN]
return score
def part2(self, parsed_input: InputType) -> int:
"""Score a tournament with the second column representing the outcome."""
score = 0
for elf_move, outcome in parsed_input:
pos_a = "ABC".index(elf_move)
score += POINTS[outcome]
# The outcome determines if my move is the object before/after/same as the elf's.
shift = {DRAW: 0, WIN: 1, LOSE: 2}[outcome]
score += ((pos_a + shift) % 3) + 1
return score
def part2_short(self, parsed_input: InputType) -> int:
return sum(
POINTS[outcome] + ("ABC".index(elf_move) + {DRAW: 0, WIN: 1, LOSE: 2}[outcome]) % 3
for elf_move, outcome in parsed_input
) + len(parsed_input)
This was an interesting one indeed. Like you say, simple on the surface, but with a lot of little details that prompted a lot of decisions. For that reason, I expect to see very different approaches to this one.
I ended up creating a lot of mappings, enums and types in general to represent the data. It was fun, I learned things!
Since the solution ended up bigger than I expected, I’ll just link the file instead of posting the code here: day02.ts
I read the text from today and had to bike for 20 minutes. During the ride I was pondering if it was of any benefit to make some enums or convert the strings to atoms. In the end I think the direct string comparison is still pretty readable. So I left it at that and had 9 guarded function calls. On reddit I have seen some nice modulo solutions though…
I started in Typescript to try out Deno and quickly ended up with a confusing amount of mappings by trying to be clever. I flipped back to Julia to start over from scratch, and I’m still suspicious that there’s a clever trick hidden in plain sight since A B C and Y X Z as opposite ends of the alphabet were unlikely chosen arbitrarily.
Julia Solution
module day02
#@enum Game Loss=0 Draw=3 Win=6
#@enum Move Rock=1 Paper=2 Scissors=3
LOSS = 0
DRAW = 3
WIN = 6
ROCK = 1
PAPER = 2
SCISSORS = 3
SCORES_ROUND1 = Dict(
"A X" => (DRAW + ROCK),
"A Y" => (WIN + PAPER),
"A Z" => (LOSS + SCISSORS),
"B X" => (LOSS + ROCK),
"B Y" => (DRAW + PAPER),
"B Z" => (WIN + SCISSORS),
"C X" => (WIN + ROCK),
"C Y" => (LOSS + PAPER),
"C Z" => (DRAW + SCISSORS),
)
SCORES_ROUND2 = Dict(
"A X" => (LOSS + SCISSORS),
"A Y" => (DRAW + ROCK),
"A Z" => (WIN + PAPER),
"B X" => (LOSS + ROCK),
"B Y" => (DRAW + PAPER),
"B Z" => (WIN + SCISSORS),
"C X" => (LOSS + PAPER),
"C Y" => (DRAW + SCISSORS),
"C Z" => (WIN + ROCK),
)
function part01()
score = 0
for l in eachline("/Users/anagy/Documents/AdventOfCode2022/AdventOfCode2022-Julia/input/02/input.in")
if length(l) != 0
#a, b = split(l)
score += SCORES_ROUND1[l]
end
end
score
end
function part02()
score = 0
for l in eachline("/Users/anagy/Documents/AdventOfCode2022/AdventOfCode2022-Julia/input/02/input.in")
if length(l) != 0
score += SCORES_ROUND2[l]
end
end
score
end
end
println("P01: $(day02.part01())")
println("P02: $(day02.part02())")
I think just having a map listing the 9 possible cases for each part is pretty clever. Usually, in programming by clever we also implicitly mean “not clear”, but this is one of few instances where the clever solution might actually be the clearer one.
I think I’ll keep the mappings and the over-engineering of my solution though, it was a great learning experience and I’m proud of my mistakes learning experiences.
I also noticed this! Just shows the amount of attention to detail that goes into creating these puzzles. It’s a greater enabler of different solutions. Another pattern a few puzzles from previous years have is to have some input that when converted to binary gives you a “suspiciously convenient” representation for which you can then apply bitwise operations to solve the puzzle instead of the “normal way”.