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
|
||||
}
|
||||
|
||||
func day1_parse(lines []string) (*Day1Input, error) {
|
||||
func Day1Parse(lines []string) (*Day1Input, error) {
|
||||
column1 := make([]int64, len(lines))
|
||||
column2 := make([]int64, len(lines))
|
||||
|
||||
@ -42,8 +42,8 @@ func day1_parse(lines []string) (*Day1Input, error) {
|
||||
return &parsed, nil
|
||||
}
|
||||
|
||||
func day1_part1(lines []string) (error) {
|
||||
input, err := day1_parse(lines)
|
||||
func Day1Part1(lines []string) (error) {
|
||||
input, err := Day1Parse(lines)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -70,8 +70,8 @@ func day1_part1(lines []string) (error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func day1_part2(lines []string) (error) {
|
||||
input, err := day1_parse(lines)
|
||||
func Day1Part2(lines []string) (error) {
|
||||
input, err := Day1Parse(lines)
|
||||
if err != nil {
|
||||
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])
|
||||
}
|
||||
|
||||
type DayPartSolver func([]string) error
|
||||
type DaySolver struct {
|
||||
day1 DayPartSolver
|
||||
day2 DayPartSolver
|
||||
}
|
||||
|
||||
func main() {
|
||||
if (len(os.Args) < 3) {
|
||||
showUsage()
|
||||
@ -35,11 +41,26 @@ func main() {
|
||||
|
||||
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" {
|
||||
day1_part1(lines)
|
||||
err = solver.day1(lines)
|
||||
} 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