Compare commits

...

5 commits

Author SHA1 Message Date
8b6ea615f7 Day 2a 2024-11-04 19:18:21 +00:00
7e3b20a8c8 day 1: misc idiomaticness 2024-10-28 20:19:56 +00:00
399e40a6f9 Day 1b 2024-10-28 19:58:56 +00:00
255c191dfc day 1a 2024-10-28 18:12:20 +00:00
c3c1fe8b3a go environment setup 2024-10-28 18:12:11 +00:00
9 changed files with 249 additions and 0 deletions

75
day01/day01.go Normal file
View file

@ -0,0 +1,75 @@
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const digits = "0123456789"
func words() [10]string {
return [10]string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
}
func firstDigit(input string) string {
var result string
loc := len(input)
if index := strings.IndexAny(input, "0123456789"); index != -1 {
loc = index
result = string([]rune(input)[index])
}
for key, value := range words() {
if index := strings.Index(input, value); index != -1 && index <= loc {
loc = index
result = strconv.Itoa(key)
}
}
return result
}
func lastDigit(input string) string {
var result string
loc := -1
if index := strings.LastIndexAny(input, "0123456789"); index != -1 {
loc = index
result = string([]rune(input)[index])
}
for key, value := range words() {
if index := strings.LastIndex(input, value); index != -1 && index >= loc {
loc = index
result = strconv.Itoa(key)
}
}
return result
}
func calibration(input string) int {
first := firstDigit(input)
last := lastDigit(input)
output, _ := strconv.Atoi(first + last)
return output
}
func ScanFile(file *os.File) (int, error) {
scanner := bufio.NewScanner(file)
sum := 0
for scanner.Scan() {
sum += calibration(scanner.Text())
}
if err := scanner.Err(); err != nil {
return 0, err
}
return sum, nil
}
func main() {
sum, err := ScanFile(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "Invalid input: %s\n", err)
return
}
fmt.Println(sum)
}

32
day01/day01_test.go Normal file
View file

@ -0,0 +1,32 @@
package main
import (
"os"
"testing"
)
func TestScanFile(t *testing.T) {
cases := []struct {
inFile string;
want int;
}{
{"input1.txt", 142},
{"input2.txt", 281},
}
for _, c := range cases {
f, err := os.Open(c.inFile)
if err != nil {
t.Fatal(err)
}
got, err := ScanFile(f)
if err != nil {
t.Fatal(err)
}
if got != c.want {
t.Errorf("ScanFile(%q) == %d, want %d", c.inFile, got, c.want)
}
}
}

4
day01/input1.txt Normal file
View file

@ -0,0 +1,4 @@
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet

7
day01/input2.txt Normal file
View file

@ -0,0 +1,7 @@
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen

82
day02/day02.go Normal file
View file

@ -0,0 +1,82 @@
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
type Game struct {
id int
sets []Set
}
type Set struct {
red int
green int
blue int
}
func parseGame(input string) Game {
idStr, setsStr, _ := strings.Cut(input, ": ")
var game Game
var err error
game.id, err = strconv.Atoi(strings.TrimPrefix(idStr, "Game "))
for i, setStr := range strings.Split(setsStr, "; ") {
game.sets = append(game.sets, Set{})
for _, colorStr := range strings.Split(setStr, ", ") {
if strings.HasSuffix(colorStr, " red") {
game.sets[i].red, err = strconv.Atoi(strings.TrimSuffix(colorStr, " red"))
}
if strings.HasSuffix(colorStr, " green") {
game.sets[i].green, err = strconv.Atoi(strings.TrimSuffix(colorStr, " green"))
}
if strings.HasSuffix(colorStr, " blue") {
game.sets[i].blue, err = strconv.Atoi(strings.TrimSuffix(colorStr, " blue"))
}
}
}
if err != nil {
panic("day02: invalid game format")
}
return game
}
func isGameValid(game Game) bool {
for _, set := range game.sets {
if set.red > 12 || set.green > 13 || set.blue > 14 {
return false
}
}
return true
}
func ScanFile(file *os.File) (int, error) {
scanner := bufio.NewScanner(file)
sum := 0
for scanner.Scan() {
if game := parseGame(scanner.Text()); isGameValid(game) {
sum += game.id
}
}
if err := scanner.Err(); err != nil {
return 0, err
}
return sum, nil
}
func main() {
sum, err := ScanFile(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "Invalid input: %s\n", err)
return
}
fmt.Println(sum)
}

31
day02/day02_test.go Normal file
View file

@ -0,0 +1,31 @@
package main
import (
"os"
"testing"
)
func TestScanFile(t *testing.T) {
cases := []struct {
inFile string;
want int;
}{
{"input1.txt", 8},
}
for _, c := range cases {
f, err := os.Open(c.inFile)
if err != nil {
t.Fatal(err)
}
got, err := ScanFile(f)
if err != nil {
t.Fatal(err)
}
if got != c.want {
t.Errorf("ScanFile(%q) == %d, want %d", c.inFile, got, c.want)
}
}
}

5
day02/input1.txt Normal file
View file

@ -0,0 +1,5 @@
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green

3
go.mod Normal file
View file

@ -0,0 +1,3 @@
module git.qenya.tel/qenya/aoc2023
go 1.23.2

10
shell.nix Normal file
View file

@ -0,0 +1,10 @@
let
pkgs = import <nixpkgs> {};
in pkgs.mkShell {
packages = with pkgs; [
go
];
shellHook = ''
export PATH=$PATH:~/go/bin
'';
}