Skip to content

Commit

Permalink
feat: Implement 2024 day01 solution (#334)
Browse files Browse the repository at this point in the history
* feat: Add 2024 year to constants

* feat: Add 2024/day01 initial code

* feat: Implement solution for 2024 day 1

* fix: Linter warnings in 2017 day 02
  • Loading branch information
obalunenko authored Dec 16, 2024
1 parent 66bb133 commit 4f6b4a8
Show file tree
Hide file tree
Showing 11 changed files with 742 additions and 10 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ SHELL := env APP_NAME=$(APP_NAME) $(SHELL)

SHELL := env GOTOOLS_IMAGE_TAG=$(GOTOOLS_IMAGE_TAG) $(SHELL)

AOC_PUZZLE_URL=
SHELL := env AOC_PUZZLE_URL=$(AOC_PUZZLE_URL) $(SHELL)

COMPOSE_TOOLS_FILE=deployments/docker-compose/go-tools-docker-compose.yml
COMPOSE_TOOLS_CMD_BASE=docker compose -f $(COMPOSE_TOOLS_FILE)
COMPOSE_TOOLS_CMD_UP=$(COMPOSE_TOOLS_CMD_BASE) up --exit-code-from
Expand Down
1 change: 1 addition & 0 deletions internal/puzzles/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const (
Year2021 // 2021
Year2022 // 2022
Year2023 // 2023
Year2024 // 2024

yearSentinel
)
Expand Down
14 changes: 7 additions & 7 deletions internal/puzzles/solutions/2017/day02/solution.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (s solution) Year() string {

func (s solution) Part1(input io.Reader) (string, error) {
var f checksumFunc = func(row []string) (int, error) {
var min, max int
var minVal, maxVal int

for i, number := range row {
d, err := strconv.Atoi(number)
Expand All @@ -37,19 +37,19 @@ func (s solution) Part1(input io.Reader) (string, error) {
}

if i == 0 {
min, max = d, d
minVal, maxVal = d, d
}

if d < min {
min = d
if d < minVal {
minVal = d
}

if d > max {
max = d
if d > maxVal {
maxVal = d
}
}

return max - min, nil
return maxVal - minVal, nil
}

return findChecksum(input, f)
Expand Down
126 changes: 126 additions & 0 deletions internal/puzzles/solutions/2024/day01/solution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Package day01 contains solution for https://adventofcode.com/2024/day/1 puzzle.
package day01

import (
"bufio"
"fmt"
"io"
"slices"
"strconv"
"strings"

"github.com/obalunenko/advent-of-code/internal/puzzles"
)

func init() {
puzzles.Register(solution{})
}

type solution struct{}

func (s solution) Year() string {
return puzzles.Year2024.String()
}

func (s solution) Day() string {
return puzzles.Day01.String()
}

func (s solution) Part1(input io.Reader) (string, error) {
l, err := parseInput(input)
if err != nil {
return "", fmt.Errorf("failed to parse input: %w", err)
}

slices.Sort(l.itemsA)
slices.Sort(l.itemsB)

var sum int

for i := 0; i < len(l.itemsA); i++ {
d := l.itemsA[i] - l.itemsB[i]
if d < 0 {
d = -d
}

sum += d
}

return strconv.Itoa(sum), nil
}

func (s solution) Part2(input io.Reader) (string, error) {
l, err := parseInput(input)
if err != nil {
return "", fmt.Errorf("failed to parse input: %w", err)
}

seenA := make(map[int]int)

for _, a := range l.itemsA {
seenA[a] = 0

for _, b := range l.itemsB {
if a == b {
seenA[a]++
}
}
}

var sum int

for _, a := range l.itemsA {
sum += a * seenA[a]
}

return strconv.Itoa(sum), nil
}

type lists struct {
itemsA []int
itemsB []int
}

func parseInput(input io.Reader) (lists, error) {
const (
listsNum = 2
listAIdx = 0
listBIdx = 1
)

l := lists{
itemsA: make([]int, 0),
itemsB: make([]int, 0),
}

scanner := bufio.NewScanner(input)
for scanner.Scan() {
line := scanner.Text()

parts := strings.Split(line, " ")
if len(parts) != listsNum {
return lists{}, fmt.Errorf("invalid input line: %s", line)
}

// Parse parts[0] and parts[1] to integers and append them to l.itemsA and l.itemsB respectively.
a, err := strconv.Atoi(parts[listAIdx])
if err != nil {
return lists{}, fmt.Errorf("failed to parse int: %w", err)
}

b, err := strconv.Atoi(parts[listBIdx])
if err != nil {
return lists{}, fmt.Errorf("failed to parse int: %w", err)
}

l.itemsA = append(l.itemsA, a)

l.itemsB = append(l.itemsB, b)
}

if scanner.Err() != nil {
return lists{}, fmt.Errorf("scanner error: %w", scanner.Err())
}

return l, nil
}
117 changes: 117 additions & 0 deletions internal/puzzles/solutions/2024/day01/solution_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package day01

import (
"errors"
"io"
"path/filepath"
"testing"
"testing/iotest"

"github.com/stretchr/testify/assert"

"github.com/obalunenko/advent-of-code/internal/puzzles/common/utils"
)

func Test_solution_Year(t *testing.T) {
var s solution

want := "2024"
got := s.Year()

assert.Equal(t, want, got)
}

func Test_solution_Day(t *testing.T) {
var s solution

want := "1"
got := s.Day()

assert.Equal(t, want, got)
}

func Test_solution_Part1(t *testing.T) {
var s solution

type args struct {
input io.Reader
}

tests := []struct {
name string
args args
want string
wantErr assert.ErrorAssertionFunc
}{
{
name: "test example from description",
args: args{
input: utils.ReaderFromFile(t, filepath.Join("testdata", "input.txt")),
},
want: "11",
wantErr: assert.NoError,
},
{
name: "",
args: args{
input: iotest.ErrReader(errors.New("custom error")),
},
want: "",
wantErr: assert.Error,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := s.Part1(tt.args.input)
if !tt.wantErr(t, err) {
return
}

assert.Equal(t, tt.want, got)
})
}
}

func Test_solution_Part2(t *testing.T) {
var s solution

type args struct {
input io.Reader
}

tests := []struct {
name string
args args
want string
wantErr assert.ErrorAssertionFunc
}{
{
name: "test example from description",
args: args{
input: utils.ReaderFromFile(t, filepath.Join("testdata", "input.txt")),
},
want: "31",
wantErr: assert.NoError,
},
{
name: "",
args: args{
input: iotest.ErrReader(errors.New("custom error")),
},
want: "",
wantErr: assert.Error,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := s.Part2(tt.args.input)
if !tt.wantErr(t, err) {
return
}

assert.Equal(t, tt.want, got)
})
}
}
Loading

0 comments on commit 4f6b4a8

Please sign in to comment.