From 1e269d7988d059f3a54e865a672c99606865ebf5 Mon Sep 17 00:00:00 2001 From: alexchao26 Date: Fri, 25 Dec 2020 00:48:10 -0500 Subject: [PATCH] 2020-day25: 2020 finished! "breaking" mock public key cryptography --- 2020/day25/main.go | 70 +++++++++++++++++++++++------------------ 2020/day25/main_test.go | 22 +++---------- 2 files changed, 43 insertions(+), 49 deletions(-) diff --git a/2020/day25/main.go b/2020/day25/main.go index bde80ba..dc62139 100644 --- a/2020/day25/main.go +++ b/2020/day25/main.go @@ -1,46 +1,54 @@ package main import ( - "flag" "fmt" "strings" - "github.com/alexchao26/advent-of-code-go/mathutil" + "github.com/alexchao26/advent-of-code-go/cast" "github.com/alexchao26/advent-of-code-go/util" ) func main() { - var part int - flag.IntVar(&part, "part", 1, "part 1 or 2") - flag.Parse() - fmt.Println("Running part", part) - - if part == 1 { - ans := part1(util.ReadFile("./input.txt")) - util.CopyToClipboard(fmt.Sprintf("%v", ans)) - fmt.Println("Output:", ans) - } else { - ans := part2(util.ReadFile("./input.txt")) - util.CopyToClipboard(fmt.Sprintf("%v", ans)) - fmt.Println("Output:", ans) - } + ans := part1(util.ReadFile("./input.txt")) + fmt.Println("Output:", ans) } +// ~1900.. func part1(input string) int { - parsed := parseInput(input) - _ = parsed - - return 0 -} - -func part2(input string) int { - return 0 -} - -func parseInput(input string) (ans []int) { - lines := strings.Split(input, "\n") - for _, l := range lines { - ans = append(ans, mathutil.StrToInt(l)) + var publicKeys []int + for _, l := range strings.Split(input, "\n") { + publicKeys = append(publicKeys, cast.ToInt(l)) } - return ans + + var loopSizes [2]int + val := 1 + // calculate both loop sizes in one pass to avoid recalculating over and over... + for loops := 1; loopSizes[0] == 0 || loopSizes[1] == 0; loops++ { + val *= 7 + val %= 20201227 + if val == publicKeys[0] { + loopSizes[0] = loops + } + if val == publicKeys[1] { + loopSizes[1] = loops + } + } + + // ensure both loop sizes are correct by reaching the same encryption key + key1 := runTranformations(publicKeys[0], loopSizes[1]) + key2 := runTranformations(publicKeys[1], loopSizes[0]) + if key1 != key2 { + panic(fmt.Sprintf("encryption keys should be the same, got %d and %d", key1, key2)) + } + + return key1 +} + +func runTranformations(subject, loops int) int { + val := 1 + for i := 0; i < loops; i++ { + val *= subject + val %= 20201227 + } + return val } diff --git a/2020/day25/main_test.go b/2020/day25/main_test.go index 22a4487..c8f0f4a 100644 --- a/2020/day25/main_test.go +++ b/2020/day25/main_test.go @@ -2,6 +2,8 @@ package main import ( "testing" + + "github.com/alexchao26/advent-of-code-go/util" ) func Test_part1(t *testing.T) { @@ -10,7 +12,8 @@ func Test_part1(t *testing.T) { input string want int }{ - // {"actual", util.ReadFile("input.txt"), ACTUAL_ANSWER}, + {"example", "5764801\n17807724", 14897079}, + {"actual", util.ReadFile("input.txt"), 18608573}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -20,20 +23,3 @@ func Test_part1(t *testing.T) { }) } } - -func Test_part2(t *testing.T) { - tests := []struct { - name string - input string - want int - }{ - // {"actual", util.ReadFile("input.txt"), ACTUAL_ANSWER}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := part2(tt.input); got != tt.want { - t.Errorf("part2() = %v, want %v", got, tt.want) - } - }) - } -}