Day 22 solution
Part 1 was very straightforward. I believe there are ways to calculate this answer without the complicated maths from part 2 and without actually applying each of the instructions, but I'm not concerned with finding it. Part 2 was a big "nope" from me. I went out and found this answer and I don't understand it. I'm okay with that.
This commit is contained in:
155
days/22.go
Normal file
155
days/22.go
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
package days
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
u "parnic.com/aoc2019/utilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type day22Instruction int
|
||||||
|
|
||||||
|
const (
|
||||||
|
day22InstructionNewStack day22Instruction = iota
|
||||||
|
day22InstructionCut
|
||||||
|
day22InstructionDealIncrement
|
||||||
|
)
|
||||||
|
|
||||||
|
type day22Shuffle struct {
|
||||||
|
instruction day22Instruction
|
||||||
|
arg int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Day22 struct {
|
||||||
|
shuffles []day22Shuffle
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day22) Parse() {
|
||||||
|
lines := u.GetStringLines("22p")
|
||||||
|
d.shuffles = make([]day22Shuffle, len(lines))
|
||||||
|
|
||||||
|
for idx, line := range lines {
|
||||||
|
split := strings.Split(line, " ")
|
||||||
|
if split[0] == "deal" {
|
||||||
|
if split[1] == "into" {
|
||||||
|
d.shuffles[idx] = day22Shuffle{instruction: day22InstructionNewStack}
|
||||||
|
} else if split[1] == "with" {
|
||||||
|
arg, err := strconv.Atoi(split[3])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
d.shuffles[idx] = day22Shuffle{
|
||||||
|
instruction: day22InstructionDealIncrement,
|
||||||
|
arg: arg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if split[0] == "cut" {
|
||||||
|
arg, err := strconv.Atoi(split[1])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
d.shuffles[idx] = day22Shuffle{
|
||||||
|
instruction: day22InstructionCut,
|
||||||
|
arg: arg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day22) Num() int {
|
||||||
|
return 22
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Day22) applyShuffle(s day22Shuffle, stack, scratch []int) {
|
||||||
|
switch s.instruction {
|
||||||
|
case day22InstructionNewStack:
|
||||||
|
for i := 0; i < len(stack)/2; i++ {
|
||||||
|
stack[i], stack[len(stack)-1-i] = stack[len(stack)-1-i], stack[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// there's probably a way to do these two in place...
|
||||||
|
case day22InstructionCut:
|
||||||
|
absArg := int(math.Abs(float64(s.arg)))
|
||||||
|
for i, v := range stack {
|
||||||
|
if s.arg > 0 {
|
||||||
|
if i < absArg {
|
||||||
|
scratch[len(scratch)-absArg+i] = v
|
||||||
|
} else {
|
||||||
|
scratch[i-absArg] = v
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if i < absArg {
|
||||||
|
scratch[i] = stack[len(stack)-absArg+i]
|
||||||
|
} else {
|
||||||
|
scratch[i] = stack[i-absArg]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copy(stack, scratch)
|
||||||
|
|
||||||
|
case day22InstructionDealIncrement:
|
||||||
|
for i, v := range stack {
|
||||||
|
scratch[(i*s.arg)%len(stack)] = v
|
||||||
|
}
|
||||||
|
copy(stack, scratch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day22) Part1() string {
|
||||||
|
deckSize := 10007
|
||||||
|
// deckSize := 10
|
||||||
|
|
||||||
|
stack := make([]int, deckSize)
|
||||||
|
for i := range stack {
|
||||||
|
stack[i] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch := make([]int, len(stack))
|
||||||
|
|
||||||
|
for _, s := range d.shuffles {
|
||||||
|
d.applyShuffle(s, stack, scratch)
|
||||||
|
}
|
||||||
|
|
||||||
|
pos := -1
|
||||||
|
for i, v := range stack {
|
||||||
|
if v == 2019 {
|
||||||
|
pos = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Card 2019 is at position %s%d%s", u.TextBold, pos, u.TextReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Day22) Part2() string {
|
||||||
|
n, iter := big.NewInt(119315717514047), big.NewInt(101741582076661)
|
||||||
|
offset, increment := big.NewInt(0), big.NewInt(1)
|
||||||
|
for _, s := range d.shuffles {
|
||||||
|
switch s.instruction {
|
||||||
|
case day22InstructionNewStack:
|
||||||
|
increment.Mul(increment, big.NewInt(-1))
|
||||||
|
offset.Add(offset, increment)
|
||||||
|
case day22InstructionCut:
|
||||||
|
offset.Add(offset, big.NewInt(0).Mul(big.NewInt(int64(s.arg)), increment))
|
||||||
|
case day22InstructionDealIncrement:
|
||||||
|
increment.Mul(increment, big.NewInt(0).Exp(big.NewInt(int64(s.arg)), big.NewInt(0).Sub(n, big.NewInt(2)), n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finalIncr := big.NewInt(0).Exp(increment, iter, n)
|
||||||
|
|
||||||
|
finalOffs := big.NewInt(0).Exp(increment, iter, n)
|
||||||
|
finalOffs.Sub(big.NewInt(1), finalOffs)
|
||||||
|
invmod := big.NewInt(0).Exp(big.NewInt(0).Sub(big.NewInt(1), increment), big.NewInt(0).Sub(n, big.NewInt(2)), n)
|
||||||
|
finalOffs.Mul(finalOffs, invmod)
|
||||||
|
finalOffs.Mul(finalOffs, offset)
|
||||||
|
|
||||||
|
answer := big.NewInt(0).Mul(big.NewInt(2020), finalIncr)
|
||||||
|
answer.Add(answer, finalOffs)
|
||||||
|
answer.Mod(answer, n)
|
||||||
|
|
||||||
|
return fmt.Sprintf("Card at position 2020: %s%d%s", u.TextBold, answer, u.TextReset)
|
||||||
|
}
|
100
inputs/22p.txt
Normal file
100
inputs/22p.txt
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
cut 578
|
||||||
|
deal with increment 25
|
||||||
|
cut -3085
|
||||||
|
deal with increment 16
|
||||||
|
cut -6620
|
||||||
|
deal with increment 17
|
||||||
|
cut -1305
|
||||||
|
deal with increment 71
|
||||||
|
cut -4578
|
||||||
|
deal with increment 44
|
||||||
|
cut 5639
|
||||||
|
deal with increment 74
|
||||||
|
deal into new stack
|
||||||
|
deal with increment 39
|
||||||
|
cut 7888
|
||||||
|
deal with increment 17
|
||||||
|
deal into new stack
|
||||||
|
cut 6512
|
||||||
|
deal with increment 46
|
||||||
|
cut -8989
|
||||||
|
deal with increment 46
|
||||||
|
cut -8518
|
||||||
|
deal with increment 75
|
||||||
|
cut -870
|
||||||
|
deal into new stack
|
||||||
|
deal with increment 53
|
||||||
|
cut 7377
|
||||||
|
deal with increment 60
|
||||||
|
cut -4733
|
||||||
|
deal with increment 25
|
||||||
|
cut -6914
|
||||||
|
deal with increment 23
|
||||||
|
cut -4379
|
||||||
|
deal into new stack
|
||||||
|
cut 582
|
||||||
|
deal with increment 35
|
||||||
|
cut 9853
|
||||||
|
deal with increment 2
|
||||||
|
cut -142
|
||||||
|
deal with increment 74
|
||||||
|
cut 328
|
||||||
|
deal into new stack
|
||||||
|
deal with increment 75
|
||||||
|
deal into new stack
|
||||||
|
cut -8439
|
||||||
|
deal into new stack
|
||||||
|
deal with increment 34
|
||||||
|
cut 2121
|
||||||
|
deal with increment 2
|
||||||
|
cut 8335
|
||||||
|
deal with increment 65
|
||||||
|
cut -1254
|
||||||
|
deal into new stack
|
||||||
|
cut -122
|
||||||
|
deal with increment 75
|
||||||
|
cut -9227
|
||||||
|
deal into new stack
|
||||||
|
deal with increment 24
|
||||||
|
cut 3976
|
||||||
|
deal into new stack
|
||||||
|
deal with increment 8
|
||||||
|
cut -3292
|
||||||
|
deal with increment 4
|
||||||
|
deal into new stack
|
||||||
|
cut -8851
|
||||||
|
deal with increment 2
|
||||||
|
deal into new stack
|
||||||
|
cut 4333
|
||||||
|
deal with increment 73
|
||||||
|
deal into new stack
|
||||||
|
deal with increment 9
|
||||||
|
cut -7880
|
||||||
|
deal with increment 49
|
||||||
|
cut 9770
|
||||||
|
deal with increment 30
|
||||||
|
cut 2701
|
||||||
|
deal with increment 59
|
||||||
|
cut 4292
|
||||||
|
deal with increment 37
|
||||||
|
deal into new stack
|
||||||
|
cut -184
|
||||||
|
deal with increment 25
|
||||||
|
cut 9907
|
||||||
|
deal with increment 46
|
||||||
|
deal into new stack
|
||||||
|
cut 902
|
||||||
|
deal with increment 46
|
||||||
|
cut 2622
|
||||||
|
deal into new stack
|
||||||
|
cut 637
|
||||||
|
deal with increment 58
|
||||||
|
cut 7354
|
||||||
|
deal with increment 69
|
||||||
|
deal into new stack
|
||||||
|
deal with increment 49
|
||||||
|
deal into new stack
|
||||||
|
deal with increment 19
|
||||||
|
cut -8342
|
||||||
|
deal with increment 68
|
||||||
|
deal into new stack
|
3
inputs/22s1.txt
Normal file
3
inputs/22s1.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
deal with increment 7
|
||||||
|
deal into new stack
|
||||||
|
deal into new stack
|
3
inputs/22s2.txt
Normal file
3
inputs/22s2.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
cut 6
|
||||||
|
deal with increment 7
|
||||||
|
deal into new stack
|
3
inputs/22s3.txt
Normal file
3
inputs/22s3.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
deal with increment 7
|
||||||
|
deal with increment 9
|
||||||
|
cut -2
|
10
inputs/22s4.txt
Normal file
10
inputs/22s4.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
deal into new stack
|
||||||
|
cut -2
|
||||||
|
deal with increment 7
|
||||||
|
cut 8
|
||||||
|
cut -4
|
||||||
|
deal with increment 7
|
||||||
|
cut 3
|
||||||
|
deal with increment 9
|
||||||
|
deal with increment 3
|
||||||
|
cut -1
|
Reference in New Issue
Block a user