From c3c1fe8b3aa0a4a7b40edfccfbb033cf4b464a24 Mon Sep 17 00:00:00 2001 From: Katherina Walshe-Grey Date: Mon, 28 Oct 2024 18:12:11 +0000 Subject: [PATCH 1/5] go environment setup --- go.mod | 3 +++ shell.nix | 10 ++++++++++ 2 files changed, 13 insertions(+) create mode 100644 go.mod create mode 100644 shell.nix diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..00f0358 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.qenya.tel/qenya/aoc2023 + +go 1.23.2 diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..8303b75 --- /dev/null +++ b/shell.nix @@ -0,0 +1,10 @@ +let + pkgs = import {}; +in pkgs.mkShell { + packages = with pkgs; [ + go + ]; + shellHook = '' + export PATH=$PATH:~/go/bin + ''; +} \ No newline at end of file From 255c191dfced434c759062fc6aecb14000f1f538 Mon Sep 17 00:00:00 2001 From: Katherina Walshe-Grey Date: Mon, 28 Oct 2024 18:12:20 +0000 Subject: [PATCH 2/5] day 1a --- day01/day01.go | 39 +++++++++++++++++++++++++++++++++++++++ day01/day01_test.go | 31 +++++++++++++++++++++++++++++++ day01/input1.txt | 4 ++++ 3 files changed, 74 insertions(+) create mode 100644 day01/day01.go create mode 100644 day01/day01_test.go create mode 100644 day01/input1.txt diff --git a/day01/day01.go b/day01/day01.go new file mode 100644 index 0000000..7a6efda --- /dev/null +++ b/day01/day01.go @@ -0,0 +1,39 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +func getCalibrationValue(input string) int { + firstIdx := strings.IndexAny(input, "0123456789") + lastIdx := strings.LastIndexAny(input, "0123456789") + first := string([]rune(input)[firstIdx]) + last := string([]rune(input)[lastIdx]) + output, _ := strconv.Atoi(first + last) + return output +} + +func ScanFile(file *os.File) (int, error) { + scanner := bufio.NewScanner(file); + sum := 0; + for scanner.Scan() { + sum += getCalibrationValue(scanner.Text()); + } + if err := scanner.Err(); err != nil { + return 0, err + } + return sum, nil +} + +func main() { + sum, err := ScanFile(os.Stdin) + if err != nil { + fmt.Fprintf(os.Stderr, "Invalid input: %s\n", err) + return + } + fmt.Println(sum) +} \ No newline at end of file diff --git a/day01/day01_test.go b/day01/day01_test.go new file mode 100644 index 0000000..95e50e9 --- /dev/null +++ b/day01/day01_test.go @@ -0,0 +1,31 @@ +package main + +import ( + "os" + "testing" +) + +func TestScanFile(t *testing.T) { + cases := []struct { + inFile string; + want int; + }{ + {"input1.txt", 142}, + } + + for _, c := range cases { + f, err := os.Open(c.inFile) + if err != nil { + t.Fatal(err) + } + + got, err := ScanFile(f) + if err != nil { + t.Fatal(err) + } + + if got != c.want { + t.Errorf("ScanFile(%q) == %q, want %q", c.inFile, got, c.want) + } + } +} \ No newline at end of file diff --git a/day01/input1.txt b/day01/input1.txt new file mode 100644 index 0000000..7bbc69a --- /dev/null +++ b/day01/input1.txt @@ -0,0 +1,4 @@ +1abc2 +pqr3stu8vwx +a1b2c3d4e5f +treb7uchet From 399e40a6f9f162b46cc37f2c3be0532e52552891 Mon Sep 17 00:00:00 2001 From: Katherina Walshe-Grey Date: Mon, 28 Oct 2024 19:58:56 +0000 Subject: [PATCH 3/5] Day 1b --- day01/day01.go | 44 ++++++++++++++++++++++++++++++++++++++++---- day01/day01_test.go | 3 ++- day01/input2.txt | 7 +++++++ 3 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 day01/input2.txt diff --git a/day01/day01.go b/day01/day01.go index 7a6efda..9b0505f 100644 --- a/day01/day01.go +++ b/day01/day01.go @@ -8,11 +8,47 @@ import ( "strings" ) +const digits = "0123456789" + +func words() [10]string { + return [10]string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"} +} + +func firstDigit(input string) string { + var result string + loc := len(input) + if index := strings.IndexAny(input, "0123456789"); index != -1 { + loc = index + result = string([]rune(input)[index]) + } + for key, value := range words() { + if index := strings.Index(input, value); index != -1 && index <= loc { + loc = index + result = strconv.Itoa(key) + } + } + return result +} + +func lastDigit(input string) string { + var result string + loc := -1 + if index := strings.LastIndexAny(input, "0123456789"); index != -1 { + loc = index + result = string([]rune(input)[index]) + } + for key, value := range words() { + if index := strings.LastIndex(input, value); index != -1 && index >= loc { + loc = index + result = strconv.Itoa(key) + } + } + return result +} + func getCalibrationValue(input string) int { - firstIdx := strings.IndexAny(input, "0123456789") - lastIdx := strings.LastIndexAny(input, "0123456789") - first := string([]rune(input)[firstIdx]) - last := string([]rune(input)[lastIdx]) + first := firstDigit(input) + last := lastDigit(input) output, _ := strconv.Atoi(first + last) return output } diff --git a/day01/day01_test.go b/day01/day01_test.go index 95e50e9..141ab87 100644 --- a/day01/day01_test.go +++ b/day01/day01_test.go @@ -11,6 +11,7 @@ func TestScanFile(t *testing.T) { want int; }{ {"input1.txt", 142}, + {"input2.txt", 281}, } for _, c := range cases { @@ -25,7 +26,7 @@ func TestScanFile(t *testing.T) { } if got != c.want { - t.Errorf("ScanFile(%q) == %q, want %q", c.inFile, got, c.want) + t.Errorf("ScanFile(%q) == %d, want %d", c.inFile, got, c.want) } } } \ No newline at end of file diff --git a/day01/input2.txt b/day01/input2.txt new file mode 100644 index 0000000..4316a6b --- /dev/null +++ b/day01/input2.txt @@ -0,0 +1,7 @@ +two1nine +eightwothree +abcone2threexyz +xtwone3four +4nineeightseven2 +zoneight234 +7pqrstsixteen \ No newline at end of file From 7e3b20a8c87f203313469d7af6ee759222d5c453 Mon Sep 17 00:00:00 2001 From: Katherina Walshe-Grey Date: Mon, 28 Oct 2024 20:19:56 +0000 Subject: [PATCH 4/5] day 1: misc idiomaticness --- day01/day01.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/day01/day01.go b/day01/day01.go index 9b0505f..69c603a 100644 --- a/day01/day01.go +++ b/day01/day01.go @@ -46,7 +46,7 @@ func lastDigit(input string) string { return result } -func getCalibrationValue(input string) int { +func calibration(input string) int { first := firstDigit(input) last := lastDigit(input) output, _ := strconv.Atoi(first + last) @@ -54,10 +54,10 @@ func getCalibrationValue(input string) int { } func ScanFile(file *os.File) (int, error) { - scanner := bufio.NewScanner(file); - sum := 0; + scanner := bufio.NewScanner(file) + sum := 0 for scanner.Scan() { - sum += getCalibrationValue(scanner.Text()); + sum += calibration(scanner.Text()) } if err := scanner.Err(); err != nil { return 0, err From 8b6ea615f7793d0e17434184196565a601a22a7d Mon Sep 17 00:00:00 2001 From: Katherina Walshe-Grey Date: Mon, 4 Nov 2024 19:18:21 +0000 Subject: [PATCH 5/5] Day 2a --- day02/day02.go | 82 +++++++++++++++++++++++++++++++++++++++++++++ day02/day02_test.go | 31 +++++++++++++++++ day02/input1.txt | 5 +++ 3 files changed, 118 insertions(+) create mode 100644 day02/day02.go create mode 100644 day02/day02_test.go create mode 100644 day02/input1.txt diff --git a/day02/day02.go b/day02/day02.go new file mode 100644 index 0000000..cd0d465 --- /dev/null +++ b/day02/day02.go @@ -0,0 +1,82 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +type Game struct { + id int + sets []Set +} + +type Set struct { + red int + green int + blue int +} + +func parseGame(input string) Game { + idStr, setsStr, _ := strings.Cut(input, ": ") + + var game Game + var err error + + game.id, err = strconv.Atoi(strings.TrimPrefix(idStr, "Game ")) + + for i, setStr := range strings.Split(setsStr, "; ") { + game.sets = append(game.sets, Set{}) + for _, colorStr := range strings.Split(setStr, ", ") { + if strings.HasSuffix(colorStr, " red") { + game.sets[i].red, err = strconv.Atoi(strings.TrimSuffix(colorStr, " red")) + } + if strings.HasSuffix(colorStr, " green") { + game.sets[i].green, err = strconv.Atoi(strings.TrimSuffix(colorStr, " green")) + } + if strings.HasSuffix(colorStr, " blue") { + game.sets[i].blue, err = strconv.Atoi(strings.TrimSuffix(colorStr, " blue")) + } + } + } + + if err != nil { + panic("day02: invalid game format") + } + + return game +} + +func isGameValid(game Game) bool { + for _, set := range game.sets { + if set.red > 12 || set.green > 13 || set.blue > 14 { + return false + } + } + return true +} + +func ScanFile(file *os.File) (int, error) { + scanner := bufio.NewScanner(file) + sum := 0 + for scanner.Scan() { + if game := parseGame(scanner.Text()); isGameValid(game) { + sum += game.id + } + } + if err := scanner.Err(); err != nil { + return 0, err + } + return sum, nil +} + +func main() { + sum, err := ScanFile(os.Stdin) + if err != nil { + fmt.Fprintf(os.Stderr, "Invalid input: %s\n", err) + return + } + fmt.Println(sum) +} \ No newline at end of file diff --git a/day02/day02_test.go b/day02/day02_test.go new file mode 100644 index 0000000..923b84c --- /dev/null +++ b/day02/day02_test.go @@ -0,0 +1,31 @@ +package main + +import ( + "os" + "testing" +) + +func TestScanFile(t *testing.T) { + cases := []struct { + inFile string; + want int; + }{ + {"input1.txt", 8}, + } + + for _, c := range cases { + f, err := os.Open(c.inFile) + if err != nil { + t.Fatal(err) + } + + got, err := ScanFile(f) + if err != nil { + t.Fatal(err) + } + + if got != c.want { + t.Errorf("ScanFile(%q) == %d, want %d", c.inFile, got, c.want) + } + } +} \ No newline at end of file diff --git a/day02/input1.txt b/day02/input1.txt new file mode 100644 index 0000000..1cd7d33 --- /dev/null +++ b/day02/input1.txt @@ -0,0 +1,5 @@ +Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green \ No newline at end of file