♻️ Refactored whole repo contents into testable puzzle modules
This commit is contained in:
parent
6910155f91
commit
58a0fbf077
|
@ -0,0 +1,77 @@
|
|||
package adventofcode_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day1/part1"
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day1/part2"
|
||||
)
|
||||
|
||||
/*
|
||||
Something is wrong with global snow production, and you've been selected to take
|
||||
a look. The Elves have even given you a map; on it, they've used stars to mark
|
||||
the top fifty locations that are likely to be having problems.
|
||||
|
||||
You've been doing this long enough to know that to restore snow operations, you
|
||||
need to check all fifty stars by December 25th.
|
||||
|
||||
Collect stars by solving puzzles. Two puzzles will be made available on each day
|
||||
in the Advent calendar; the second puzzle is unlocked when you complete the
|
||||
first. Each puzzle grants one star. Good luck!
|
||||
|
||||
You try to ask why they can't just use a weather machine ("not powerful enough")
|
||||
and where they're even sending you ("the sky") and why your map looks mostly
|
||||
blank ("you sure ask a lot of questions") and hang on did you just say the sky
|
||||
("of course, where do you think snow comes from") when you realize that the
|
||||
Elves are already loading you into a trebuchet ("please hold still, we need to
|
||||
strap you in").
|
||||
|
||||
As they're making the final adjustments, they discover that their calibration
|
||||
document (your puzzle input) has been amended by a very young Elf who was
|
||||
apparently just excited to show off her art skills. Consequently, the Elves are
|
||||
having trouble reading the values on the document.
|
||||
|
||||
Consider your entire calibration document. What is the sum of all of the
|
||||
calibration values?
|
||||
*/
|
||||
func ExampleDay1() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day1", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
result, err := part1.Calibrate(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot sum all calibration values:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 54601
|
||||
}
|
||||
|
||||
/*
|
||||
Your calculation isn't quite right.
|
||||
|
||||
Equipped with this new information, you now need to find the real first and last
|
||||
digit on each line.
|
||||
|
||||
What is the sum of all of the calibration values?
|
||||
*/
|
||||
func ExampleDay1_PartTwo() {
|
||||
input, err := os.ReadFile(filepath.Join("internal", "day1", "testdata", "input"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
result, err := part2.Calibrate(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot sum all calibration values:", err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
// Output: 54078
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
// Package provides attempts and solutions for Advent Of Code 2023 puzzles:
|
||||
// https://adventofcode.com/2023
|
||||
package adventofcode
|
|
@ -0,0 +1,54 @@
|
|||
package part1
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Calibrate(r io.Reader) (uint, error) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
|
||||
var sum uint
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
calVal, err := makeCalibrationValue(strings.NewReader(line))
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot make calibration value from '%s': %w", line, err)
|
||||
}
|
||||
|
||||
sum += uint(calVal)
|
||||
}
|
||||
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
func makeCalibrationValue(r io.Reader) (uint8, error) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
scanner.Split(bufio.ScanRunes)
|
||||
|
||||
parts := make([]rune, 0)
|
||||
for scanner.Scan() {
|
||||
text := scanner.Bytes()
|
||||
|
||||
switch text[0] {
|
||||
default:
|
||||
continue
|
||||
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
parts = append(parts, rune(text[0]))
|
||||
}
|
||||
}
|
||||
|
||||
digit := fmt.Sprintf("%c%c", parts[0], parts[len(parts)-1])
|
||||
|
||||
result, err := strconv.ParseUint(digit, 10, 8)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot parse '%s' as calibration value number: %w", digit, err)
|
||||
}
|
||||
|
||||
return uint8(result), nil
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package part1_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day1/part1"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
var sum uint = 0
|
||||
|
||||
// The newly-improved calibration document consists of lines of text;
|
||||
// each line originally contained a specific calibration value that the
|
||||
// Elves now need to recover. On each line, the calibration value can be
|
||||
// found by combining the first digit and the last digit (in that order)
|
||||
// to form a single two-digit number.
|
||||
for _, exampleLine := range []string{
|
||||
"1abc2",
|
||||
"pqr3stu8vwx",
|
||||
"a1b2c3d4e5f",
|
||||
"treb7uchet",
|
||||
} {
|
||||
calibrationValue, err := part1.Calibrate(strings.NewReader(exampleLine))
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
sum += calibrationValue
|
||||
|
||||
fmt.Println(calibrationValue)
|
||||
}
|
||||
|
||||
// Adding these together produces 142.
|
||||
fmt.Println(sum)
|
||||
|
||||
// Output:
|
||||
// 12
|
||||
// 38
|
||||
// 15
|
||||
// 77
|
||||
// 142
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package part2
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
@ -8,23 +8,23 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
func Trebuchet(r io.Reader) (uint, error) {
|
||||
func Calibrate(r io.Reader) (uint, error) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
|
||||
var total uint
|
||||
var sum uint
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
calibrationValue, err := makeCalibrationValue(strings.NewReader(line))
|
||||
calVal, err := makeCalibrationValue(strings.NewReader(line))
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot make calibration value from '%s': %w", line, err)
|
||||
}
|
||||
|
||||
total += uint(calibrationValue)
|
||||
sum += uint(calVal)
|
||||
}
|
||||
|
||||
return total, nil
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
func makeCalibrationValue(r io.Reader) (uint8, error) {
|
|
@ -0,0 +1,47 @@
|
|||
package part2_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"source.toby3d.me/toby3d/adventofcode/internal/day1/part2"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
var sum uint = 0
|
||||
|
||||
// It looks like some of the digits are actually spelled out with
|
||||
// letters: one, two, three, four, five, six, seven, eight, and nine
|
||||
// also count as valid "digits".
|
||||
for _, exampleLine := range []string{
|
||||
"two1nine",
|
||||
"eightwothree",
|
||||
"abcone2threexyz",
|
||||
"xtwone3four",
|
||||
"4nineeightseven2",
|
||||
"zoneight234",
|
||||
"7pqrstsixteen",
|
||||
} {
|
||||
calibrationValue, err := part2.Calibrate(strings.NewReader(exampleLine))
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
sum += calibrationValue
|
||||
|
||||
fmt.Println(calibrationValue)
|
||||
}
|
||||
|
||||
fmt.Println(sum)
|
||||
|
||||
// Output:
|
||||
// 29
|
||||
// 83
|
||||
// 13
|
||||
// 24
|
||||
// 42
|
||||
// 14
|
||||
// 76
|
||||
// 281
|
||||
}
|
22
main.go
22
main.go
|
@ -1,22 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func main() {
|
||||
input, err := os.ReadFile(filepath.Join("testdata", "input1.txt"))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot open input file:", err)
|
||||
}
|
||||
|
||||
result, err := Trebuchet(bytes.NewReader(input))
|
||||
if err != nil {
|
||||
log.Fatalln("cannot sum all calibration values:", err)
|
||||
}
|
||||
|
||||
log.Println(result)
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTrebuchet(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for name, tc := range map[string]struct {
|
||||
input string
|
||||
expect uint
|
||||
}{
|
||||
"mixed": {input: "two1nine", expect: 29},
|
||||
"edges": {input: "eightwothree", expect: 83},
|
||||
"inner": {input: "abcone2threexyz", expect: 13},
|
||||
"suffix": {input: "xtwone3four", expect: 24},
|
||||
"numbers": {input: "4nineeightseven2", expect: 42},
|
||||
"race": {input: "zoneight234", expect: 14},
|
||||
"more": {input: "7pqrstsixteen", expect: 76},
|
||||
"everything": {
|
||||
input: "two1nine\n" +
|
||||
"eightwothree\n" +
|
||||
"abcone2threexyz\n" +
|
||||
"xtwone3four\n" +
|
||||
"4nineeightseven2\n" +
|
||||
"zoneight234\n" +
|
||||
"7pqrstsixteen",
|
||||
expect: 281,
|
||||
},
|
||||
} {
|
||||
name, tc := name, tc
|
||||
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
actual, err := Trebuchet(strings.NewReader(tc.input))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if tc.expect != actual {
|
||||
t.Errorf("want %d, got %d", tc.expect, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue