Skip to content

Instantly share code, notes, and snippets.

@DmitryTsepelev

DmitryTsepelev/day01.go

Last active Dec 26, 2018
Embed
What would you like to do?
Advent of code 2018
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func getInputData() *[]int {
data := []int{}
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
intValue, _ := strconv.Atoi(scanner.Text())
data = append(data, intValue)
}
return &data
}
func solveTask1() int {
total := 0
data := *getInputData()
for _, item := range data {
total += item
}
return total
}
func contains(s []int, e int) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
func solveTask2() int {
total := 0
data := *getInputData()
frequencies := []int{0}
for {
for _, item := range data {
total += item
if contains(frequencies, total) {
return total
}
frequencies = append(frequencies, total)
}
}
}
func main() {
fmt.Println("Task 1 solution is", solveTask1())
fmt.Println("Task 2 solution is", solveTask2())
}
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
type Area struct {
ID int
X int
Y int
Width int
Height int
Overlaps bool
}
func getInputData() *[]string {
data := []string{}
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
data = append(data, scanner.Text())
}
return &data
}
func lineToArea(line string) *Area {
base := strings.Split(line, "@")
id, _ := strconv.Atoi(strings.TrimSpace(strings.Replace(base[0], "#", "", 1)))
cmp := strings.Split(base[1], ":")
coordinates := strings.Split(cmp[0], ",")
x, _ := strconv.Atoi(strings.TrimSpace(coordinates[0]))
y, _ := strconv.Atoi(strings.TrimSpace(coordinates[1]))
size := strings.Split(cmp[1], "x")
width, _ := strconv.Atoi(strings.TrimSpace(size[0]))
height, _ := strconv.Atoi(strings.TrimSpace(size[1]))
return &Area{
ID: id,
X: x,
Y: y,
Width: width,
Height: height,
Overlaps: false,
}
}
func solveTask1(areas *[]*Area) int {
field := [1000][1000]int{}
for _, area := range *areas {
x := area.X
y := area.Y
for i := 0; i < area.Height; i++ {
for j := 0; j < area.Width; j++ {
if field[x+j][y+i] == 0 {
field[x+j][y+i] = area.ID
} else {
field[x+j][y+i] = -1
}
}
}
}
overlaps := 0
for i, row := range field {
for j := range row {
if field[i][j] == -1 {
overlaps += 1
}
}
}
return overlaps
}
func solveTask2(areas *[]*Area) int {
areasIndex := make(map[int]*Area)
field := [1000][1000]int{}
for _, area := range *areas {
areasIndex[area.ID] = area
x := area.X
y := area.Y
for i := 0; i < area.Height; i++ {
for j := 0; j < area.Width; j++ {
areaId := field[x+j][y+i]
if areaId == 0 {
field[x+j][y+i] = area.ID
} else {
areasIndex[area.ID].Overlaps = true
areasIndex[areaId].Overlaps = true
}
}
}
}
for _, area := range *areas {
if !area.Overlaps {
return area.ID
}
}
return 0
}
func main() {
areas := []*Area{}
data := *getInputData()
for _, line := range data {
areas = append(
areas,
lineToArea(line),
)
}
fmt.Println("Task 1 solution is", solveTask1(&areas))
fmt.Println("Task 2 solution is", solveTask2(&areas))
}
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
type Guard struct {
ID int
MostSleptMinute int
Sleeps map[string]*[60]int
Counts [60]int
MinutesSlept int
}
func loadGuards() map[int]*Guard {
data := *getInputData()
sort.Strings(data)
guards := map[int]*Guard{}
var guard *Guard
startedAt := 0
for _, line := range data {
cmp := strings.Split(line, "] ")
message := cmp[1]
datetime := strings.Split(strings.Replace(cmp[0], "[", "", 1), " ")
date := datetime[0]
minute, _ := strconv.Atoi(
strings.Split(datetime[1], ":")[1],
)
if strings.Contains(message, "begins shift") {
id, _ := strconv.Atoi(
strings.Replace(
strings.Replace(message, "Guard #", "", 1),
" begins shift",
"",
1,
),
)
guard = guards[id]
if guard == nil {
guards[id] = &Guard{
ID: id,
Sleeps: make(map[string]*[60]int),
}
guard = guards[id]
}
} else if strings.Contains(message, "falls asleep") {
startedAt = minute
} else if strings.Contains(message, "wakes up") {
sleep := guard.Sleeps[date]
if sleep == nil {
guard.Sleeps[date] = &[60]int{}
}
for i := startedAt; i < minute; i++ {
guard.Sleeps[date][i] = 1
}
}
}
for _, guard := range guards {
for _, minutes := range guard.Sleeps {
for i := range guard.Counts {
if minutes[i] > 0 {
guard.Counts[i] = guard.Counts[i] + 1
guard.MinutesSlept = guard.MinutesSlept + 1
}
}
}
mostSleptMinuteCount := 0
for i, sleepCount := range guard.Counts {
if sleepCount > mostSleptMinuteCount {
mostSleptMinuteCount = sleepCount
guard.MostSleptMinute = i
}
}
}
return guards
}
func getInputData() *[]string {
data := []string{}
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
data = append(data, scanner.Text())
}
return &data
}
func solveTask1() int {
guards := loadGuards()
var mostSleepingGuard *Guard
for _, guard := range guards {
if mostSleepingGuard == nil || guard.MinutesSlept > mostSleepingGuard.MinutesSlept {
mostSleepingGuard = guard
}
}
return mostSleepingGuard.ID * mostSleepingGuard.MostSleptMinute
}
func solveTask2() int {
guards := loadGuards()
var mostSleepingGuard *Guard
for _, guard := range guards {
if mostSleepingGuard == nil || guard.Counts[guard.MostSleptMinute] > mostSleepingGuard.Counts[mostSleepingGuard.MostSleptMinute] {
mostSleepingGuard = guard
}
}
return mostSleepingGuard.ID * mostSleepingGuard.MostSleptMinute
}
func main() {
fmt.Println("Task 1 solution is", solveTask1())
fmt.Println("Task 2 solution is", solveTask2())
}
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func getInput() []byte {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Scan()
return scanner.Bytes()
}
func react(polymer *[]byte) *[]byte {
reacted := make([]byte, len(*polymer))
copy(reacted, *polymer)
i := 0
for {
if i > len(reacted)-2 {
break
}
currentChar := string(reacted[i])
nextChar := string(reacted[i+1])
if currentChar != nextChar && strings.ToUpper(nextChar) == strings.ToUpper(currentChar) {
copy(reacted[i:], reacted[i+2:])
reacted = reacted[:len(reacted)-2]
if i > 0 {
i--
}
} else {
i++
}
}
return &reacted
}
func solveTask1() int {
polymer := getInput()
reacted := react(&polymer)
return len(*reacted)
}
func removeUnit(polymer *[]byte, unit byte) *[]byte {
withoutUnit := []byte{}
for i := 0; i < len(*polymer); i++ {
currentByte := (*polymer)[i]
if currentByte != unit && currentByte != unit-32 {
withoutUnit = append(withoutUnit, currentByte)
}
}
return &withoutUnit
}
func solveTask2() int {
polymer := getInput()
minLength := len(polymer)
for unit := 'a'; unit <= 'z'; unit++ {
withoutUnit := removeUnit(&polymer, byte(unit))
reacted := react(withoutUnit)
length := len(*reacted)
if length < minLength {
minLength = length
}
}
return minLength
}
func main() {
fmt.Println("Task 1 solution is", solveTask1())
fmt.Println("Task 2 solution is", solveTask2())
}
package main
import (
"bufio"
"fmt"
"math"
"os"
"strconv"
"strings"
)
type Point struct {
ID string
X int
Y int
Infinite bool
Count int
}
func loadPoints() *[]*Point {
points := []*Point{}
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
id := 'A'
for scanner.Scan() {
coordinates := strings.Split(scanner.Text(), ", ")
x, _ := strconv.Atoi(coordinates[0])
y, _ := strconv.Atoi(coordinates[1])
points = append(points, &Point{ID: string(id), X: x, Y: y, Infinite: false, Count: 0})
id++
}
return &points
}
func distanceBetween(point *Point, x int, y int) int {
return int(math.Abs(float64(point.X-x)) + math.Abs(float64(point.Y-y)))
}
func solveTask1() int {
points := *loadPoints()
const fieldSize = 360
for x := 0; x < fieldSize; x++ {
for y := 0; y < fieldSize; y++ {
minDistance := fieldSize + fieldSize
distances := make(map[*Point]int)
for _, point := range points {
distance := distanceBetween(point, x, y)
distances[point] = distance
if distance < minDistance {
minDistance = distance
}
}
var closestPoint *Point
for point, distance := range distances {
if distance == minDistance {
if closestPoint == nil {
closestPoint = point
} else {
closestPoint = nil
}
}
}
if closestPoint != nil {
closestPoint.Count++
if x == 0 || x == fieldSize-1 || y == 0 || y == fieldSize-1 {
closestPoint.Infinite = true
}
}
}
}
maxCount := 0
for _, point := range points {
if !point.Infinite && maxCount < point.Count {
maxCount = point.Count
}
}
return maxCount
}
func solveTask2() int {
points := *loadPoints()
const fieldSize = 360
const maxDistance = 10000
count := 0
for x := 0; x < fieldSize; x++ {
for y := 0; y < fieldSize; y++ {
distance := 0
for _, point := range points {
distance += distanceBetween(point, x, y)
}
if distance < maxDistance {
count++
}
}
}
return count
}
func main() {
fmt.Println("Task 1 solution is", solveTask1())
fmt.Println("Task 2 solution is", solveTask2())
}
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
type Row map[string]int
type Field map[string]Row
func getSteps() Field {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
restrictions := [][]string{}
stepNames := []string{}
for scanner.Scan() {
cmp := strings.Split(scanner.Text(), " must be finished before step ")
from := strings.Replace(cmp[0], "Step ", "", 1)
to := strings.Replace(cmp[1], " can begin.", "", 1)
restrictions = append(restrictions, []string{from, to})
if !contains(stepNames, from) {
stepNames = append(stepNames, from)
}
if !contains(stepNames, to) {
stepNames = append(stepNames, to)
}
}
field := make(Field)
for _, i := range stepNames {
row := make(Row)
for _, j := range stepNames {
row[j] = 0
}
field[i] = row
}
for _, restriction := range restrictions {
from := restriction[0]
to := restriction[1]
field[from][to] = 1
}
return field
}
func getCandidates(field Field) []string {
candidates := []string{}
for candidate := range field {
isCandidate := true
for key, directions := range field {
if candidate != key && directions[candidate] == 1 {
isCandidate = false
}
}
if isCandidate {
candidates = append(candidates, candidate)
}
}
return candidates
}
func solveTask1() string {
field := getSteps()
result := ""
for {
candidates := getCandidates(field)
if len(candidates) == 0 {
break
}
sort.Strings(candidates)
nextStep := candidates[0]
delete(field, nextStep)
result += nextStep
}
return result
}
func secondsToComplete(step string) int {
stepCmp := int(byte(step[0]) - 64)
added := 60
return stepCmp + added
}
type Worker struct {
Job string
Remaining int
}
func solveTask2() int {
field := getSteps()
workers := []*Worker{
&Worker{},
&Worker{},
&Worker{},
&Worker{},
&Worker{},
}
seconds := 0
for {
for _, worker := range workers {
if worker.Job != "" {
worker.Remaining--
if worker.Remaining == 0 {
delete(field, worker.Job)
worker.Job = ""
}
}
}
candidates := getCandidates(field)
noCandidates := len(candidates) == 0
availableCandidates := []string{}
for _, candidate := range candidates {
isAvailable := true
for _, worker := range workers {
if worker.Job != "" && worker.Job == candidate {
isAvailable = false
}
}
if isAvailable {
availableCandidates = append(availableCandidates, candidate)
}
}
sort.Strings(availableCandidates)
currentCandidateIdx := 0
allWorkersFree := true
for _, worker := range workers {
if worker.Job == "" {
if len(availableCandidates) > currentCandidateIdx {
job := availableCandidates[currentCandidateIdx]
worker.Job = job
worker.Remaining = secondsToComplete(job)
allWorkersFree = false
currentCandidateIdx++
}
}
}
if noCandidates && allWorkersFree {
return seconds
}
seconds++
}
}
func main() {
fmt.Println("Task 1 solution is", solveTask1())
fmt.Println("Task 2 solution is", solveTask2())
}
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func getData() *[]int {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
data := []int{}
for scanner.Scan() {
text := scanner.Text()
stringValues := strings.Split(text, " ")
for _, stringValue := range stringValues {
value, _ := strconv.Atoi(stringValue)
data = append(data, value)
}
}
return &data
}
type Node struct {
Children *[]Node
Metadata *[]int
}
func buildNode(data *[]int, startIdx int) (*Node, int) {
childrenCount := (*data)[startIdx]
metaCount := (*data)[startIdx+1]
children := []Node{}
startIdx += 2
for i := 0; i < childrenCount; i++ {
child, newIndex := buildNode(data, startIdx)
startIdx = newIndex
children = append(children, *child)
}
metadata := []int{}
for i := 0; i < metaCount; i++ {
meta := (*data)[startIdx]
metadata = append(metadata, meta)
startIdx++
}
node := Node{
Children: &children,
Metadata: &metadata,
}
return &node, startIdx
}
func countMeta(node *Node) int {
sum := 0
for _, meta := range *node.Metadata {
sum += meta
}
for _, child := range *node.Children {
sum += countMeta(&child)
}
return sum
}
func solveTask1() int {
data := getData()
node, _ := buildNode(data, 0)
return countMeta(node)
}
func countValue(node *Node) int {
sum := 0
if len(*node.Children) == 0 {
for _, meta := range *node.Metadata {
sum += meta
}
return sum
}
for _, meta := range *node.Metadata {
children := *node.Children
if meta > 0 && meta <= len(children) {
child := children[meta-1]
sum += countValue(&child)
}
}
return sum
}
func solveTask2() int {
data := getData()
node, _ := buildNode(data, 0)
return countValue(node)
}
func main() {
fmt.Println("Task 1 solution is", solveTask1())
fmt.Println("Task 2 solution is", solveTask2())
}
package main
import (
"bufio"
"fmt"
"math"
"os"
"strconv"
"strings"
)
func getData() (int, int) {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Scan()
cmp := strings.Split(scanner.Text(), " players; last marble is worth ")
players, _ := strconv.Atoi(cmp[0])
points, _ := strconv.Atoi(strings.Replace(cmp[1], " points", "", 1))
return players, points
}
type Node struct {
Value int
Prev *Node
Next *Node
}
func insertAfter(node *Node, marble int) *Node {
newNode := Node{Value: marble, Prev: node, Next: node.Next}
newNode.Next = node.Next
newNode.Prev = node
node.Next.Prev = &newNode
node.Next = &newNode
return &newNode
}
func remove(node *Node) *Node {
prev := node.Prev
prev.Next = node.Next
node.Next.Prev = prev
return node.Next
}
func solveTask(players int, lastMarble int) int {
current := &Node{Value: 0}
current.Next = current
current.Prev = current
scores := []int{}
for i := 0; i < players; i++ {
scores = append(scores, 0)
}
currentPlayer := 0
for marble := 1; marble <= lastMarble; marble++ {
isScoringMarble := int(math.Mod(float64(marble), float64(23))) == 0
if isScoringMarble {
for i := 0; i < 7; i++ {
current = current.Prev
}
scores[currentPlayer] += marble + current.Value
current = remove(current)
} else {
for i := 0; i < 1; i++ {
current = current.Next
}
current = insertAfter(current, marble)
}
currentPlayer++
if currentPlayer == players {
currentPlayer = 0
}
}
maxScore := 0
for _, score := range scores {
if score > maxScore {
maxScore = score
}
}
return maxScore
}
func main() {
players, points := getData()
fmt.Println("Task 1 solution is", solveTask(players, points))
fmt.Println("Task 2 solution is", solveTask(players, points*100))
}
package main
import (
"bufio"
"fmt"
"math"
"os"
"strconv"
"strings"
)
type Star struct {
X int
Y int
DX int
DY int
}
func getData() *[]*Star {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
data := []*Star{}
for scanner.Scan() {
cmp := strings.Split(scanner.Text(), "> velocity=<")
coorditatesString := strings.Replace(cmp[0], "position=<", "", 1)
coordinates := strings.Split(coorditatesString, ",")
x, _ := strconv.Atoi(strings.TrimSpace(coordinates[0]))
y, _ := strconv.Atoi(strings.TrimSpace(coordinates[1]))
velocityString := strings.Replace(cmp[1], ">", "", 1)
velocity := strings.Split(velocityString, ",")
dx, _ := strconv.Atoi(strings.TrimSpace(velocity[0]))
dy, _ := strconv.Atoi(strings.TrimSpace(velocity[1]))
star := Star{X: x, Y: y, DX: dx, DY: dy}
data = append(data, &star)
}
return &data
}
func draw(stars *[]*Star) {
minX := math.MaxInt32
maxX := math.MinInt32
minY := math.MaxInt32
maxY := math.MinInt32
for _, star := range *stars {
if star.X < minX {
minX = star.X
}
if star.X > maxX {
maxX = star.X
}
if star.Y < minY {
minY = star.Y
}
if star.Y > maxY {
maxY = star.Y
}
}
for y := minY - 5; y < maxY+5; y++ {
line := ""
shouldBePrinted := false
for x := minX - 5; x < maxX+5; x++ {
hasStar := false
for _, star := range *stars {
if star.X == x && star.Y == y {
line += "#"
hasStar = true
shouldBePrinted = true
break
}
}
if !hasStar {
line += "."
}
}
if shouldBePrinted {
fmt.Println(line)
}
}
}
func move(stars *[]*Star) {
for _, star := range *stars {
star.X += star.DX
star.Y += star.DY
}
}
func solveTask() (result *[]*Star, seconds int) {
stars := getData()
for i := 0; i < 1000000; i++ {
move(stars)
minX := 0
maxX := 0
minY := 0
maxY := 0
for _, star := range *stars {
if star.X < minX {
minX = star.X
}
if star.X > maxX {
maxX = star.X
}
if star.Y < minY {
minY = star.Y
}
if star.Y > maxY {
maxY = star.Y
}
}
if maxX-minX < 238 {
return stars, i + 1
}
}
return nil, 0
}
func main() {
stars, seconds := solveTask()
draw(stars)
fmt.Println("Seconds", seconds)
}
package main
import (
"fmt"
"strconv"
)
func powerLevel(x, y, serialNumber int) int {
rackId := x + 10
baseLevel := ((rackId * y) + serialNumber) * rackId
strLevel := strconv.Itoa(baseLevel)
level := 0
if len(strLevel) >= 3 {
level, _ = strconv.Atoi(strLevel[len(strLevel)-3 : len(strLevel)-2])
}
return level - 5
}
func solveTask(serialNumber int, minSize int, maxSize int) (int, int, int) {
const gridSize = 300
sumTable := make([][]int, gridSize+1)
for y := 0; y <= gridSize; y++ {
sumTable[y] = make([]int, gridSize+1)
}
for y := 1; y <= gridSize; y++ {
for x := 1; x <= gridSize; x++ {
sumTable[y][x] = powerLevel(x, y, serialNumber) + sumTable[y-1][x] + sumTable[y][x-1] - sumTable[y-1][x-1]
}
}
resultX := 0
resultY := 0
maxPower := 0
resultSize := 0
for squareSize := minSize; squareSize <= maxSize; squareSize++ {
for squareY := squareSize; squareY <= gridSize; squareY++ {
for squareX := squareSize; squareX <= gridSize; squareX++ {
totalPower := sumTable[squareY][squareX] - sumTable[squareY-squareSize][squareX] - sumTable[squareY][squareX-squareSize] + sumTable[squareY-squareSize][squareX-squareSize]
if totalPower > maxPower {
maxPower = totalPower
resultX = squareX - squareSize + 1
resultY = squareY - squareSize + 1
resultSize = squareSize
}
}
}
}
return resultX, resultY, resultSize
}
func main() {
const serialNumber = 5093
x, y, _ := solveTask(serialNumber, 3, 3)
fmt.Println("Task 1 solution is", x, y)
x, y, size := solveTask(serialNumber, 1, 300)
fmt.Println("Task 2 solution is", x, y, size)
}
package main
import (
"bufio"
"fmt"
"os"
"reflect"
"strings"
)
func getData() (*[]string, *[][]string) {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Scan()
initialState := strings.Split(strings.Replace(scanner.Text(), "initial state: ", "", 1), "")
patterns := [][]string{}
for scanner.Scan() {
cmp := strings.Split(scanner.Text(), " => ")
if len(cmp) > 1 && cmp[1] == "#" {
pots := strings.Split(cmp[0], "")
patterns = append(patterns, pots)
}
}
return &initialState, &patterns
}
func extendGeneration(shift int, generation []string) (int, *[]string) {
result := []string{}
newShift := shift
maxLeftPadding := 4
for i := 0; i < maxLeftPadding; i++ {
if generation[i] == "#" {
newShift += maxLeftPadding - i + 1
for j := 0; j <= maxLeftPadding-i; j++ {
result = append(result, ".")
}
break
}
}
result = append(result, generation...)
maxRightPadding := 4
for i := 0; i < maxRightPadding; i++ {
if generation[len(generation)-i-1] == "#" {
for j := 0; j < maxRightPadding-i; j++ {
result = append(result, ".")
}
}
}
return newShift, &result
}
func calculateGenerations(initialState *[]string, patterns *[][]string, generationCount int) int {
initialShift, extendedGeneration := extendGeneration(0, *initialState)
shift := initialShift
prevGeneration := *extendedGeneration
currentGeneration := []string{}
for generation := 0; generation < generationCount; generation++ {
currentGeneration = append(currentGeneration, ".", ".")
for middlePot := 2; middlePot <= len(prevGeneration)-3; middlePot++ {
potSlice := prevGeneration[middlePot-2 : middlePot+3]
matching := false
for _, pattern := range *patterns {
if reflect.DeepEqual(pattern, potSlice) {
matching = true
break
}
}
if matching {
currentGeneration = append(currentGeneration, "#")
} else {
currentGeneration = append(currentGeneration, ".")
}
}
newShift, extendedGeneration := extendGeneration(shift, currentGeneration)
shift = newShift
prevGeneration = *extendedGeneration
currentGeneration = []string{}
}
total := 0
for i, pot := range prevGeneration {
if pot == "#" {
total += i - shift
}
}
return total
}
func solveTask1(initialState *[]string, patterns *[][]string) int {
return calculateGenerations(initialState, patterns, 20)
}
func solveTask2(initialState *[]string, patterns *[][]string) int {
var generation int
currentDiff := 0
repeated := 0
for generation = 1; ; generation += 10 {
diff := calculateGenerations(initialState, patterns, generation) - calculateGenerations(initialState, patterns, generation-1)
if diff == currentDiff {
repeated++
}
if repeated > 5 {
break
}
currentDiff = diff
}
increment := calculateGenerations(initialState, patterns, generation) - calculateGenerations(initialState, patterns, generation-1)
return calculateGenerations(initialState, patterns, generation) + (50000000000-(generation))*increment
}
func main() {
initialState, patterns := getData()
fmt.Println("Task 1 solution is", solveTask1(initialState, patterns))
fmt.Println("Task 2 solution is", solveTask2(initialState, patterns))
}
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func move(field *[][]string, carts *[]*Cart) bool {
for _, cart := range *carts {
cart.Moved = false
}
notCrashed := 0
var last *Cart
for _, cart := range *carts {
if !cart.Crashed {
notCrashed++
last = cart
}
}
lastTick := notCrashed == 1
for rowNumber, row := range *field {
for cellNumber, _ := range row {
for _, cart := range *carts {
if cart.Row == rowNumber && cart.Cell == cellNumber && !cart.Moved && !cart.Crashed {
cart.Moved = true
if cart.Dir == ">" {
cart.Cell++
rightCell := (*field)[rowNumber][cellNumber+1]
if rightCell == "\\" {
cart.Dir = "v"
} else if rightCell == "/" {
cart.Dir = "^"
} else if rightCell == "+" {
if cart.NextTurn == "l" {
cart.NextTurn = "s"
cart.Dir = "^"
} else if cart.NextTurn == "s" {
cart.NextTurn = "r"
} else if cart.NextTurn == "r" {
cart.NextTurn = "l"
cart.Dir = "v"
}
}
} else if cart.Dir == "<" {
cart.Cell--
leftCell := (*field)[rowNumber][cellNumber-1]
if leftCell == "\\" {
cart.Dir = "^"
} else if leftCell == "/" {
cart.Dir = "v"
} else if leftCell == "+" {
if cart.NextTurn == "l" {
cart.NextTurn = "s"
cart.Dir = "v"
} else if cart.NextTurn == "s" {
cart.NextTurn = "r"
} else if cart.NextTurn == "r" {
cart.NextTurn = "l"
cart.Dir = "^"
}
}
} else if cart.Dir == "v" {
cart.Row++
bottomCell := (*field)[rowNumber+1][cellNumber]
if bottomCell == "\\" {
cart.Dir = ">"
} else if bottomCell == "/" {
cart.Dir = "<"
} else if bottomCell == "+" {
if cart.NextTurn == "l" {
cart.NextTurn = "s"
cart.Dir = ">"
} else if cart.NextTurn == "s" {
cart.NextTurn = "r"
} else if cart.NextTurn == "r" {
cart.NextTurn = "l"
cart.Dir = "<"
}
}
} else if cart.Dir == "^" {
cart.Row--
topCell := (*field)[rowNumber-1][cellNumber]
if topCell == "\\" {
cart.Dir = "<"
} else if topCell == "/" {
cart.Dir = ">"
} else if topCell == "+" {
if cart.NextTurn == "l" {
cart.NextTurn = "s"
cart.Dir = "<"
} else if cart.NextTurn == "s" {
cart.NextTurn = "r"
} else if cart.NextTurn == "r" {
cart.NextTurn = "l"
cart.Dir = ">"
}
}
}
for _, anotherCart := range *carts {
if !anotherCart.Crashed && cart != anotherCart && cart.Row == anotherCart.Row && cart.Cell == anotherCart.Cell {
cart.Crashed = true
anotherCart.Crashed = true
fmt.Println(fmt.Sprintf("Crash %d,%d", cart.Cell, cart.Row))
}
}
}
}
if lastTick {
fmt.Println(fmt.Sprintf("Last cart %d,%d", last.Cell, last.Row))
return true
}
}
}
return false
}
type Cart struct {
Row int
Cell int
Dir string
Moved bool
Crashed bool
NextTurn string
}
func getData() (*[][]string, *[]*Cart) {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
carts := []*Cart{}
field := [][]string{}
rowNumber := 0
for scanner.Scan() {
chars := strings.Split(scanner.Text(), "")
row := []string{}
for cellNumber, cell := range chars {
if cell == "^" || cell == "v" {
carts = append(carts, &Cart{Row: rowNumber, Cell: cellNumber, Dir: cell, NextTurn: "l"})
row = append(row, "|")
} else if cell == ">" || cell == "<" {
carts = append(carts, &Cart{Row: rowNumber, Cell: cellNumber, Dir: cell, NextTurn: "l"})
row = append(row, "-")
} else {
row = append(row, cell)
}
}
field = append(field, row)
rowNumber++
}
return &field, &carts
}
func main() {
field, carts := getData()
for {
completed := move(field, carts)
if completed {
break
}
}
}
package main
import (
"fmt"
"strconv"
"strings"
)
type Recipe struct {
Value int
Next *Recipe
Prev *Recipe
}
type Scoreboard struct {
First *Recipe
Last *Recipe
RecipeCount int
}
func (scoreboard *Scoreboard) Move(recipe *Recipe) *Recipe {
result := recipe
for i := 0; i < recipe.Value+1; i++ {
result = result.Next
if result == nil {
result = scoreboard.First
}
}
return result
}
func (scoreboard *Scoreboard) AddRecipe(recipe *Recipe) {
scoreboard.Last.Next = recipe
recipe.Prev = scoreboard.Last
scoreboard.Last = recipe
scoreboard.RecipeCount++
}
func (scoreboard *Scoreboard) LastSequence(length int) string {
recipe := scoreboard.Last
result := ""
for i := 0; i < length; i++ {
if recipe == nil {
break
}
result = strconv.Itoa(recipe.Value) + result
recipe = recipe.Prev
}
return result
}
func initScoreboard() *Scoreboard {
SecondRecipe := Recipe{Value: 7}
FirstRecipe := Recipe{Value: 3, Next: &SecondRecipe}
SecondRecipe.Prev = &FirstRecipe
return &Scoreboard{First: &FirstRecipe, Last: &SecondRecipe, RecipeCount: 2}
}
func makeNewRecipes(firstElf *Recipe, secondElf *Recipe) *[]string {
values := strings.Split(strconv.Itoa(firstElf.Value+secondElf.Value), "")
return &values
}
func solveTask1(input int) string {
scoreboard := initScoreboard()
firstElf := scoreboard.First
secondElf := scoreboard.Last
resultRecipes := []string{}
for i := 0; ; i++ {
values := makeNewRecipes(firstElf, secondElf)
for _, value := range *values {
stringValue, _ := strconv.Atoi(value)
scoreboard.AddRecipe(&Recipe{Value: stringValue})
if scoreboard.RecipeCount > input {
resultRecipes = append(resultRecipes, value)
}
}
if len(resultRecipes) >= 10 {
return strings.Join(resultRecipes[0:10], "")
}
firstElf = scoreboard.Move(firstElf)
secondElf = scoreboard.Move(secondElf)
}
}
func solveTask2(sequence string) int {
scoreboard := initScoreboard()
firstElf := scoreboard.First
secondElf := scoreboard.Last
for i := 0; ; i++ {
values := makeNewRecipes(firstElf, secondElf)
for _, value := range *values {
stringValue, _ := strconv.Atoi(value)
scoreboard.AddRecipe(&Recipe{Value: stringValue})
if scoreboard.LastSequence(len(sequence)) == sequence {
return scoreboard.RecipeCount - len(sequence)
}
}
firstElf = scoreboard.Move(firstElf)
secondElf = scoreboard.Move(secondElf)
}
}
func main() {
const input = "147061"
recipeCount, _ := strconv.Atoi(input)
fmt.Println("Task 1 solution is", solveTask1(recipeCount))
fmt.Println("Task 2 solution is", solveTask2(input))
}
package main
import (
"bufio"
"fmt"
"os"
"reflect"
"strconv"
"strings"
)
type Sample struct {
Before *[]int
Instruction *[]int
After *[]int
}
type Operation interface {
Title() string
Execute(registers *[]int, instruction *[]int)
}
func Check(op Operation, sample *Sample) bool {
registers := make([]int, 4)
copy(registers, *sample.Before)
op.Execute(&registers, sample.Instruction)
return reflect.DeepEqual(*sample.After, registers)
}
// -------------------------------
type Addr struct{}
func (op Addr) Title() string {
return "addr"
}
func (_ Addr) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := (*registers)[instructionData[2]]
(*registers)[instructionData[3]] = arg1 + arg2
}
// -------------------------------
type Addi struct{}
func (_ Addi) Title() string {
return "addi"
}
func (_ Addi) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := instructionData[2]
(*registers)[instructionData[3]] = arg1 + arg2
}
// -------------------------------
type Murl struct{}
func (_ Murl) Title() string {
return "murl"
}
func (_ Murl) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := (*registers)[instructionData[2]]
(*registers)[instructionData[3]] = arg1 * arg2
}
// -------------------------------
type Muli struct{}
func (_ Muli) Title() string {
return "muli"
}
func (_ Muli) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := instructionData[2]
(*registers)[instructionData[3]] = arg1 * arg2
}
// -------------------------------
type Banr struct{}
func (_ Banr) Title() string {
return "banr"
}
func (_ Banr) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := (*registers)[instructionData[2]]
(*registers)[instructionData[3]] = arg1 & arg2
}
// -------------------------------
type Bani struct{}
func (_ Bani) Title() string {
return "bani"
}
func (_ Bani) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := instructionData[2]
(*registers)[instructionData[3]] = arg1 & arg2
}
// -------------------------------
type Borr struct{}
func (_ Borr) Title() string {
return "borr"
}
func (_ Borr) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := (*registers)[instructionData[2]]
(*registers)[instructionData[3]] = arg1 | arg2
}
// -------------------------------
type Bori struct{}
func (_ Bori) Title() string {
return "bori"
}
func (_ Bori) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := instructionData[2]
(*registers)[instructionData[3]] = arg1 | arg2
}
// -------------------------------
type Setr struct{}
func (_ Setr) Title() string {
return "setr"
}
func (_ Setr) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
(*registers)[instructionData[3]] = (*registers)[instructionData[1]]
}
// -------------------------------
type Seti struct{}
func (_ Seti) Title() string {
return "seti"
}
func (_ Seti) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
(*registers)[instructionData[3]] = instructionData[1]
}
// -------------------------------
type Gtir struct{}
func (_ Gtir) Title() string {
return "gtir"
}
func (_ Gtir) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := instructionData[1]
arg2 := (*registers)[instructionData[2]]
if arg1 > arg2 {
(*registers)[instructionData[3]] = 1
} else {
(*registers)[instructionData[3]] = 0
}
}
// -------------------------------
type Gtri struct{}
func (_ Gtri) Title() string {
return "gtri"
}
func (_ Gtri) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := instructionData[2]
if arg1 > arg2 {
(*registers)[instructionData[3]] = 1
} else {
(*registers)[instructionData[3]] = 0
}
}
// -------------------------------
type Gtrr struct{}
func (_ Gtrr) Title() string {
return "gtrr"
}
func (_ Gtrr) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := (*registers)[instructionData[2]]
if arg1 > arg2 {
(*registers)[instructionData[3]] = 1
} else {
(*registers)[instructionData[3]] = 0
}
}
// -------------------------------
type Eqir struct{}
func (_ Eqir) Title() string {
return "eqir"
}
func (_ Eqir) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := instructionData[1]
arg2 := (*registers)[instructionData[2]]
if arg1 == arg2 {
(*registers)[instructionData[3]] = 1
} else {
(*registers)[instructionData[3]] = 0
}
}
// -------------------------------
type Eqri struct{}
func (_ Eqri) Title() string {
return "eqri"
}
func (_ Eqri) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := instructionData[2]
if arg1 == arg2 {
(*registers)[instructionData[3]] = 1
} else {
(*registers)[instructionData[3]] = 0
}
}
// -------------------------------
type Eqrr struct{}
func (_ Eqrr) Title() string {
return "eqrr"
}
func (_ Eqrr) Execute(registers *[]int, instruction *[]int) {
instructionData := *instruction
arg1 := (*registers)[instructionData[1]]
arg2 := (*registers)[instructionData[2]]
if arg1 == arg2 {
(*registers)[instructionData[3]] = 1
} else {
(*registers)[instructionData[3]] = 0
}
}
// -------------------------------
func getData() (*[]*Sample, *[]*[]int) {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
samples := []*Sample{}
var sample *Sample
for scanner.Scan() {
input := scanner.Text()
if input == "" {
if sample == nil {
break
}
samples = append(samples, sample)
sample = nil
} else if sample == nil {
before := []int{}
input = strings.Replace(input, "Before: [", "", 1)
input = strings.Replace(input, "]", "", 1)
for _, c := range strings.Split(input, ", ") {
intValue, _ := strconv.Atoi(c)
before = append(before, intValue)
}
sample = &Sample{Before: &before}
} else if sample.Instruction == nil {
instruction := []int{}
for _, c := range strings.Split(input, " ") {
intValue, _ := strconv.Atoi(c)
instruction = append(instruction, intValue)
}
sample.Instruction = &instruction
} else {
after := []int{}
input = strings.Replace(input, "After: [", "", 1)
input = strings.Replace(input, "]", "", 1)
for _, c := range strings.Split(input, ", ") {
intValue, _ := strconv.Atoi(c)
after = append(after, intValue)
}
sample.After = &after
}
}
program := []*[]int{}
scanner.Scan()
scanner.Text()
for scanner.Scan() {
input := scanner.Text()
row := []int{}
for _, c := range strings.Split(input, " ") {
intValue, _ := strconv.Atoi(c)
row = append(row, intValue)
}
program = append(program, &row)
}
return &samples, &program
}
func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
func main() {
samples, program := getData()
// samples, _ := getData()
operations := []Operation{
Addi{},
Addr{},
Murl{},
Muli{},
Banr{},
Bani{},
Borr{},
Bori{},
Setr{},
Seti{},
Gtir{},
Gtri{},
Gtrr{},
Eqir{},
Eqri{},
Eqrr{},
}
behaveLikeThree := 0
for _, sample := range *samples {
matchingCount := 0
for _, operation := range operations {
if Check(operation, sample) {
matchingCount++
}
}
if matchingCount >= 3 {
behaveLikeThree++
}
}
fmt.Println("Task 1 solution is", behaveLikeThree)
possible := [16][]string{}
for _, sample := range *samples {
for _, operation := range operations {
if Check(operation, sample) {
opcode := (*sample.Instruction)[0]
if !contains(possible[opcode], operation.Title()) {
possible[opcode] = append(possible[opcode], operation.Title())
}
}
}
}
uniqueOps := map[int]string{}
for {
for op, candidates := range possible {
if len(candidates) == 1 {
uniqueOps[op] = candidates[0]
}
}
for _, symOpcode := range uniqueOps {
for op, candidates := range possible {
newCandidates := []string{}
for _, possibleOpcode := range candidates {
if possibleOpcode != symOpcode {
newCandidates = append(newCandidates, possibleOpcode)
}
}
possible[op] = newCandidates
}
}
if len(uniqueOps) == len(possible) {
break
}
}
registers := make([]int, 4)
for _, instruction := range *program {
opcode := uniqueOps[(*instruction)[0]]
var operation *Operation
for _, op := range operations {
if op.Title() == opcode {
operation = &op
break
}
}
(*operation).Execute(&registers, instruction)
}
fmt.Println("Task 2 solution is", registers[0])
}
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func getField() *[][]string {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
field := [][]string{}
for scanner.Scan() {
row := strings.Split(scanner.Text(), "")
field = append(field, row)
}
return &field
}
const Open = "."
const Tree = "|"
const Lumberyard = "#"
func acresAround(field *[][]string, rowIndex int, acreIndex int) map[string]int {
around := map[string]int{}
for rowMod := -1; rowMod <= 1; rowMod++ {
for acreMod := -1; acreMod <= 1; acreMod++ {
if rowMod == 0 && acreMod == 0 {
continue
}
rowNumber := rowIndex + rowMod
if rowNumber < 0 || rowNumber >= len(*field) {
continue
}
row := (*field)[rowNumber]
acreNumber := acreIndex + acreMod
if acreNumber < 0 || acreNumber >= len(row) {
continue
}
content := row[acreNumber]
count, found := around[content]
if found {
around[content] = count + 1
} else {
around[content] = 1
}
}
}
return around
}
func newAcre(field *[][]string, rowIndex int, acreIndex int) string {
around := acresAround(field, rowIndex, acreIndex)
switch (*field)[rowIndex][acreIndex] {
case Open:
if around[Tree] >= 3 {
return Tree
}
return Open
case Tree:
if around[Lumberyard] >= 3 {
return Lumberyard
}
return Tree
case Lumberyard:
if around[Lumberyard] >= 1 && around[Tree] >= 1 {
return Lumberyard
}
return Open
}
return ""
}
func showField(field *[][]string) {
for _, row := range *field {
for _, acre := range row {
fmt.Print(acre)
}
fmt.Println()
}
fmt.Println()
}
func scoreFor(field *[][]string) int {
trees := 0
lumberyards := 0
for _, row := range *field {
for _, acre := range row {
if acre == Tree {
trees++
} else if acre == Lumberyard {
lumberyards++
}
}
}
return trees * lumberyards
}
func solveTask1() int {
field := getField()
for minute := 1; minute <= 10; minute++ {
newField := [][]string{}
for rowIndex, row := range *field {
newRow := []string{}
for acreIndex := range row {
newRow = append(newRow, newAcre(field, rowIndex, acreIndex))
}
newField = append(newField, newRow)
}
field = &newField
}
return scoreFor(field)
}
func solveTask2() int {
field := getField()
scores := []int{}
for minute := 1; ; minute++ {
newField := [][]string{}
for rowIndex, row := range *field {
newRow := []string{}
for acreIndex := range row {
newRow = append(newRow, newAcre(field, rowIndex, acreIndex))
}
newField = append(newField, newRow)
}
field = &newField
newScore := scoreFor(field)
candidateIndex := -1
for index, score := range scores {
if score == newScore {
candidateIndex = index
break
}
}
scores = append(scores, newScore)
period := minute - candidateIndex
if period > 3 && candidateIndex >= 0 {
isPattern := true
for currentIndex := minute - 1; candidateIndex < currentIndex; currentIndex-- {
prevIndex := currentIndex - period + 1
if prevIndex < 0 || scores[currentIndex] != scores[prevIndex] {
isPattern = false
break
}
}
if !isPattern {
continue
}
periodScores := scores[len(scores)-period-1 : len(scores)-2]
idx := period - ((1000000000 - minute) % period) - 1
result := periodScores[idx]
return result
}
}
}
func main() {
fmt.Println("Task 1 solution is", solveTask1())
fmt.Println("Task 2 solution is", solveTask2())
}
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func getProgram() (string, *[]string) {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Scan()
ipInit := scanner.Text()
program := []string{}
for scanner.Scan() {
program = append(program, scanner.Text())
}
return ipInit, &program
}
const A = 0
const B = 1
const C = 2
func solveTask(zeroRegisterValue int) int {
ipInit, program := getProgram()
instructionPointer := 0
ipRegister, _ := strconv.Atoi(strings.Replace(ipInit, "#ip ", "", 1))
registers := []int{zeroRegisterValue, 0, 0, 0, 0, 0}
for {
if instructionPointer >= len(*program) {
break
}
if instructionPointer == 1 {
total := 0
for x := 1; x < registers[5]+1; x++ {
if registers[5]%x == 0 {
total += x
}
}
return total
}
registers[ipRegister] = instructionPointer
line := (*program)[instructionPointer]
opcode := line[0:5]
instrStrings := strings.Split(strings.Replace(line, opcode, "", 1), " ")
instruction := []int{}
for _, instrString := range instrStrings {
register, _ := strconv.Atoi(instrString)
instruction = append(instruction, register)
}
if strings.Contains(opcode, "addi") {
registers[instruction[C]] = registers[instruction[A]] + instruction[B]
} else if strings.Contains(opcode, "addr") {
registers[instruction[C]] = registers[instruction[A]] + registers[instruction[B]]
} else if strings.Contains(opcode, "seti") {
registers[instruction[C]] = instruction[A]
} else if strings.Contains(opcode, "setr") {
registers[instruction[C]] = registers[instruction[A]]
} else if strings.Contains(opcode, "mulr") {
registers[instruction[C]] = registers[instruction[A]] * registers[instruction[B]]
} else if strings.Contains(opcode, "muli") {
registers[instruction[C]] = registers[instruction[A]] * instruction[B]
} else if strings.Contains(opcode, "eqrr") {
if registers[instruction[A]] == registers[instruction[B]] {
registers[instruction[C]] = 1
} else {
registers[instruction[C]] = 0
}
} else if strings.Contains(opcode, "gtrr") {
if registers[instruction[A]] > registers[instruction[B]] {
registers[instruction[C]] = 1
} else {
registers[instruction[C]] = 0
}
}
instructionPointer = registers[ipRegister]
instructionPointer++
}
return registers[0]
}
func main() {
fmt.Println("Task 1 solution is", solveTask(0))
fmt.Println("Task 2 solution is", solveTask(1))
}
package main
import (
"bufio"
"fmt"
"os"
)
func getRegex() string {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Scan()
regex := scanner.Text()
return regex
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
type Room struct {
X int
Y int
}
func main() {
regex := getRegex()
positions := []Room{}
currentRoom := Room{X: 0, Y: 0}
prevRoom := Room{currentRoom.X, currentRoom.Y}
connected := map[Room][]Room{}
distances := map[Room]int{}
for i := 1; i < len(regex)-1; i++ {
char := regex[i : i+1]
if char == "(" {
positions = append(positions, Room{X: currentRoom.X, Y: currentRoom.Y})
} else if char == ")" {
currentRoom, positions = positions[len(positions)-1], positions[:len(positions)-1]
} else if char == "|" {
currentRoom = positions[len(positions)-1]
} else {
switch char {
case "N":
currentRoom.Y--
case "E":
currentRoom.X++
case "S":
currentRoom.Y++
case "W":
currentRoom.X--
}
contains := false
for _, el := range connected[currentRoom] {
if el == prevRoom {
contains = true
break
}
}
if !contains {
connected[currentRoom] = append(connected[currentRoom], prevRoom)
}
if distances[currentRoom] != 0 {
distances[currentRoom] = min(distances[currentRoom], distances[prevRoom]+1)
} else {
distances[currentRoom] = distances[prevRoom] + 1
}
}
prevRoom = currentRoom
}
maxDistance := 0
for _, distance := range distances {
if distance > maxDistance {
maxDistance = distance
}
}
fmt.Println("Task 1 solution is", maxDistance)
roomCount := 0
for _, distance := range distances {
if distance >= 1000 {
roomCount++
}
}
fmt.Println("Task 2 solution is", roomCount)
}
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func getInput() (uint64, int, int) {
file, _ := os.Open("./input.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Scan()
depth := strings.Replace(scanner.Text(), "depth: ", "", 1)
intDepth, _ := strconv.Atoi(depth)
scanner.Scan()
coordinates := strings.Split(strings.Replace(scanner.Text(), "target: ", "", 1), ",")
x, _ := strconv.Atoi(coordinates[0])
y, _ := strconv.Atoi(coordinates[1])
return uint64(intDepth), x, y
}
func main() {
depth, targetX, targetY := getInput()
geologicIndex := [][]uint64{}
erosionLevel := [][]uint64{}
totalRisk := 0
for y := 0; y <= targetY; y++ {
geoRow := []uint64{}
erosionRow := []uint64{}
for x := 0; x <= targetX; x++ {
var index uint64
var level uint64
if x == 0 && y == 0 || x == targetX && y == targetY {
index = 0
} else if y == 0 {
index = uint64(16807 * x)
} else if x == 0 {
index = uint64(48271 * y)
} else {
index = erosionRow[x-1] * erosionLevel[y-1][x]
}
level = (index + depth) % 20183
geoRow = append(geoRow, index)
erosionRow = append(erosionRow, level)
totalRisk += int(level % 3)
}
geologicIndex = append(geologicIndex, geoRow)
erosionLevel = append(erosionLevel, erosionRow)
}
fmt.Println("Task 1 solution is", totalRisk)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment