Compare commits
4 Commits
9c97386cef
...
66a9f3f9e6
Author | SHA1 | Date | |
---|---|---|---|
66a9f3f9e6 | |||
ee0ac427cf | |||
e715a03263 | |||
c54a2e3440 |
10
day1.go
10
day1.go
@ -12,7 +12,7 @@ type Day1Input struct {
|
|||||||
column2 []int64
|
column2 []int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func day1_parse(lines []string) (*Day1Input, error) {
|
func Day1Parse(lines []string) (*Day1Input, error) {
|
||||||
column1 := make([]int64, len(lines))
|
column1 := make([]int64, len(lines))
|
||||||
column2 := make([]int64, len(lines))
|
column2 := make([]int64, len(lines))
|
||||||
|
|
||||||
@ -42,8 +42,8 @@ func day1_parse(lines []string) (*Day1Input, error) {
|
|||||||
return &parsed, nil
|
return &parsed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func day1_part1(lines []string) (error) {
|
func Day1Part1(lines []string) (error) {
|
||||||
input, err := day1_parse(lines)
|
input, err := Day1Parse(lines)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -70,8 +70,8 @@ func day1_part1(lines []string) (error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func day1_part2(lines []string) (error) {
|
func Day1Part2(lines []string) (error) {
|
||||||
input, err := day1_parse(lines)
|
input, err := Day1Parse(lines)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
109
day2.go
Normal file
109
day2.go
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Day2Input [][]int64
|
||||||
|
|
||||||
|
func Day2Parse(lines []string) (Day2Input, error) {
|
||||||
|
rows := make([][]int64, len(lines))
|
||||||
|
for i, line := range lines {
|
||||||
|
levelsCount := strings.Count(line, " ") + 1
|
||||||
|
rows[i] = make([]int64, levelsCount)
|
||||||
|
|
||||||
|
for j, level := range strings.Split(line, " ") {
|
||||||
|
number, err := strconv.ParseInt(level, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rows[i][j] = number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func absInt(value int64) int64 {
|
||||||
|
if value < 0 {
|
||||||
|
return -value
|
||||||
|
} else {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Day2IsReportSafe(report []int64) bool {
|
||||||
|
increasing := false
|
||||||
|
decreasing := false
|
||||||
|
|
||||||
|
for i := range len(report)-1 {
|
||||||
|
if report[i+1] >= report[i] {
|
||||||
|
increasing = true
|
||||||
|
}
|
||||||
|
if report[i+1] <= report[i] {
|
||||||
|
decreasing = true
|
||||||
|
}
|
||||||
|
if absInt(report[i+1] - report[i]) >= 4 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if increasing && decreasing {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !(increasing && decreasing) && (increasing || decreasing)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Day2Part1(lines []string) error {
|
||||||
|
input, err := Day2Parse(lines)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
answer := 0
|
||||||
|
for _, row := range input {
|
||||||
|
if Day2IsReportSafe(row) {
|
||||||
|
answer += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(answer)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteAtIndex(slice []int64, index int) []int64 {
|
||||||
|
result := make([]int64, len(slice))
|
||||||
|
copy(result, slice)
|
||||||
|
return append(result[:index], result[index+1:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Day2Part2(lines []string) error {
|
||||||
|
input, err := Day2Parse(lines)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
answer := 0
|
||||||
|
for _, row := range input {
|
||||||
|
if Day2IsReportSafe(row) {
|
||||||
|
answer += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range len(row) {
|
||||||
|
if Day2IsReportSafe(DeleteAtIndex(row, i)) {
|
||||||
|
answer += 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(answer)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
142
day3.go
Normal file
142
day3.go
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Day3Mul struct {
|
||||||
|
size int
|
||||||
|
number1 int
|
||||||
|
number2 int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Day3ParseMulInstruction(text string) *Day3Mul {
|
||||||
|
max_length := 0
|
||||||
|
max_length += 4 // mul(
|
||||||
|
max_length += 3 // 999
|
||||||
|
max_length += 1 // ,
|
||||||
|
max_length += 3 // 999
|
||||||
|
max_length += 1 // )
|
||||||
|
|
||||||
|
if len(text) < 4 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(text) > max_length {
|
||||||
|
text = text[:max_length]
|
||||||
|
}
|
||||||
|
|
||||||
|
if text[0:4] != "mul(" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
comma_index := strings.IndexRune(text, ',')
|
||||||
|
if (comma_index == -1) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
closing_index := strings.IndexRune(text, ')')
|
||||||
|
if (closing_index == -1) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
number1_text := text[4:comma_index]
|
||||||
|
number2_text := text[(comma_index+1):closing_index]
|
||||||
|
|
||||||
|
number1, err := strconv.ParseUint(number1_text, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if number1 > 999 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
number2, err := strconv.ParseUint(number2_text, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if number2 > 999 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
inst := Day3Mul{
|
||||||
|
size: closing_index + 1,
|
||||||
|
number1: int(number1),
|
||||||
|
number2: int(number2),
|
||||||
|
}
|
||||||
|
|
||||||
|
return &inst
|
||||||
|
}
|
||||||
|
|
||||||
|
func Day3Part1(lines []string) error {
|
||||||
|
answer := 0
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
cursor := 0
|
||||||
|
for cursor < len(line) {
|
||||||
|
inst := Day3ParseMulInstruction(line[cursor:])
|
||||||
|
if inst != nil {
|
||||||
|
cursor += inst.size
|
||||||
|
answer += inst.number1 * inst.number2
|
||||||
|
} else {
|
||||||
|
cursor += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
println(answer)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Day3StartsWith(haystack string, needle string) bool {
|
||||||
|
if len(haystack) < len(needle) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return haystack[:len(needle)] == needle
|
||||||
|
}
|
||||||
|
|
||||||
|
func Day3Part2(lines []string) error {
|
||||||
|
answer := 0
|
||||||
|
|
||||||
|
do_inst := "do()"
|
||||||
|
dont_inst := "don't()"
|
||||||
|
|
||||||
|
enabled := true
|
||||||
|
for _, line := range lines {
|
||||||
|
cursor := 0
|
||||||
|
for cursor < len(line) {
|
||||||
|
rest := line[cursor:]
|
||||||
|
if Day3StartsWith(rest, do_inst) {
|
||||||
|
enabled = true
|
||||||
|
cursor += len(do_inst)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if Day3StartsWith(rest, dont_inst) {
|
||||||
|
enabled = false
|
||||||
|
cursor += len(dont_inst)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if enabled {
|
||||||
|
inst := Day3ParseMulInstruction(rest)
|
||||||
|
if inst != nil {
|
||||||
|
cursor += inst.size
|
||||||
|
answer += inst.number1 * inst.number2
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
println(answer)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
110
day4.go
Normal file
110
day4.go
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Day4Offset struct {
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Day4IsWordValid(lines []string, x int, y int, table []Day4Offset, word string) bool {
|
||||||
|
for i, offset := range table {
|
||||||
|
y := y + offset.y
|
||||||
|
if y < 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if y >= len(lines) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
x := x + offset.x
|
||||||
|
if x < 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if x >= len(lines[y]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if lines[y][x] != word[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func Day4Part1(lines []string) error {
|
||||||
|
offsetTables := [][]Day4Offset{
|
||||||
|
[]Day4Offset{
|
||||||
|
Day4Offset{ x: 0, y: 0, },
|
||||||
|
Day4Offset{ x: 1, y: 0, },
|
||||||
|
Day4Offset{ x: 2, y: 0, },
|
||||||
|
Day4Offset{ x: 3, y: 0, },
|
||||||
|
},
|
||||||
|
[]Day4Offset{
|
||||||
|
Day4Offset{ x: 0, y: 0, },
|
||||||
|
Day4Offset{ x: 0, y: 1, },
|
||||||
|
Day4Offset{ x: 0, y: 2, },
|
||||||
|
Day4Offset{ x: 0, y: 3, },
|
||||||
|
},
|
||||||
|
[]Day4Offset{
|
||||||
|
Day4Offset{ x: 0, y: 0, },
|
||||||
|
Day4Offset{ x: 1, y: 1, },
|
||||||
|
Day4Offset{ x: 2, y: 2, },
|
||||||
|
Day4Offset{ x: 3, y: 3, },
|
||||||
|
},
|
||||||
|
[]Day4Offset{
|
||||||
|
Day4Offset{ x: 0, y: 0, },
|
||||||
|
Day4Offset{ x: -1, y: 1, },
|
||||||
|
Day4Offset{ x: -2, y: 2, },
|
||||||
|
Day4Offset{ x: -3, y: 3, },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
answer := 0
|
||||||
|
for y := range len(lines) {
|
||||||
|
for x := range len(lines[y]) {
|
||||||
|
for _, table := range offsetTables {
|
||||||
|
if Day4IsWordValid(lines, x, y, table, "XMAS") {
|
||||||
|
answer += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if Day4IsWordValid(lines, x, y, table, "SAMX") {
|
||||||
|
answer += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println(answer)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Day4Part2(lines []string) error {
|
||||||
|
table1 := []Day4Offset{
|
||||||
|
Day4Offset{ x: 0, y: 0, },
|
||||||
|
Day4Offset{ x: 1, y: 1, },
|
||||||
|
Day4Offset{ x: 2, y: 2, },
|
||||||
|
}
|
||||||
|
|
||||||
|
table2 := []Day4Offset{
|
||||||
|
Day4Offset{ x: 2, y: 0, },
|
||||||
|
Day4Offset{ x: 1, y: 1, },
|
||||||
|
Day4Offset{ x: 0, y: 2, },
|
||||||
|
}
|
||||||
|
|
||||||
|
answer := 0
|
||||||
|
for y := range len(lines) {
|
||||||
|
for x := range len(lines[y]) {
|
||||||
|
diagonal1 := Day4IsWordValid(lines, x, y, table1, "MAS") || Day4IsWordValid(lines, x, y, table1, "SAM")
|
||||||
|
diagonal2 := Day4IsWordValid(lines, x, y, table2, "MAS") || Day4IsWordValid(lines, x, y, table2, "SAM")
|
||||||
|
|
||||||
|
if diagonal1 && diagonal2 {
|
||||||
|
answer += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println(answer)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
27
main.go
27
main.go
@ -12,6 +12,12 @@ func showUsage() {
|
|||||||
fmt.Printf("Usage: %s <day> <part> [input.txt]\n", os.Args[0])
|
fmt.Printf("Usage: %s <day> <part> [input.txt]\n", os.Args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DayPartSolver func([]string) error
|
||||||
|
type DaySolver struct {
|
||||||
|
day1 DayPartSolver
|
||||||
|
day2 DayPartSolver
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if (len(os.Args) < 3) {
|
if (len(os.Args) < 3) {
|
||||||
showUsage()
|
showUsage()
|
||||||
@ -35,11 +41,26 @@ func main() {
|
|||||||
|
|
||||||
lines := strings.Split(strings.TrimRight(string(contents), "\n"), "\n")
|
lines := strings.Split(strings.TrimRight(string(contents), "\n"), "\n")
|
||||||
|
|
||||||
if day == "1" {
|
solvers := make(map[string]DaySolver)
|
||||||
|
solvers["1"] = DaySolver{ day1: Day1Part1, day2: Day1Part2 }
|
||||||
|
solvers["2"] = DaySolver{ day1: Day2Part1, day2: Day2Part2 }
|
||||||
|
solvers["3"] = DaySolver{ day1: Day3Part1, day2: Day3Part2 }
|
||||||
|
solvers["4"] = DaySolver{ day1: Day4Part1, day2: Day4Part2 }
|
||||||
|
|
||||||
|
solver, ok := solvers[day]
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
var err error
|
||||||
if part == "1" {
|
if part == "1" {
|
||||||
day1_part1(lines)
|
err = solver.day1(lines)
|
||||||
} else if part == "2" {
|
} else if part == "2" {
|
||||||
day1_part2(lines)
|
err = solver.day1(lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Fatal("Day not found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user