From 4175778d526199b4aa8f2d3bcb79261f75fad457 Mon Sep 17 00:00:00 2001 From: Parnic Date: Tue, 19 Jul 2022 13:29:19 -0500 Subject: [PATCH] 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. --- days/22.go | 155 ++++++++++++++++++++++++++++++++++++++++++++++++ inputs/22p.txt | 100 +++++++++++++++++++++++++++++++ inputs/22s1.txt | 3 + inputs/22s2.txt | 3 + inputs/22s3.txt | 3 + inputs/22s4.txt | 10 ++++ main.go | 1 + 7 files changed, 275 insertions(+) create mode 100644 days/22.go create mode 100644 inputs/22p.txt create mode 100644 inputs/22s1.txt create mode 100644 inputs/22s2.txt create mode 100644 inputs/22s3.txt create mode 100644 inputs/22s4.txt 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..e9d2144 --- /dev/null +++ b/inputs/22p.txt @@ -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 \ 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() {