Intitial project scaffolding & day 1 solution
This commit is contained in:
commit
fccc444b53
|
|
@ -0,0 +1,2 @@
|
|||
aoc2022
|
||||
.idea
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package day1_calorie_counting
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Solver struct {
|
||||
elves [][]int
|
||||
}
|
||||
|
||||
func (s *Solver) ParseInput(input []string) {
|
||||
elves := make([][]int, 0)
|
||||
|
||||
elfIndex := 0
|
||||
elves = append(elves, make([]int, 0))
|
||||
for _, line := range input {
|
||||
if line == "" {
|
||||
elfIndex += 1
|
||||
elves = append(elves, make([]int, 0))
|
||||
} else {
|
||||
n, _ := strconv.Atoi(line)
|
||||
elves[elfIndex] = append(elves[elfIndex], n)
|
||||
}
|
||||
}
|
||||
|
||||
s.elves = elves
|
||||
}
|
||||
|
||||
func (s *Solver) SolvePart1() int {
|
||||
mostCalories := 0
|
||||
for _, calories := range s.elves {
|
||||
sum := 0
|
||||
for _, c := range calories {
|
||||
sum += c
|
||||
}
|
||||
if sum > mostCalories {
|
||||
mostCalories = sum
|
||||
}
|
||||
}
|
||||
return mostCalories
|
||||
}
|
||||
|
||||
func (s *Solver) SolvePart2() int {
|
||||
caloriesPerElf := make([]int, len(s.elves))
|
||||
for i, calories := range s.elves {
|
||||
sum := 0
|
||||
for _, c := range calories {
|
||||
sum += c
|
||||
}
|
||||
caloriesPerElf[i] = sum
|
||||
}
|
||||
sort.Ints(caloriesPerElf)
|
||||
|
||||
top3sum := 0
|
||||
for i := len(caloriesPerElf) - 3; i < len(caloriesPerElf); i++ {
|
||||
top3sum += caloriesPerElf[i]
|
||||
}
|
||||
return top3sum
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package day1_calorie_counting
|
||||
|
||||
import (
|
||||
"snikolov.me/aoc2022/testutils"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCorrectSolutions(t *testing.T) {
|
||||
solver := &Solver{}
|
||||
testutils.TestHelper(t, solver, 1, true, 24000, 45000)
|
||||
testutils.TestHelper(t, solver, 1, false, 66306, 195292)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,14 @@
|
|||
1000
|
||||
2000
|
||||
3000
|
||||
|
||||
4000
|
||||
|
||||
5000
|
||||
6000
|
||||
|
||||
7000
|
||||
8000
|
||||
9000
|
||||
|
||||
10000
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
day1_calorie_counting "snikolov.me/aoc2022/day1"
|
||||
"snikolov.me/aoc2022/utils"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Args struct {
|
||||
DayNumber int
|
||||
PartNumber int
|
||||
TestMode bool
|
||||
DownloadInput bool
|
||||
}
|
||||
|
||||
func main() {
|
||||
var args Args
|
||||
flag.IntVar(&args.DayNumber, "day", 0, "day number")
|
||||
flag.IntVar(&args.PartNumber, "part", 0, "day part number")
|
||||
flag.BoolVar(&args.TestMode, "test", false, "use test input")
|
||||
flag.BoolVar(&args.DownloadInput, "download-input", false, "download production input")
|
||||
flag.Parse()
|
||||
|
||||
inputFileName := utils.GetInputFileName(args.DayNumber, args.TestMode)
|
||||
|
||||
if args.DownloadInput {
|
||||
const sessionCookie = "53616c7465645f5f63d2a07212d6266c5e8de3664d5684dac31a6031e5ddf4c1ec004e5475bf45a16c9f9919fae43b7344135650408c9aec716880afd94bbc0b"
|
||||
if err := utils.DownloadInput(sessionCookie, args.DayNumber, inputFileName); err != nil {
|
||||
log.Fatalf("Could not download puzzle input: %s", err)
|
||||
}
|
||||
} else {
|
||||
solve(args, inputFileName)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func solve(args Args, inputFileName string) {
|
||||
solvers := map[int]utils.Solver{
|
||||
1: &day1_calorie_counting.Solver{},
|
||||
}
|
||||
solver, ok := solvers[args.DayNumber]
|
||||
if !ok {
|
||||
log.Fatalf("Could not find a solver for day %d", args.DayNumber)
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
|
||||
if input, err := utils.ReadInput(inputFileName); err == nil {
|
||||
solver.ParseInput(input)
|
||||
} else {
|
||||
log.Fatalf("Could not read input for day %d: %s", args.DayNumber, err)
|
||||
}
|
||||
|
||||
var solution int
|
||||
switch args.PartNumber {
|
||||
case 1:
|
||||
solution = solver.SolvePart1()
|
||||
case 2:
|
||||
solution = solver.SolvePart2()
|
||||
default:
|
||||
log.Fatal("unknown part number, please use 1 or 2")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("%s: %d\n", time.Now().Sub(startTime), solution)
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package testutils
|
||||
|
||||
import (
|
||||
"snikolov.me/aoc2022/utils"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHelper(t *testing.T, solver utils.Solver, dayNumber int, testMode bool, solutionPart1, solutionPart2 int) {
|
||||
testInput, err := utils.ReadInput("../" + utils.GetInputFileName(dayNumber, testMode))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
solver.ParseInput(testInput)
|
||||
if result := solver.SolvePart1(); result != solutionPart1 {
|
||||
t.Errorf("wrong output for day %d part 1, test = %v: %d != %d", dayNumber, testMode, result, solutionPart1)
|
||||
}
|
||||
if result := solver.SolvePart2(); result != solutionPart2 {
|
||||
t.Errorf("wrong output for day %d part 2, test = %v: %d != %d", dayNumber, testMode, result, solutionPart1)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Solver interface {
|
||||
ParseInput(input []string)
|
||||
SolvePart1() int
|
||||
SolvePart2() int
|
||||
}
|
||||
|
||||
func ReadInput(inputFileName string) ([]string, error) {
|
||||
var input = make([]string, 0)
|
||||
|
||||
reader, err := os.Open(inputFileName)
|
||||
if err != nil {
|
||||
return input, fmt.Errorf("failed to open input file: %w", err)
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(reader)
|
||||
for scanner.Scan() {
|
||||
input = append(input, scanner.Text())
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func GetInputFileName(dayNumber int, testMode bool) string {
|
||||
var testString string
|
||||
if testMode {
|
||||
testString = "test"
|
||||
} else {
|
||||
testString = "prod"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("day%d/%s.in.txt", dayNumber, testString)
|
||||
}
|
||||
|
||||
func DownloadInput(sessionCookie string, dayNumber int, inputFileName string) error {
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("https://adventofcode.com/2022/day/%d/input", dayNumber), nil)
|
||||
if err != nil {
|
||||
log.Fatalf("couldn't create reques: %s", err)
|
||||
}
|
||||
req.AddCookie(&http.Cookie{Name: "session", Value: sessionCookie})
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
writer, err := os.Create(inputFileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(writer, resp.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Loading…
Reference in New Issue