2021 day23, its slow... but it works :) lots of small bugs that got hunted via tests

This commit is contained in:
alexchao26
2021-12-25 22:34:04 -05:00
parent cd5d4b0a78
commit dd88e03f2c
3 changed files with 265 additions and 183 deletions
+3
View File
@@ -3,3 +3,6 @@ input*.txt
!scripts/skeleton/tmpls/input.txt !scripts/skeleton/tmpls/input.txt
prompt.md prompt.md
prompt.txt prompt.txt
// ignore files that are prefixed with an underscore
_*
+94 -116
View File
@@ -28,20 +28,40 @@ func main() {
flag.Parse() flag.Parse()
fmt.Println("Running part", part) fmt.Println("Running part", part)
if part == 1 { ans := amphipodDay23(input, part)
ans := part1(input) util.CopyToClipboard(fmt.Sprintf("%v", ans))
util.CopyToClipboard(fmt.Sprintf("%v", ans)) fmt.Println("Output:", ans)
fmt.Println("Output:", ans)
} else {
ans := part2(input)
util.CopyToClipboard(fmt.Sprintf("%v", ans))
fmt.Println("Output:", ans)
}
} }
func part1(input string) int { var roomCoordToWantCharPart1 = map[[2]int]string{
{2, 3}: "A", {3, 3}: "A",
{2, 5}: "B", {3, 5}: "B",
{2, 7}: "C", {3, 7}: "C",
{2, 9}: "D", {3, 9}: "D",
}
var roomCoordToWantCharPart2 = map[[2]int]string{
{2, 3}: "A", {3, 3}: "A", {4, 3}: "A", {5, 3}: "A",
{2, 5}: "B", {3, 5}: "B", {4, 5}: "B", {5, 5}: "B",
{2, 7}: "C", {3, 7}: "C", {4, 7}: "C", {5, 7}: "C",
{2, 9}: "D", {3, 9}: "D", {4, 9}: "D", {5, 9}: "D",
}
func amphipodDay23(input string, part int) int {
start := parseInput(input) start := parseInput(input)
roomCoordToWantChar := roomCoordToWantCharPart1
if part == 2 {
roomCoordToWantChar = roomCoordToWantCharPart2
// update the grid with the 2 new rows, move old ones down
start.grid = append(start.grid, nil, nil)
start.grid[6] = start.grid[4]
start.grid[5] = start.grid[3]
start.grid[3] = strings.Split(" #D#C#B#A# ", "")
start.grid[4] = strings.Split(" #D#B#A#C# ", "")
}
minHeap := heap.NewMinHeap() minHeap := heap.NewMinHeap()
minHeap.Add(start) minHeap.Add(start)
@@ -53,22 +73,16 @@ func part1(input string) int {
if seenGrids[key] { if seenGrids[key] {
continue continue
} }
fmt.Println(minHeap.Length(), "\n", front)
seenGrids[key] = true seenGrids[key] = true
if front.allDone() { if front.allDone(roomCoordToWantChar) {
return front.energyUsed return front.energyUsed
} }
unsettledCoords := front.getUnsettledCoords() unsettledCoords := front.getUnsettledCoords(roomCoordToWantChar)
for _, unsettledCoord := range unsettledCoords { for _, unsettledCoord := range unsettledCoords {
// // do not try to move the last one that was moved, otherwise it'll infinite loop
// if front.coordOfLastMoved == unsettledCoord {
// continue
// }
ur, uc := unsettledCoord[0], unsettledCoord[1] ur, uc := unsettledCoord[0], unsettledCoord[1]
nextMoves := front.getNextPossibleMoves(unsettledCoord) nextMoves := front.getNextPossibleMoves(unsettledCoord, roomCoordToWantChar)
for _, nextCoord := range nextMoves { for _, nextCoord := range nextMoves {
nr, nc := nextCoord[0], nextCoord[1] nr, nc := nextCoord[0], nextCoord[1]
if front.grid[nr][nc] != "." { if front.grid[nr][nc] != "." {
@@ -80,7 +94,6 @@ func part1(input string) int {
cp.energyUsed += calcEnergy(cp.grid[ur][uc], unsettledCoord, nextCoord) cp.energyUsed += calcEnergy(cp.grid[ur][uc], unsettledCoord, nextCoord)
cp.path += fmt.Sprintf("%s%v->%v{%d},", front.grid[ur][uc], unsettledCoord, nextCoord, cp.energyUsed) cp.path += fmt.Sprintf("%s%v->%v{%d},", front.grid[ur][uc], unsettledCoord, nextCoord, cp.energyUsed)
cp.grid[nr][nc], cp.grid[ur][uc] = cp.grid[ur][uc], cp.grid[nr][nc] cp.grid[nr][nc], cp.grid[ur][uc] = cp.grid[ur][uc], cp.grid[nr][nc]
cp.coordOfLastMoved = nextCoord
// add it to the min heap // add it to the min heap
minHeap.Add(cp) minHeap.Add(cp)
@@ -88,23 +101,26 @@ func part1(input string) int {
} }
} }
// 10901 TOO LOW
panic("should return from loop") panic("should return from loop")
} }
func part2(input string) int {
return 0
}
type state struct { type state struct {
grid [][]string grid [][]string
coordOfLastMoved [2]int // store so you don't try to move the same one twice in a row energyUsed int
energyUsed int path string // for debugging
path string
} }
// Value is to implement the heap.Node interface so I can dump states into a Min Heap func parseInput(input string) *state {
grid := [][]string{}
for _, line := range strings.Split(input, "\n") {
grid = append(grid, strings.Split(line, ""))
}
return &state{
grid: grid,
}
}
// Value is to implement the heap.heapNode interface so I can dump states into a Min Heap
func (s *state) Value() int { func (s *state) Value() int {
return s.energyUsed return s.energyUsed
} }
@@ -118,7 +134,7 @@ func (s *state) String() string {
sb.WriteRune('\n') sb.WriteRune('\n')
} }
sb.WriteString(fmt.Sprintf("nrg: %d, last_moved: %v, path: %s\n", s.energyUsed, s.coordOfLastMoved, s.path)) sb.WriteString(fmt.Sprintf("nrg: %d, ,path: %s\n", s.energyUsed, s.path))
return sb.String() return sb.String()
} }
@@ -126,10 +142,9 @@ func (s *state) String() string {
// copy method to generate copies to make future heap nodes // copy method to generate copies to make future heap nodes
func (s *state) copy() *state { func (s *state) copy() *state {
cp := state{ cp := state{
grid: make([][]string, len(s.grid)), grid: make([][]string, len(s.grid)),
coordOfLastMoved: s.coordOfLastMoved, energyUsed: s.energyUsed,
energyUsed: s.energyUsed, path: s.path,
path: s.path,
} }
// need to directly copy grid or else underlying arrays will be the same & interfere // need to directly copy grid or else underlying arrays will be the same & interfere
@@ -141,14 +156,7 @@ func (s *state) copy() *state {
return &cp return &cp
} }
var roomCoordToWantChar = map[[2]int]string{ func (s *state) allDone(roomCoordToWantChar map[[2]int]string) bool {
{2, 3}: "A", {3, 3}: "A",
{2, 5}: "B", {3, 5}: "B",
{2, 7}: "C", {3, 7}: "C",
{2, 9}: "D", {3, 9}: "D",
}
func (s *state) allDone() bool {
for coord, want := range roomCoordToWantChar { for coord, want := range roomCoordToWantChar {
if s.grid[coord[0]][coord[1]] != want { if s.grid[coord[0]][coord[1]] != want {
return false return false
@@ -157,45 +165,36 @@ func (s *state) allDone() bool {
return true return true
} }
func (s *state) getUnsettledCoords() [][2]int { func (s *state) getUnsettledCoords(roomCoordToWantChar map[[2]int]string) [][2]int {
var unsettled [][2]int var unsettled [][2]int
for r, row := range s.grid { // check entire hallway
for c, v := range row { for col := 1; col < len(s.grid[0]); col++ {
// iterate through the entire grid, for every letter "/[A-D]/" if strings.Contains("ABCD", s.grid[1][col]) {
if strings.Contains("ABCD", v) { unsettled = append(unsettled, [2]int{1, col})
// add it to the unsettled list }
coord := [2]int{r, c} }
// IF not in coords map
if want, ok := roomCoordToWantChar[coord]; !ok {
unsettled = append(unsettled, coord)
continue // these are all probably unnecessary but helpful for my brain
} else {
// IF in coords map but not matching the wantChar
if want != v {
unsettled = append(unsettled, coord)
continue
} else {
// IF it matches wantChar but the cell below is
// ALSO in coords->want map AND it is the wrong want unsettledChar
// this means that it is in the right place but needs to get out
// of the way for a cell below
below := [2]int{r + 1, c}
wantBelow, ok := roomCoordToWantChar[below]
// ok means that it is a "room" cell, not wall
if ok && wantBelow != s.grid[r+1][c] {
unsettled = append(unsettled, coord)
continue
}
}
}
for _, col := range []int{3, 5, 7, 9} {
roomFullFromBack := true
for row := len(s.grid) - 2; row >= 2; row-- {
coord := [2]int{row, col}
wantChar := roomCoordToWantChar[coord]
gotChar := s.grid[row][col]
if gotChar != "." {
if gotChar != wantChar {
roomFullFromBack = false
unsettled = append(unsettled, coord)
} else if gotChar == wantChar && !roomFullFromBack {
// need to get out of the way of someone in the wrong room
unsettled = append(unsettled, coord)
}
} }
} }
} }
return unsettled return unsettled
} }
// cannot stop in front of a room // cannot stop in front of a room, still applicable for part2
var coordsInFrontOfRooms = map[[2]int]bool{ var coordsInFrontOfRooms = map[[2]int]bool{
{1, 3}: true, {1, 3}: true,
{1, 5}: true, {1, 5}: true,
@@ -207,7 +206,7 @@ func isInHallway(coord [2]int) bool {
return coord[0] == 1 return coord[0] == 1
} }
func (s *state) getNextPossibleMoves(unsettledCoord [2]int) [][2]int { func (s *state) getNextPossibleMoves(unsettledCoord [2]int, roomCoordToWantChar map[[2]int]string) [][2]int {
// get all the eligible locations for this coord to go to // get all the eligible locations for this coord to go to
unsettledChar := s.grid[unsettledCoord[0]][unsettledCoord[1]] unsettledChar := s.grid[unsettledCoord[0]][unsettledCoord[1]]
@@ -215,10 +214,10 @@ func (s *state) getNextPossibleMoves(unsettledCoord [2]int) [][2]int {
panic("unexpected character to get next moves for " + unsettledChar) panic("unexpected character to get next moves for " + unsettledChar)
} }
startedInHallway := isInHallway(unsettledCoord)
// fmt.Println(unsettledChar, unsettledCoord, "in hallway", startedInHallway)
var possible [][2]int var possible [][2]int
startedInHallway := isInHallway(unsettledCoord)
queue := [][2]int{unsettledCoord} queue := [][2]int{unsettledCoord}
seen := map[[2]int]bool{} seen := map[[2]int]bool{}
for len(queue) > 0 { for len(queue) > 0 {
@@ -243,26 +242,26 @@ func (s *state) getNextPossibleMoves(unsettledCoord [2]int) [][2]int {
} else if wantChar == unsettledChar { } else if wantChar == unsettledChar {
// found the correct room // found the correct room
// check if there is a deeper part of the room (aka lower) // check if there is a deeper part of the room (aka lower)
maybeLower := [2]int{front[0] + 1, front[1]}
if _, ok := roomCoordToWantChar[maybeLower]; ok { // if there is a "stuck" amphipod deeper in the room, cannot stop here
lowerChar := s.grid[maybeLower[0]][maybeLower[1]] // if not deepest empty coord, cannot stop here
if lowerChar == "." { // in both cases walking further is handles all cases, whether that's
possible = append(possible, maybeLower) // to walk further in or out of the room
// can only go deeper into the room so just kill the traverse here isStuckAmphipod := false
continue roomHasDeeperOpenSpaces := false
for r := front[0] + 1; r < len(s.grid)-1; r++ {
char := s.grid[r][front[1]]
if char == "." {
roomHasDeeperOpenSpaces = true
} }
// if lower char is the same, then can move into the front of the room if char != "." && char != unsettledChar {
if lowerChar == unsettledChar { isStuckAmphipod = true
possible = append(possible, front) break
// no where else to go, so just continue and end this iteration
continue
} }
} else { }
// otherwise already deep part of the room, append it
// ?probably unreachable code if !roomHasDeeperOpenSpaces && !isStuckAmphipod {
fmt.Println("unreachable code in else block?")
possible = append(possible, front) possible = append(possible, front)
continue
} }
} }
} }
@@ -306,24 +305,3 @@ func calcEnergy(char string, start, end [2]int) int {
} }
return energyPerType[char] * dist return energyPerType[char] * dist
} }
func parseInput(input string) *state {
grid := [][]string{}
for _, line := range strings.Split(input, "\n") {
grid = append(grid, strings.Split(line, ""))
}
// // uncomment to check if coordToWantChars are correct...
// for c, unsettledChar := range roomCoordToWantChar {
// grid[c[0]][c[1]] = unsettledChar
// }
// st := state{grid: grid}
// fmt.Println(st.String())
// if !st.allDone() {
// panic("state.allDone() should be true ")
// }
return &state{
grid: grid,
}
}
+164 -63
View File
@@ -2,7 +2,9 @@ package main
import ( import (
_ "embed" _ "embed"
"fmt"
"reflect" "reflect"
"strings"
"testing" "testing"
) )
@@ -18,96 +20,94 @@ var doneInput = `#############
#A#B#C#D# #A#B#C#D#
######### ` ######### `
func Test_part1(t *testing.T) { func Test_amphipodDay23(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
input string input string
part int
want int want int
}{ }{
{ {
name: "example", name: "part1 example",
input: example, input: example,
part: 1,
want: 12521, want: 12521,
}, },
{ {
name: "simple", name: "part1 simple",
input: `############# input: `#############
#.A.........# #.A.........#
###.#B#C#D### ###.#B#C#D###
#A#B#C#D# #A#B#C#D#
######### `, ######### `,
part: 1,
want: 2, want: 2,
}, },
{ {
name: "simple: A then B", name: "part1 simple: A then B",
input: `############# input: `#############
#BA.........# #BA.........#
###.#.#C#D### ###.#.#C#D###
#A#B#C#D# #A#B#C#D#
######### `, ######### `,
part: 1,
want: 52, want: 52,
}, },
{ {
// NOTE found a bug! A moving from a deep room to another room is calculating energy // NOTE found a bug! A moving from a deep room to another room is calculating energy
// NOTE as if it is walking through the wall // NOTE as if it is walking through the wall
name: "reversed B room", // B has to get out of A's way first name: "part1 reversed B room", // B has to get out of A's way first
input: `############# input: `#############
#.B.........# #.B.........#
###.#B#C#D### ###.#B#C#D###
#A#A#C#D# #A#A#C#D#
######### `, ######### `,
part: 1,
want: 95, want: 95,
}, },
{ {
name: "some shuffling", name: "part1 some shuffling",
input: `############# input: `#############
#...........# #...........#
###A#B#C#D### ###A#B#C#D###
#A#C#B#D# #A#C#B#D#
######### `, ######### `,
part: 1,
want: 1120, want: 1120,
}, },
{ {
name: "doneInput", name: "part1 doneInput",
input: doneInput, input: doneInput,
part: 1,
want: 0, want: 0,
}, },
{ {
name: "actual", name: "part1 actual",
input: input, input: input,
part: 1,
want: 15299, want: 15299,
}, },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := part1(tt.input); got != tt.want {
t.Errorf("part1() = %v, want %v", got, tt.want)
}
})
}
}
func Test_part2(t *testing.T) {
tests := []struct {
name string
input string
want int
}{
{ {
name: "example", name: "example part 2",
input: example, input: example,
part: 2,
want: 44169, want: 44169,
}, },
// { {
// name: "actual", name: "part2 actual",
// input: input, input: input,
// want: 0, part: 2,
// }, want: 47193,
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := part2(tt.input); got != tt.want { if testing.Short() && strings.Contains(tt.name, "actual") {
t.Errorf("part2() = %v, want %v", got, tt.want) t.Skip(fmt.Sprintf("skipping %q in -short mode", tt.name))
}
if got := amphipodDay23(tt.input, tt.part); got != tt.want {
t.Errorf("amphipodDay23() = %v, want %v", got, tt.want)
} }
}) })
} }
@@ -115,14 +115,16 @@ func Test_part2(t *testing.T) {
func Test_state_getUnsettledCoords(t *testing.T) { func Test_state_getUnsettledCoords(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
input string input string
want [][2]int roomCoordToWantChar map[[2]int]string
want [][2]int
}{ }{
{ {
name: "already done", name: "already done",
input: doneInput, input: doneInput,
want: nil, roomCoordToWantChar: roomCoordToWantCharPart1,
want: nil,
}, },
{ {
name: "example - 2 \"done\" amphipods", name: "example - 2 \"done\" amphipods",
@@ -134,22 +136,41 @@ func Test_state_getUnsettledCoords(t *testing.T) {
#A#D#C#A# #A#D#C#A#
######### #########
*/ */
want: [][2]int{{2, 3}, {2, 5}, {2, 7}, {2, 9}, {3, 5}, {3, 9}}, roomCoordToWantChar: roomCoordToWantCharPart1,
want: [][2]int{{2, 3}, {3, 5}, {2, 5}, {2, 7}, {3, 9}, {2, 9}},
}, },
{ {
name: "four unsettled coords", name: "four unsettled coords",
input: ` ############# input: `#############
#AB.....D..D# #AB.....D..D#
###.#.#C#.### ###.#.#C#.###
#A#B#C#.# #A#B#C#.#
######### `, ######### `,
want: [][2]int{{1, 1}, {1, 2}, {1, 8}, {1, 11}}, roomCoordToWantChar: roomCoordToWantCharPart1,
want: [][2]int{{1, 1}, {1, 2}, {1, 8}, {1, 11}},
},
{
name: "part2 test",
input: `#############
#AB.....D..D#
###.#.#C#.###
#A#A#C#.#
#B#B#C#D#
#A#B#C#D#
######### `,
roomCoordToWantChar: roomCoordToWantCharPart2,
want: [][2]int{
// hallway
{1, 1}, {1, 2}, {1, 8}, {1, 11},
{4, 3}, {3, 3}, // A room
{3, 5}, // B room
},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
s := parseInput(tt.input) s := parseInput(tt.input)
if got := s.getUnsettledCoords(); !reflect.DeepEqual(got, tt.want) { if got := s.getUnsettledCoords(tt.roomCoordToWantChar); !reflect.DeepEqual(got, tt.want) {
t.Errorf("state.getUnsettledCoords() = %v, want %v", got, tt.want) t.Errorf("state.getUnsettledCoords() = %v, want %v", got, tt.want)
} }
}) })
@@ -158,10 +179,11 @@ func Test_state_getUnsettledCoords(t *testing.T) {
func Test_state_getNextPossibleMoves(t *testing.T) { func Test_state_getNextPossibleMoves(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
input string input string
unsettledCoord [2]int unsettledCoord [2]int
want [][2]int roomCoordToWantChar map[[2]int]string
want [][2]int
}{ }{
{ {
name: "example, deep room is stuck", name: "example, deep room is stuck",
@@ -173,46 +195,116 @@ func Test_state_getNextPossibleMoves(t *testing.T) {
#A#D#C#A# #A#D#C#A#
######### #########
*/ */
unsettledCoord: [2]int{3, 3}, // DEEP room in A slot unsettledCoord: [2]int{3, 3}, // DEEP room in A slot
want: nil, roomCoordToWantChar: roomCoordToWantCharPart1,
want: nil,
}, },
{ {
name: "example-frontA", name: "example-frontA",
input: example, input: example,
unsettledCoord: [2]int{2, 3}, // FRONT room in A slot unsettledCoord: [2]int{2, 3}, // FRONT room in A slot
want: [][2]int{{1, 2}, {1, 4}, {1, 1}, {1, 6}, {1, 8}, {1, 10}, {1, 11}}, roomCoordToWantChar: roomCoordToWantCharPart1,
want: [][2]int{{1, 2}, {1, 4}, {1, 1}, {1, 6}, {1, 8}, {1, 10}, {1, 11}},
}, },
{ {
name: "example-deepA-should be stuck", name: "example-deepA-should be stuck",
input: example, input: example,
unsettledCoord: [2]int{3, 3}, // FRONT room in A slot unsettledCoord: [2]int{3, 3}, // FRONT room in A slot
want: nil, roomCoordToWantChar: roomCoordToWantCharPart1,
want: nil,
}, },
{ {
name: "hallways to rooms ONLY", name: "hallways to rooms ONLY",
input: ` ############# input: `#############
#AB.....D..D# #AB.....D..D#
###.#.#C#.### ###.#.#C#.###
#A#B#C#.# #A#B#C#.#
######### `, ######### `,
unsettledCoord: [2]int{1, 2}, unsettledCoord: [2]int{1, 2},
want: [][2]int{{2, 5}}, roomCoordToWantChar: roomCoordToWantCharPart1,
want: [][2]int{{2, 5}},
}, },
{ {
name: "hallway to DEEP room", name: "hallway to DEEP room",
input: ` ############# input: `#############
#AB.....D..D# #AB.....D..D#
###.#.#C#.### ###.#.#C#.###
#A#B#C#.# #A#B#C#.#
######### `, ######### `,
unsettledCoord: [2]int{1, 8}, unsettledCoord: [2]int{1, 8},
want: [][2]int{{3, 9}}, roomCoordToWantChar: roomCoordToWantCharPart1,
want: [][2]int{{3, 9}},
},
{
name: "part2 simple",
input: `#############
#B..........#
###A#.#C#D###
#A#B#C#D#
#A#B#C#D#
#A#B#C#D#
######### `,
unsettledCoord: [2]int{1, 1},
roomCoordToWantChar: roomCoordToWantCharPart2,
want: [][2]int{{2, 5}},
},
{
name: "part2 back of room",
input: `#############
#B......B.BB#
###A#.#C#D###
#A#.#C#D#
#A#.#C#D#
#A#.#C#D#
######### `,
unsettledCoord: [2]int{1, 1},
roomCoordToWantChar: roomCoordToWantCharPart2,
want: [][2]int{{5, 5}},
},
{
name: "part2 back of room",
input: `#############
#B......B..B#
###A#.#C#D###
#A#.#C#D#
#A#.#C#D#
#A#B#C#D#
######### `,
unsettledCoord: [2]int{1, 8},
roomCoordToWantChar: roomCoordToWantCharPart2,
want: [][2]int{{4, 5}},
},
{
name: "part2 bug moving C from B room to C room",
input: `#############
#AA.....B.BD#
###B#.#.#.###
#D#C#.#.#
#D#B#C#C#
#A#D#C#A#
######### `,
unsettledCoord: [2]int{3, 5},
roomCoordToWantChar: roomCoordToWantCharPart2,
want: [][2]int{{1, 4}, {1, 6}, {3, 7}},
},
{
name: "part2 bug moving B out of B room bc of a blocked D",
input: `#############
#AA.....B.BD#
###B#.#.#.###
#D#.#C#.#
#D#B#C#C#
#A#D#C#A#
######### `,
unsettledCoord: [2]int{4, 5},
roomCoordToWantChar: roomCoordToWantCharPart2,
want: [][2]int{{1, 4}, {1, 6}},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
s := parseInput(tt.input) s := parseInput(tt.input)
if got := s.getNextPossibleMoves(tt.unsettledCoord); !reflect.DeepEqual(got, tt.want) { if got := s.getNextPossibleMoves(tt.unsettledCoord, tt.roomCoordToWantChar); !reflect.DeepEqual(got, tt.want) {
t.Errorf("state.getNextPossibleMoves() = %v, want %v", got, tt.want) t.Errorf("state.getNextPossibleMoves() = %v, want %v", got, tt.want)
} }
}) })
@@ -266,6 +358,15 @@ func Test_calcEnergy(t *testing.T) {
}, },
want: 600, want: 600,
}, },
{
name: "part2 C",
args: args{
char: "C",
start: [2]int{5, 11},
end: [2]int{3, 7},
},
want: 1000,
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {