Merge pull request #1 from StevanFreeborn/stevanfreeborn/feat/solve-day-one-part-one
feat: solve day 1 part 1
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Package direction provides constants for left and right directions.
|
||||
package direction
|
||||
|
||||
const Left = "L"
|
||||
const Right = "R"
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
hello
|
||||
world
|
||||
Reference in New Issue
Block a user