Last active
December 26, 2018 07:18
-
-
Save DmitryTsepelev/aca578adf3269eaaa84832842c8d48a3 to your computer and use it in GitHub Desktop.
Advent of code 2018
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(®isters, 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(®isters, instruction) | |
} | |
fmt.Println("Task 2 solution is", registers[0]) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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