diff --git a/days/22.go b/days/22.go new file mode 100644 index 0000000..bb5f395 --- /dev/null +++ b/days/22.go @@ -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) +} diff --git a/inputs/22p.txt b/inputs/22p.txt new file mode 100644 index 0000000..d5400e3 --- /dev/null +++ b/inputs/22p.txt @@ -0,0 +1,100 @@ +deal into new stack +cut -2732 +deal into new stack +deal with increment 57 +cut 5974 +deal into new stack +deal with increment 32 +cut -1725 +deal with increment 24 +cut 6093 +deal with increment 6 +cut -2842 +deal with increment 14 +cut 2609 +deal with increment 12 +cut -6860 +deal with increment 51 +cut -6230 +deal with increment 61 +cut 3152 +deal with increment 28 +cut 2202 +deal into new stack +deal with increment 60 +cut 433 +deal into new stack +cut -6256 +deal with increment 13 +deal into new stack +cut 8379 +deal into new stack +deal with increment 54 +cut 1120 +deal with increment 16 +cut -5214 +deal with increment 63 +deal into new stack +cut -8473 +deal with increment 11 +cut 228 +deal with increment 45 +cut -6755 +deal with increment 50 +cut -3391 +deal with increment 44 +cut -1341 +deal with increment 28 +cut -6788 +deal with increment 52 +cut 3062 +deal with increment 41 +cut 4541 +deal with increment 57 +cut -7962 +deal with increment 56 +cut 9621 +deal with increment 57 +cut 3881 +deal with increment 36 +deal into new stack +deal with increment 45 +cut 522 +deal with increment 9 +deal into new stack +deal with increment 60 +deal into new stack +deal with increment 12 +cut -9181 +deal with increment 63 +deal into new stack +deal with increment 14 +cut -2906 +deal with increment 10 +cut 848 +deal with increment 75 +cut 798 +deal with increment 29 +cut 1412 +deal with increment 10 +deal into new stack +cut -5295 +deal into new stack +cut 4432 +deal with increment 72 +cut -7831 +deal into new stack +cut 6216 +deal into new stack +deal with increment 7 +cut -1720 +deal into new stack +cut -5465 +deal with increment 70 +cut -5173 +deal with increment 7 +cut 3874 +deal with increment 65 +cut 921 +deal with increment 8 +cut -3094 \ No newline at end of file diff --git a/inputs/22s1.txt b/inputs/22s1.txt new file mode 100644 index 0000000..7833d81 --- /dev/null +++ b/inputs/22s1.txt @@ -0,0 +1,3 @@ +deal with increment 7 +deal into new stack +deal into new stack \ No newline at end of file diff --git a/inputs/22s2.txt b/inputs/22s2.txt new file mode 100644 index 0000000..76569e3 --- /dev/null +++ b/inputs/22s2.txt @@ -0,0 +1,3 @@ +cut 6 +deal with increment 7 +deal into new stack \ No newline at end of file diff --git a/inputs/22s3.txt b/inputs/22s3.txt new file mode 100644 index 0000000..04c8a53 --- /dev/null +++ b/inputs/22s3.txt @@ -0,0 +1,3 @@ +deal with increment 7 +deal with increment 9 +cut -2 \ No newline at end of file diff --git a/inputs/22s4.txt b/inputs/22s4.txt new file mode 100644 index 0000000..4b79732 --- /dev/null +++ b/inputs/22s4.txt @@ -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 \ No newline at end of file diff --git a/main.go b/main.go index b6b82e1..4dcd6f1 100644 --- a/main.go +++ b/main.go @@ -55,6 +55,7 @@ var dayMap = []day{ &days.Day19{}, &days.Day20{}, &days.Day21{}, + &days.Day22{}, } func main() {