129 lines
2.5 KiB
Go
129 lines
2.5 KiB
Go
|
|
package day2
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
type Solver struct {
|
||
|
|
rounds []*Round
|
||
|
|
}
|
||
|
|
|
||
|
|
type ActionType int
|
||
|
|
|
||
|
|
const (
|
||
|
|
Rock ActionType = iota
|
||
|
|
Paper
|
||
|
|
Scissors
|
||
|
|
)
|
||
|
|
|
||
|
|
func (a ActionType) Score() int {
|
||
|
|
m := map[ActionType]int{Rock: 1, Paper: 2, Scissors: 3}
|
||
|
|
return m[a]
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewAction(s string) ActionType {
|
||
|
|
switch s {
|
||
|
|
case "A", "X":
|
||
|
|
return Rock
|
||
|
|
case "B", "Y":
|
||
|
|
return Paper
|
||
|
|
case "C", "Z":
|
||
|
|
return Scissors
|
||
|
|
}
|
||
|
|
panic(fmt.Sprintf("Unhandled action type: %s", s))
|
||
|
|
}
|
||
|
|
|
||
|
|
type Result int
|
||
|
|
|
||
|
|
const (
|
||
|
|
Win Result = iota
|
||
|
|
Loss
|
||
|
|
Draw
|
||
|
|
)
|
||
|
|
|
||
|
|
func NewDesiredResult(s string) Result {
|
||
|
|
return map[string]Result{"X": Loss, "Y": Draw, "Z": Win}[s]
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r Result) Score() int {
|
||
|
|
return map[Result]int{Win: 6, Draw: 3, Loss: 0}[r]
|
||
|
|
}
|
||
|
|
|
||
|
|
type Round struct {
|
||
|
|
OpponentAction, OwnAction ActionType
|
||
|
|
DesiredResult Result
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r Round) Score() int {
|
||
|
|
var result Result
|
||
|
|
switch {
|
||
|
|
case r.OwnAction == r.OpponentAction:
|
||
|
|
result = Draw
|
||
|
|
case r.OwnAction == Rock && r.OpponentAction == Scissors:
|
||
|
|
result = Win
|
||
|
|
case r.OwnAction == Paper && r.OpponentAction == Rock:
|
||
|
|
result = Win
|
||
|
|
case r.OwnAction == Scissors && r.OpponentAction == Paper:
|
||
|
|
result = Win
|
||
|
|
case r.OwnAction == Rock && r.OpponentAction == Paper:
|
||
|
|
result = Loss
|
||
|
|
case r.OwnAction == Paper && r.OpponentAction == Scissors:
|
||
|
|
result = Loss
|
||
|
|
case r.OwnAction == Scissors && r.OpponentAction == Rock:
|
||
|
|
result = Loss
|
||
|
|
}
|
||
|
|
return result.Score() + r.OwnAction.Score()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Solver) ParseInput(input []string) {
|
||
|
|
s.rounds = make([]*Round, len(input))
|
||
|
|
|
||
|
|
for i, line := range input {
|
||
|
|
split := strings.Split(line, " ")
|
||
|
|
s.rounds[i] = &Round{
|
||
|
|
OpponentAction: NewAction(split[0]),
|
||
|
|
OwnAction: NewAction(split[1]),
|
||
|
|
DesiredResult: NewDesiredResult(split[1]),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Solver) SolvePart1() any {
|
||
|
|
return s.score()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Solver) SolvePart2() any {
|
||
|
|
for _, r := range s.rounds {
|
||
|
|
switch {
|
||
|
|
case r.DesiredResult == Draw:
|
||
|
|
r.OwnAction = r.OpponentAction
|
||
|
|
|
||
|
|
case r.OpponentAction == Rock && r.DesiredResult == Win:
|
||
|
|
r.OwnAction = Paper
|
||
|
|
case r.OpponentAction == Rock && r.DesiredResult == Loss:
|
||
|
|
r.OwnAction = Scissors
|
||
|
|
|
||
|
|
case r.OpponentAction == Paper && r.DesiredResult == Win:
|
||
|
|
r.OwnAction = Scissors
|
||
|
|
case r.OpponentAction == Paper && r.DesiredResult == Loss:
|
||
|
|
r.OwnAction = Rock
|
||
|
|
|
||
|
|
case r.OpponentAction == Scissors && r.DesiredResult == Win:
|
||
|
|
r.OwnAction = Rock
|
||
|
|
case r.OpponentAction == Scissors && r.DesiredResult == Loss:
|
||
|
|
r.OwnAction = Paper
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return s.score()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Solver) score() int {
|
||
|
|
score := 0
|
||
|
|
for _, s := range s.rounds {
|
||
|
|
score += s.Score()
|
||
|
|
}
|
||
|
|
return score
|
||
|
|
}
|