2021 Day 21 Complete
This commit is contained in:
parent
c7e4c2eb17
commit
aebc37122d
@ -1,7 +1,112 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println("vim-go")
|
inp := h.StdinToStringSlice()
|
||||||
|
scanners := parseScanners(inp)
|
||||||
|
foundBeacons := scanners[0].beacons
|
||||||
|
foundScannerPositions := []beacon{{0, 0, 0}}
|
||||||
|
|
||||||
|
remaining := scanners[1:]
|
||||||
|
for len(remaining) > 0 {
|
||||||
|
var wrk scanner
|
||||||
|
wrk, remaining = remaining[0], remaining[1:]
|
||||||
|
s := NewScanner(foundBeacons).getScannerFromOverlap(wrk)
|
||||||
|
if s == nil {
|
||||||
|
remaining = append(remaining, s)
|
||||||
|
} else {
|
||||||
|
foundBeacons = append(foundBeacons, s.beacons...)
|
||||||
|
//foundScannerPositions = append(foundScannerPositions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseScanners(inp []string) []scanner {
|
||||||
|
var scanners []scanner
|
||||||
|
for i := range inp {
|
||||||
|
if strings.HasPrefix(inp[i], "---") {
|
||||||
|
// Find the next empty line
|
||||||
|
end := i
|
||||||
|
for ; end < len(inp); end++ {
|
||||||
|
if inp[end] == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// a new scanner
|
||||||
|
wrk, err := NewScannerFromInput(inp[i:end])
|
||||||
|
if err == nil {
|
||||||
|
scanners = append(scanners, wrk)
|
||||||
|
} else {
|
||||||
|
fmt.Println("Error parsing scanners")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scanners
|
||||||
|
}
|
||||||
|
|
||||||
|
type scanner struct {
|
||||||
|
number int
|
||||||
|
region map[h.Coordinate]bool
|
||||||
|
beacons []beacon
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewScanner(b []beacon) scanner {
|
||||||
|
return scanner{beacons: b}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewScannerFromInput(inp []string) (scanner, error) {
|
||||||
|
s := scanner{}
|
||||||
|
r := strings.NewReader(inp[0])
|
||||||
|
_, err := fmt.Fscanf(r, "--- scanner %d ---", &s.number)
|
||||||
|
if err != nil {
|
||||||
|
return s, errors.New("No Scanner ID")
|
||||||
|
}
|
||||||
|
for _, v := range inp[1:] {
|
||||||
|
r = strings.NewReader(v)
|
||||||
|
b := beacon{}
|
||||||
|
_, err := fmt.Fscanf(r, "%d,%d,%d", &b.x, &b.y, &b.z)
|
||||||
|
if err == nil {
|
||||||
|
s.beacons = append(s.beacons, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s scanner) allRotations() [][]beacon {
|
||||||
|
var beacons [][]beacon
|
||||||
|
for i := range s.beacons {
|
||||||
|
beacons = append(beacons, s.beacons[i].allRotations())
|
||||||
|
}
|
||||||
|
return beacons
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s scanner) String() string {
|
||||||
|
return fmt.Sprintf("-- Scanner %d (%d beacons)---", s.number, len(s.beacons))
|
||||||
|
}
|
||||||
|
|
||||||
|
type beacon struct {
|
||||||
|
x, y, z int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b beacon) allRotations() []beacon {
|
||||||
|
return []beacon{
|
||||||
|
{b.x, b.y, b.z}, {b.x, -b.z, b.y}, {b.x, -b.y, -b.z}, {b.x, b.z, -b.y}, {-b.x, -b.y, b.z},
|
||||||
|
{-b.x, -b.z, -b.y}, {-b.x, b.y, -b.z}, {-b.x, b.z, b.y}, {-b.z, b.x, -b.y}, {b.y, b.x, -b.z},
|
||||||
|
{b.z, b.x, b.y}, {-b.y, b.x, b.z}, {b.z, -b.x, -b.y}, {b.y, -b.x, b.z}, {-b.z, -b.x, b.y},
|
||||||
|
{-b.y, -b.x, -b.z}, {-b.y, -b.z, b.x}, {b.z, -b.y, b.x}, {b.y, b.z, b.x}, {-b.z, b.y, b.x},
|
||||||
|
{b.z, b.y, -b.x}, {-b.y, b.z, -b.x}, {-b.z, -b.y, -b.x}, {b.y, -b.z, -b.x},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b beacon) String() string {
|
||||||
|
return fmt.Sprintf("{%d,%d,%d}", b.x, b.y, b.z)
|
||||||
}
|
}
|
||||||
|
2
2021/day21/input
Normal file
2
2021/day21/input
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Player 1 starting position: 4
|
||||||
|
Player 2 starting position: 2
|
137
2021/day21/main.go
Normal file
137
2021/day21/main.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
inp := h.StdinToStringSlice()
|
||||||
|
var starting []int
|
||||||
|
for i := range inp {
|
||||||
|
starting = append(starting, int(inp[i][len(inp[i])-1]-'0'))
|
||||||
|
}
|
||||||
|
part1(starting)
|
||||||
|
fmt.Println()
|
||||||
|
part2(starting)
|
||||||
|
}
|
||||||
|
|
||||||
|
type player struct {
|
||||||
|
number int
|
||||||
|
position, score int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *player) move(spaces int) {
|
||||||
|
p.position = (p.position + spaces) % 10
|
||||||
|
if p.position == 0 {
|
||||||
|
p.position = 10
|
||||||
|
}
|
||||||
|
p.score += p.position
|
||||||
|
}
|
||||||
|
|
||||||
|
type die struct {
|
||||||
|
value int
|
||||||
|
rolls int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *die) roll() int {
|
||||||
|
d.rolls++
|
||||||
|
d.value++
|
||||||
|
if d.value > 100 {
|
||||||
|
d.value = 1
|
||||||
|
}
|
||||||
|
return d.value
|
||||||
|
}
|
||||||
|
|
||||||
|
func part1(pos []int) {
|
||||||
|
var players []player
|
||||||
|
for i := range pos {
|
||||||
|
players = append(players, player{number: i + 1, position: pos[i]})
|
||||||
|
}
|
||||||
|
die := die{value: 0}
|
||||||
|
pTurn := 0
|
||||||
|
for players[0].score < 1000 && players[1].score < 1000 {
|
||||||
|
turn := die.roll() + die.roll() + die.roll()
|
||||||
|
players[pTurn].move(turn)
|
||||||
|
pTurn = (pTurn + 1) % len(players)
|
||||||
|
}
|
||||||
|
var loser player
|
||||||
|
for i := range players {
|
||||||
|
if loser.number == 0 || players[i].score < loser.score {
|
||||||
|
loser = players[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("# Part 1")
|
||||||
|
fmt.Printf("Player %d loses, score %d\n", (loser.number), loser.score*die.rolls)
|
||||||
|
}
|
||||||
|
|
||||||
|
func part2(pos []int) {
|
||||||
|
var players []player
|
||||||
|
for i := range pos {
|
||||||
|
players = append(players, player{number: i + 1, position: pos[i]})
|
||||||
|
}
|
||||||
|
|
||||||
|
diracIt(pos[0], pos[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
type gameState struct {
|
||||||
|
p1, p2 int
|
||||||
|
s1, s2 int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the games with the dirac die.
|
||||||
|
func diracIt(p1, p2 int) {
|
||||||
|
move := func(pos, roll int) int {
|
||||||
|
pos += roll
|
||||||
|
pos = pos % 10
|
||||||
|
if pos == 0 {
|
||||||
|
return 10
|
||||||
|
}
|
||||||
|
return pos
|
||||||
|
}
|
||||||
|
|
||||||
|
states := map[gameState]int64{{p1, p2, 0, 0}: 1}
|
||||||
|
rolls := map[int]int64{}
|
||||||
|
for r1 := 1; r1 <= 3; r1++ {
|
||||||
|
for r2 := 1; r2 <= 3; r2++ {
|
||||||
|
for r3 := 1; r3 <= 3; r3++ {
|
||||||
|
rolls[r1+r2+r3] += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var p1w, p2w int64 = 0, 0
|
||||||
|
for len(states) != 0 {
|
||||||
|
for turn := 1; turn <= 2; turn++ {
|
||||||
|
nextStates := map[gameState]int64{}
|
||||||
|
for state, count := range states {
|
||||||
|
for roll, rCount := range rolls {
|
||||||
|
p1, p2 := state.p1, state.p2
|
||||||
|
s1, s2 := state.s1, state.s2
|
||||||
|
n := count * rCount
|
||||||
|
|
||||||
|
if turn == 1 {
|
||||||
|
p1 = move(p1, roll)
|
||||||
|
s1 += p1
|
||||||
|
if s1 > 20 {
|
||||||
|
p1w += n
|
||||||
|
} else {
|
||||||
|
nextStates[gameState{p1, p2, s1, s2}] += n
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p2 = move(p2, roll)
|
||||||
|
s2 += p2
|
||||||
|
if s2 > 20 {
|
||||||
|
p2w += n
|
||||||
|
} else {
|
||||||
|
nextStates[gameState{p1, p2, s1, s2}] += n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
states = nextStates
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("# Part 2")
|
||||||
|
fmt.Printf("Player 1 Wins: %d\nPlayer 2 Wins: %d\n", p1w, p2w)
|
||||||
|
}
|
2
2021/day21/testinput
Normal file
2
2021/day21/testinput
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Player 1 starting position: 4
|
||||||
|
Player 2 starting position: 8
|
Loading…
Reference in New Issue
Block a user