The aoc_lib package used in these solutions is my own custom helper functions library. You can find the code here. I’ll try to post my solutions daily. These are probably not the most optimized solutions. That is not my goal with advent of code honestly, I do these just for fun.
Day 1
Day 1 was pretty straightforward. Just some basic array magic. I don’t think the code needs much explanation.
package main
import (
"fmt"
"sort"
aoc_lib "github.com/Jitesh117/aoc_lib"
)
func part1(input []string) int {
var leftList, rightList []int
for _, line := range input {
nums := aoc_lib.StringToIntSlice(line)
leftList = append(leftList, nums[0])
rightList = append(rightList, nums[1])
}
sort.Ints(leftList)
sort.Ints(rightList)
result := 0
for i := 0; i < len(leftList); i++ {
diff := leftList[i] - rightList[i]
if diff < 0 {
diff = -diff
}
result += diff
}
return result
}
func part2(input []string) int {
var leftList, rightList []int
for _, line := range input {
nums := aoc_lib.StringToIntSlice(line)
leftList = append(leftList, nums[0])
rightList = append(rightList, nums[1])
}
rightCount := make(map[int]int)
for _, num := range rightList {
rightCount[num]++
}
similarityScore := 0
for _, num := range leftList {
if count, exists := rightCount[num]; exists {
similarityScore += num * count
}
}
return similarityScore
}
func main() {
lines := aoc_lib.ReadLines("input.txt")
resultPart1 := part1(lines)
resultPart2 := part2(lines)
fmt.Printf("Part 1: %d\n", resultPart1)
fmt.Printf("Part 2: %d\n", resultPart2)
}
Day 2
package main
import (
"fmt"
"math"
"strings"
"github.com/Jitesh117/aoc_lib"
)
func isSafe(nums []int) bool {
isIncreasing := true
isDecreasing := true
differencesValid := true
for i := 0; i < len(nums)-1; i++ {
diff := nums[i+1] - nums[i]
if diff <= 0 {
isIncreasing = false
}
if diff >= 0 {
isDecreasing = false
}
if math.Abs(float64(diff)) < 1 || math.Abs(float64(diff)) > 3 {
differencesValid = false
}
}
return (isIncreasing || isDecreasing) && differencesValid
}
func part1(lines []string) int {
result := 0
for _, line := range lines {
nums := aoc_lib.StringToIntSlice(
strings.ReplaceAll(line, " ", "~"),
)
if isSafe(nums) {
result++
}
}
return result
}
func part2(lines []string) int {
result := 0
for _, line := range lines {
nums := aoc_lib.StringToIntSlice(strings.ReplaceAll(line, " ", "~"))
if isSafe(nums) {
result++
continue
}
for i := 0; i < len(nums); i++ {
modifiedNums := append([]int{}, nums[:i]...)
modifiedNums = append(modifiedNums, nums[i+1:]...)
if isSafe(modifiedNums) {
result++
break
}
}
}
return result
}
func main() {
lines := aoc_lib.ReadLines("input.txt")
fmt.Printf("part1: %d\n", part1(lines))
fmt.Printf("part2: %d\n", part2(lines))
}
Day 3
package main
import (
"fmt"
"os"
"regexp"
"strconv"
)
func part1(input string) int {
mulPattern := regexp.MustCompile(`mul\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)`)
results := 0
for _, match := range mulPattern.FindAllStringSubmatch(input, -1) {
num1, _ := strconv.Atoi(match[1])
num2, _ := strconv.Atoi(match[2])
results += num1 * num2
}
return results
}
func part2(input string) int {
mulPattern := regexp.MustCompile(`mul\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)`)
doPattern := regexp.MustCompile(`do\(\)`)
dontPattern := regexp.MustCompile(`don'?t\(\)`)
results := 0
mulEnabled := true
combinedPattern := regexp.MustCompile(
fmt.Sprintf(`%s|%s|%s`, mulPattern.String(), doPattern.String(), dontPattern.String()),
)
for _, match := range combinedPattern.FindAllStringSubmatch(input, -1) {
if doPattern.MatchString(match[0]) {
mulEnabled = true
} else if dontPattern.MatchString(match[0]) {
mulEnabled = false
} else if mulPattern.MatchString(match[0]) && mulEnabled {
num1, _ := strconv.Atoi(match[1])
num2, _ := strconv.Atoi(match[2])
results += num1 * num2
}
}
return results
}
func main() {
inputBytes, err := os.ReadFile("input.txt")
if err != nil {
panic(err)
}
input := string(inputBytes)
fmt.Printf("Part 1 Result: %d\n", part1(input))
fmt.Printf("Part 2 Result: %d\n", part2(input))
}