From 834f23ef456ee7d3aae1225b5ccf0c07f9dc4ce6 Mon Sep 17 00:00:00 2001 From: Stanislas Lange Date: Thu, 7 Dec 2023 23:43:42 +0100 Subject: [PATCH] day 7 refacto --- 07/07.go | 200 +++++++------------------------------ 07/07_test.go | 272 +++++++++++++++++++++----------------------------- 2 files changed, 146 insertions(+), 326 deletions(-) diff --git a/07/07.go b/07/07.go index ba21bcb..0bc07d8 100644 --- a/07/07.go +++ b/07/07.go @@ -13,148 +13,23 @@ func main() { input := utils.ParseInput("input.txt") parsedInput := ConvertRawInputToInput(input) + for i := range parsedInput.Hands { + parsedInput.Hands[i].ComputeAndAssignHandType() + } + parsedInput.SortHands(StrengthsPart1) part1Score := parsedInput.ComputeTotalPoints() fmt.Printf("Part 1: %d\n", part1Score) - parsedInputV2 := ConvertRawInputToInputV2(input) - for i := range parsedInputV2.Hands { - parsedInputV2.Hands[i].ComputeAndAssignHandType() - parsedInputV2.Hands[i].JokerMode() + parsedInputPart2 := ConvertRawInputToInput(input) + for i := range parsedInputPart2.Hands { + parsedInput.Hands[i].ComputeAndAssignHandType() + parsedInput.Hands[i].JokerMode() } - parsedInputV2.SortHands() - part2Score := parsedInputV2.ComputeTotalPoints() + parsedInputPart2.SortHands(StrengthsPart2) + part2Score := parsedInputPart2.ComputeTotalPoints() fmt.Printf("Part 2: %d\n", part2Score) } -type HandV1 struct { - Cards string - Bid int -} - -type InputV1 struct { - Hands []HandV1 -} - -func ConvertRawInputToInput(rawInput []string) InputV1 { - input := InputV1{} - - for _, line := range rawInput { - splitLine := strings.Split(line, " ") - cards := splitLine[0] - bid, err := strconv.Atoi(splitLine[1]) - if err != nil { - panic(err) - } - - hand := HandV1{ - Cards: cards, - Bid: bid, - } - - input.Hands = append(input.Hands, hand) - } - - return input -} - -func (input InputV1) SortHands() { - sort.Slice(input.Hands, func(i, j int) bool { - occurrencesI := input.Hands[i].Occurrences() - occurrencesJ := input.Hands[j].Occurrences() - - maxOccurrenceCountI := 0 - for i, occurrence := range occurrencesI { - if occurrence > 0 { - maxOccurrenceCountI = i + 1 - } - } - - maxOccurrenceCountJ := 0 - for i, occurrence := range occurrencesJ { - if occurrence > 0 { - maxOccurrenceCountJ = i + 1 - } - } - - if maxOccurrenceCountI != maxOccurrenceCountJ { - return maxOccurrenceCountI < maxOccurrenceCountJ - } - - if maxOccurrenceCountI == 3 || maxOccurrenceCountI == 2 { - if occurrencesI[2-1] != occurrencesJ[2-1] { - return occurrencesI[2-1] < occurrencesJ[2-1] - } - } - - strengths := map[string]int{ - "A": 13, - "K": 12, - "Q": 11, - "J": 10, - "T": 9, - "9": 8, - "8": 7, - "7": 6, - "6": 5, - "5": 4, - "4": 3, - "3": 2, - "2": 1, - } - - for cardIndex := 0; cardIndex < 5; cardIndex++ { - cardJ := string(input.Hands[j].Cards[cardIndex]) - cardI := string(input.Hands[i].Cards[cardIndex]) - - if strengths[cardI] != strengths[cardJ] { - return strengths[cardI] < strengths[cardJ] - } - } - - return true - }) -} - -func (hand HandV1) Occurrences() []int { - occurrences := make([]int, 5) - - for _, card := range hand.Cards { - count := strings.Count(hand.Cards, string(card)) - - if count == 0 { - continue - } - indexCount := count - 1 - - if ok := occurrences[indexCount]; ok == 0 { - occurrences[indexCount] = 1 - } else { - occurrences[indexCount]++ - } - - hand.Cards = strings.ReplaceAll(hand.Cards, string(card), "") - } - - return occurrences -} - -func (input InputV1) ComputeTotalPoints() int { - input.SortHands() - - totalPoints := 0 - for i, hand := range input.Hands { - totalPoints += hand.Bid * (i + 1) - } - - return totalPoints -} - -/* -============================== - Part 2 -============================== -*/ - type HandType int const ( @@ -167,18 +42,28 @@ const ( FiveOfAKind ) -type HandV2 struct { +type Hand struct { Cards string Bid int HandType HandType } -type InputV2 struct { - Hands []HandV2 +type Input struct { + Hands []Hand } -func ConvertRawInputToInputV2(rawInput []string) InputV2 { - input := InputV2{} +var ( + StrengthsPart1 = map[string]int{ + "A": 13, "K": 12, "Q": 11, "J": 10, "T": 9, "9": 8, "8": 7, "7": 6, "6": 5, "5": 4, "4": 3, "3": 2, "2": 1, + } + + StrengthsPart2 = map[string]int{ + "A": 13, "K": 12, "Q": 11, "T": 10, "9": 9, "8": 8, "7": 7, "6": 6, "5": 5, "4": 4, "3": 3, "2": 2, "J": 1, + } +) + +func ConvertRawInputToInput(rawInput []string) Input { + input := Input{} for _, line := range rawInput { splitLine := strings.Split(line, " ") @@ -188,7 +73,7 @@ func ConvertRawInputToInputV2(rawInput []string) InputV2 { panic(err) } - hand := HandV2{ + hand := Hand{ Cards: cards, Bid: bid, } @@ -199,7 +84,7 @@ func ConvertRawInputToInputV2(rawInput []string) InputV2 { return input } -func (hand HandV2) ComputeOcurrences() []int { +func (hand Hand) ComputeOcurrences() []int { occurrences := make([]int, 5) for _, card := range hand.Cards { @@ -222,7 +107,7 @@ func (hand HandV2) ComputeOcurrences() []int { return occurrences } -func (hand *HandV2) ComputeAndAssignHandType() { +func (hand *Hand) ComputeAndAssignHandType() { occurrences := hand.ComputeOcurrences() if occurrences[5-1] == 1 { @@ -258,7 +143,7 @@ func (hand *HandV2) ComputeAndAssignHandType() { hand.HandType = HighCard } -func (hand *HandV2) JokerMode() { +func (hand *Hand) JokerMode() { JCount := strings.Count(hand.Cards, "J") if JCount == 0 { @@ -294,34 +179,19 @@ func (hand *HandV2) JokerMode() { } } -func (input InputV2) SortHands() { +func (input Input) SortHands(strengthsMap map[string]int) { sort.Slice(input.Hands, func(i, j int) bool { if input.Hands[i].HandType != input.Hands[j].HandType { return input.Hands[i].HandType < input.Hands[j].HandType } - strengths := map[string]int{ - "A": 13, - "K": 12, - "Q": 11, - "T": 10, - "9": 9, - "8": 8, - "7": 7, - "6": 6, - "5": 5, - "4": 4, - "3": 3, - "2": 2, - "J": 1, - } - + // If both hands have the same type, compare the cards by strength for cardIndex := 0; cardIndex < 5; cardIndex++ { cardJ := string(input.Hands[j].Cards[cardIndex]) cardI := string(input.Hands[i].Cards[cardIndex]) - if strengths[cardI] != strengths[cardJ] { - return strengths[cardI] < strengths[cardJ] + if strengthsMap[cardI] != strengthsMap[cardJ] { + return strengthsMap[cardI] < strengthsMap[cardJ] } } @@ -329,9 +199,7 @@ func (input InputV2) SortHands() { }) } -func (input InputV2) ComputeTotalPoints() int { - input.SortHands() - +func (input Input) ComputeTotalPoints() int { totalPoints := 0 for i, hand := range input.Hands { totalPoints += hand.Bid * (i + 1) diff --git a/07/07_test.go b/07/07_test.go index 749fd14..2eb9efd 100644 --- a/07/07_test.go +++ b/07/07_test.go @@ -15,8 +15,8 @@ func TestConvertRawInputToInput(t *testing.T) { "QQQJA 483", } - expected := InputV1{ - Hands: []HandV1{ + expected := Input{ + Hands: []Hand{ {Cards: "32T3K", Bid: 765}, {Cards: "T55J5", Bid: 684}, {Cards: "KK677", Bid: 28}, @@ -29,129 +29,8 @@ func TestConvertRawInputToInput(t *testing.T) { } func TestOccurences(t *testing.T) { - input := InputV1{ - Hands: []HandV1{ - {Cards: "T55J5", Bid: 684}, - {Cards: "32T3K", Bid: 765}, - {Cards: "QQQJA", Bid: 483}, - {Cards: "KK677", Bid: 28}, - {Cards: "KTJJT", Bid: 220}, - {Cards: "T3T3J", Bid: 17}, - {Cards: "Q2KJJ", Bid: 13}, - }, - } - - expected := [][]int{ - {2, 0, 1, 0, 0}, - {3, 1, 0, 0, 0}, - {2, 0, 1, 0, 0}, - {1, 2, 0, 0, 0}, - {1, 2, 0, 0, 0}, - {1, 2, 0, 0, 0}, - {3, 1, 0, 0, 0}, - } - - for i, hand := range input.Hands { - assert.Equal(t, expected[i], hand.Occurrences()) - } -} - -func TestSortHands(t *testing.T) { - type test struct { - input InputV1 - expected InputV1 - } - - tests := []test{ - { - input: InputV1{ - Hands: []HandV1{ - {Cards: "T55J5", Bid: 684}, - {Cards: "32T3K", Bid: 765}, - {Cards: "QQQJA", Bid: 483}, - {Cards: "KK677", Bid: 28}, - {Cards: "KTJJT", Bid: 220}, - }, - }, - expected: InputV1{ - Hands: []HandV1{ - {Cards: "32T3K", Bid: 765}, - {Cards: "KTJJT", Bid: 220}, - {Cards: "KK677", Bid: 28}, - {Cards: "T55J5", Bid: 684}, - {Cards: "QQQJA", Bid: 483}, - }, - }, - }, - { - input: InputV1{ - Hands: []HandV1{ - {Cards: "T3T3J", Bid: 17}, - {Cards: "Q2KJJ", Bid: 13}, - }, - }, - expected: InputV1{ - Hands: []HandV1{ - {Cards: "Q2KJJ", Bid: 13}, - {Cards: "T3T3J", Bid: 17}, - }, - }, - }, - } - - for _, tc := range tests { - tc.input.SortHands() - assert.Equal(t, tc.expected, tc.input) - } -} - -func TestComputeTotalPoints(t *testing.T) { - input := InputV1{ - Hands: []HandV1{ - {Cards: "32T3K", Bid: 765}, - {Cards: "KTJJT", Bid: 220}, - {Cards: "KK677", Bid: 28}, - {Cards: "T55J5", Bid: 684}, - {Cards: "QQQJA", Bid: 483}, - }, - } - - expected := 6440 - - assert.Equal(t, expected, input.ComputeTotalPoints()) -} - -/* -============================== - Part 2 -============================== -*/ - -func TestConvertRawInputToInputV2(t *testing.T) { - input := []string{ - "32T3K 765", - "T55J5 684", - "KK677 28", - "KTJJT 220", - "QQQJA 483", - } - - expected := InputV2{ - Hands: []HandV2{ - {Cards: "32T3K", Bid: 765}, - {Cards: "T55J5", Bid: 684}, - {Cards: "KK677", Bid: 28}, - {Cards: "KTJJT", Bid: 220}, - {Cards: "QQQJA", Bid: 483}, - }, - } - - assert.Equal(t, expected, ConvertRawInputToInputV2(input)) -} - -func TestOccurencesV2(t *testing.T) { - input := InputV2{ - Hands: []HandV2{ + input := Input{ + Hands: []Hand{ {Cards: "T55J5", Bid: 684}, {Cards: "32T3K", Bid: 765}, {Cards: "QQQJA", Bid: 483}, @@ -179,20 +58,20 @@ func TestOccurencesV2(t *testing.T) { func TestComputeAndAssignHandType(t *testing.T) { type test struct { - input []HandV2 - expected []HandV2 + input []Hand + expected []Hand } tests := []test{ { - input: []HandV2{ + input: []Hand{ {Cards: "T55J5", Bid: 684}, {Cards: "32T3K", Bid: 765}, {Cards: "QQQJA", Bid: 483}, {Cards: "KK677", Bid: 28}, {Cards: "KTJJT", Bid: 220}, }, - expected: []HandV2{ + expected: []Hand{ {Cards: "T55J5", Bid: 684, HandType: ThreeOfAKind}, {Cards: "32T3K", Bid: 765, HandType: OnePair}, {Cards: "QQQJA", Bid: 483, HandType: ThreeOfAKind}, @@ -201,11 +80,11 @@ func TestComputeAndAssignHandType(t *testing.T) { }, }, { - input: []HandV2{ + input: []Hand{ {Cards: "T3T3J", Bid: 17}, {Cards: "Q2KJJ", Bid: 13}, }, - expected: []HandV2{ + expected: []Hand{ {Cards: "T3T3J", Bid: 17, HandType: TwoPair}, {Cards: "Q2KJJ", Bid: 13, HandType: OnePair}, }, @@ -222,20 +101,20 @@ func TestComputeAndAssignHandType(t *testing.T) { func TestJokerMode(t *testing.T) { type test struct { - input []HandV2 - expected []HandV2 + input []Hand + expected []Hand } tests := []test{ { - input: []HandV2{ + input: []Hand{ {Cards: "T55J5", Bid: 684, HandType: ThreeOfAKind}, {Cards: "32T3K", Bid: 765, HandType: OnePair}, {Cards: "QQQJA", Bid: 483, HandType: ThreeOfAKind}, {Cards: "KK677", Bid: 28, HandType: TwoPair}, {Cards: "KTJJT", Bid: 220, HandType: TwoPair}, }, - expected: []HandV2{ + expected: []Hand{ {Cards: "T55J5", Bid: 684, HandType: FourOfAKind}, {Cards: "32T3K", Bid: 765, HandType: OnePair}, {Cards: "QQQJA", Bid: 483, HandType: FourOfAKind}, @@ -244,12 +123,12 @@ func TestJokerMode(t *testing.T) { }, }, { - input: []HandV2{ + input: []Hand{ {Cards: "T3T3J", Bid: 17, HandType: TwoPair}, {Cards: "Q2KJJ", Bid: 13, HandType: OnePair}, {Cards: "JJJQA", Bid: 483, HandType: ThreeOfAKind}, }, - expected: []HandV2{ + expected: []Hand{ {Cards: "T3T3J", Bid: 17, HandType: FullHouse}, {Cards: "Q2KJJ", Bid: 13, HandType: ThreeOfAKind}, {Cards: "JJJQA", Bid: 483, HandType: FourOfAKind}, @@ -265,16 +144,67 @@ func TestJokerMode(t *testing.T) { } } -func TestSortHandsV2(t *testing.T) { +func TestSortHandsPart1(t *testing.T) { + type test struct { + input Input + expected Input + } + + tests := []test{ + { + input: Input{ + Hands: []Hand{ + {Cards: "T55J5", Bid: 684, HandType: ThreeOfAKind}, + {Cards: "32T3K", Bid: 765, HandType: OnePair}, + {Cards: "QQQJA", Bid: 483, HandType: ThreeOfAKind}, + {Cards: "KK677", Bid: 28, HandType: TwoPair}, + {Cards: "KTJJT", Bid: 220, HandType: TwoPair}, + }, + }, + expected: Input{ + Hands: []Hand{ + {Cards: "32T3K", Bid: 765, HandType: OnePair}, + {Cards: "KTJJT", Bid: 220, HandType: TwoPair}, + {Cards: "KK677", Bid: 28, HandType: TwoPair}, + {Cards: "T55J5", Bid: 684, HandType: ThreeOfAKind}, + {Cards: "QQQJA", Bid: 483, HandType: ThreeOfAKind}, + }, + }, + }, + { + input: Input{ + Hands: []Hand{ + {Cards: "T3T3J", Bid: 17, HandType: FullHouse}, + {Cards: "Q2KJJ", Bid: 13, HandType: ThreeOfAKind}, + {Cards: "JJJQA", Bid: 483, HandType: FourOfAKind}, + }, + }, + expected: Input{ + Hands: []Hand{ + {Cards: "Q2KJJ", Bid: 13, HandType: ThreeOfAKind}, + {Cards: "T3T3J", Bid: 17, HandType: FullHouse}, + {Cards: "JJJQA", Bid: 483, HandType: FourOfAKind}, + }, + }, + }, + } + + for _, tc := range tests { + tc.input.SortHands(StrengthsPart1) + assert.Equal(t, tc.expected, tc.input) + } +} + +func TestSortHandsPart2(t *testing.T) { type test struct { - input InputV2 - expected InputV2 + input Input + expected Input } tests := []test{ { - input: InputV2{ - Hands: []HandV2{ + input: Input{ + Hands: []Hand{ {Cards: "T55J5", Bid: 684, HandType: FourOfAKind}, {Cards: "32T3K", Bid: 765, HandType: OnePair}, {Cards: "QQQJA", Bid: 483, HandType: FourOfAKind}, @@ -282,8 +212,8 @@ func TestSortHandsV2(t *testing.T) { {Cards: "KTJJT", Bid: 220, HandType: FourOfAKind}, }, }, - expected: InputV2{ - Hands: []HandV2{ + expected: Input{ + Hands: []Hand{ {Cards: "32T3K", Bid: 765, HandType: OnePair}, {Cards: "KK677", Bid: 28, HandType: TwoPair}, {Cards: "T55J5", Bid: 684, HandType: FourOfAKind}, @@ -293,15 +223,15 @@ func TestSortHandsV2(t *testing.T) { }, }, { - input: InputV2{ - Hands: []HandV2{ + input: Input{ + Hands: []Hand{ {Cards: "T3T3J", Bid: 17, HandType: FullHouse}, {Cards: "Q2KJJ", Bid: 13, HandType: ThreeOfAKind}, {Cards: "JJJQA", Bid: 483, HandType: FourOfAKind}, }, }, - expected: InputV2{ - Hands: []HandV2{ + expected: Input{ + Hands: []Hand{ {Cards: "Q2KJJ", Bid: 13, HandType: ThreeOfAKind}, {Cards: "T3T3J", Bid: 17, HandType: FullHouse}, {Cards: "JJJQA", Bid: 483, HandType: FourOfAKind}, @@ -311,23 +241,45 @@ func TestSortHandsV2(t *testing.T) { } for _, tc := range tests { - tc.input.SortHands() + tc.input.SortHands(StrengthsPart2) assert.Equal(t, tc.expected, tc.input) } } -func TestComputeTotalPointsV2(t *testing.T) { - input := InputV2{ - Hands: []HandV2{ - {Cards: "T55J5", Bid: 684, HandType: FourOfAKind}, - {Cards: "32T3K", Bid: 765, HandType: OnePair}, - {Cards: "QQQJA", Bid: 483, HandType: FourOfAKind}, - {Cards: "KK677", Bid: 28, HandType: TwoPair}, - {Cards: "KTJJT", Bid: 220, HandType: FourOfAKind}, - }, +func TestComputeTotalPoints(t *testing.T) { + type test struct { + input Input + expectedScore int } - expected := 5905 + tests := []test{ + { + input: Input{ + Hands: []Hand{ + {Cards: "32T3K", Bid: 765, HandType: OnePair}, + {Cards: "KTJJT", Bid: 220, HandType: TwoPair}, + {Cards: "KK677", Bid: 28, HandType: TwoPair}, + {Cards: "T55J5", Bid: 684, HandType: ThreeOfAKind}, + {Cards: "QQQJA", Bid: 483, HandType: ThreeOfAKind}, + }, + }, + expectedScore: 6440, + }, + { + input: Input{ + Hands: []Hand{ + {Cards: "32T3K", Bid: 765, HandType: OnePair}, + {Cards: "KK677", Bid: 28, HandType: TwoPair}, + {Cards: "T55J5", Bid: 684, HandType: FourOfAKind}, + {Cards: "QQQJA", Bid: 483, HandType: FourOfAKind}, + {Cards: "KTJJT", Bid: 220, HandType: FourOfAKind}, + }, + }, + expectedScore: 5905, + }, + } - assert.Equal(t, expected, input.ComputeTotalPoints()) + for _, tc := range tests { + assert.Equal(t, tc.expectedScore, tc.input.ComputeTotalPoints()) + } }