package day02 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 }