Merge pull request #1 from StevanFreeborn/stevanfreeborn/feat/solve-day-one-part-one

feat: solve day 1 part 1
This commit is contained in:
Stevan Freeborn
2025-12-01 07:50:53 -05:00
committed by GitHub
10 changed files with 297 additions and 3 deletions
+48
View File
@@ -0,0 +1,48 @@
// Package dial provides a model for representing a dial
package dial
import (
"github.com/StevanFreeborn/advent-of-code-2025/cmd/01/direction"
"github.com/StevanFreeborn/advent-of-code-2025/cmd/01/instruction"
)
type Dial interface {
Value() int
Turn(instruction instruction.Instruction)
}
type dial struct {
value int
}
func New() Dial {
return &dial{
value: 50,
}
}
func (d *dial) Value() int {
return d.value
}
func (d *dial) Turn(instruction instruction.Instruction) {
if instruction.Direction() == direction.Left {
d.value -= instruction.Distance()
for d.value < 0 {
d.value += 100
}
return
}
if instruction.Direction() == direction.Right {
d.value += instruction.Distance()
for d.value > 99 {
d.value -= 100
}
return
}
}
+78
View File
@@ -0,0 +1,78 @@
package dial_test
import (
"testing"
"github.com/StevanFreeborn/advent-of-code-2025/cmd/01/dial"
"github.com/StevanFreeborn/advent-of-code-2025/cmd/01/instruction"
)
func TestNew(t *testing.T) {
expectedStartingValue := 50
result := dial.New()
if result.Value() != expectedStartingValue {
t.Errorf("got unexpected beginning value. expected %d but got %d", expectedStartingValue, result.Value())
}
}
type TurnTestCase struct {
Instruction instruction.Instruction
ExpectedDialValue int
}
func TestTurn(t *testing.T) {
testCases := []TurnTestCase{
{
Instruction: instruction.FromParts("L", 68),
ExpectedDialValue: 82,
},
{
Instruction: instruction.FromParts("L", 30),
ExpectedDialValue: 52,
},
{
Instruction: instruction.FromParts("R", 48),
ExpectedDialValue: 0,
},
{
Instruction: instruction.FromParts("L", 5),
ExpectedDialValue: 95,
},
{
Instruction: instruction.FromParts("R", 60),
ExpectedDialValue: 55,
},
{
Instruction: instruction.FromParts("L", 55),
ExpectedDialValue: 0,
},
{
Instruction: instruction.FromParts("L", 1),
ExpectedDialValue: 99,
},
{
Instruction: instruction.FromParts("L", 99),
ExpectedDialValue: 0,
},
{
Instruction: instruction.FromParts("R", 14),
ExpectedDialValue: 14,
},
{
Instruction: instruction.FromParts("L", 82),
ExpectedDialValue: 32,
},
}
dial := dial.New()
for i, testCase := range testCases {
dial.Turn(testCase.Instruction)
if dial.Value() != testCase.ExpectedDialValue {
t.Errorf("%d: got dial value %d, but expected dial value %d", i, dial.Value(), testCase.ExpectedDialValue)
}
}
}
+5
View File
@@ -0,0 +1,5 @@
// Package direction provides constants for left and right directions.
package direction
const Left = "L"
const Right = "R"
+40
View File
@@ -0,0 +1,40 @@
// Package instruction provides a model for representing dial instructions
package instruction
import "strconv"
type Instruction interface {
Direction() string
Distance() int
}
type instruction struct {
direction string
distance int
}
func FromLine(line string) Instruction {
dir := string(line[0])
dist := line[1:]
distAsInt, _ := strconv.Atoi(dist)
return instruction{
direction: dir,
distance: distAsInt,
}
}
func FromParts(direction string, distance int) Instruction {
return instruction{
direction: direction,
distance: distance,
}
}
func (i instruction) Direction() string {
return i.direction
}
func (i instruction) Distance() int {
return i.distance
}
+39
View File
@@ -0,0 +1,39 @@
package instruction_test
import (
"fmt"
"testing"
"github.com/StevanFreeborn/advent-of-code-2025/cmd/01/instruction"
)
func TestFromLine(t *testing.T) {
expectedDirection := "L"
expectedDistance := 7
line := fmt.Sprintf("%s%d", expectedDirection, expectedDistance)
result := instruction.FromLine(line)
if result.Direction() != expectedDirection {
t.Errorf("got direction %s but expected direction %s", result.Direction(), expectedDirection)
}
if result.Distance() != expectedDistance {
t.Errorf("got distance %d but expected distance %d", result.Distance(), expectedDistance)
}
}
func TestFromParts(t *testing.T) {
expectedDirection := "L"
expectedDistance := 7
result := instruction.FromParts(expectedDirection, expectedDistance)
if result.Direction() != expectedDirection {
t.Errorf("got direction %s but expected direction %s", result.Direction(), expectedDirection)
}
if result.Distance() != expectedDistance {
t.Errorf("got distance %d but expected distance %d", result.Distance(), expectedDistance)
}
}
+24 -1
View File
@@ -1,5 +1,28 @@
package main
import (
"github.com/StevanFreeborn/advent-of-code-2025/cmd/01/dial"
"github.com/StevanFreeborn/advent-of-code-2025/cmd/01/instruction"
"github.com/StevanFreeborn/advent-of-code-2025/internal/file"
)
func SolvePartOne(filePath string) int {
return 0
lines := file.ReadLines(filePath)
dial := dial.New()
total := 0
for _, line := range lines {
if line == "" {
continue
}
instruction := instruction.FromLine(line)
dial.Turn(instruction)
if dial.Value() == 0 {
total++
}
}
return total
}
+12 -2
View File
@@ -7,11 +7,21 @@ import (
)
func TestSolvePartOneWithExampleInput(t *testing.T) {
expected := -1
expected := 3
result := solution.SolvePartOne("EXAMPLE.txt")
if result != expected {
t.Errorf("SolvePartOne() = %d; want %d", result, expected)
t.Errorf(`SolvePartOne("EXAMPLE.txt") = %d; want %d`, result, expected)
}
}
func TestSolvePartOneWithInput(t *testing.T) {
expected := 1011
result := solution.SolvePartOne("INPUT.txt")
if result != expected {
t.Errorf(`SolvePartOne("INPUT.txt") = %d; want %d`, result, expected)
}
}
+28
View File
@@ -0,0 +1,28 @@
// Package file provides useful methods for interacting with files
package file
import (
"bufio"
"fmt"
"os"
)
func ReadLines(filePath string) []string {
lines := []string{}
file, openErr := os.Open(filePath)
if openErr != nil {
return lines
}
scanner := bufio.NewScanner(file)
for hasLine := scanner.Scan(); hasLine; hasLine = scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
lines = append(lines, line)
}
return lines
}
+21
View File
@@ -0,0 +1,21 @@
package file_test
import (
"slices"
"testing"
"github.com/StevanFreeborn/advent-of-code-2025/internal/file"
)
func TestReadLines(t *testing.T) {
expectedLines := []string{
"hello",
"world",
}
result := file.ReadLines("test.txt")
if slices.Equal(result, expectedLines) == false {
t.Errorf("got %s but expected %s", result, expectedLines)
}
}
+2
View File
@@ -0,0 +1,2 @@
hello
world