Skip to content

Commit

Permalink
Merge pull request #12 from feuerrot/day14
Browse files Browse the repository at this point in the history
day 14
  • Loading branch information
feuerrot authored Dec 14, 2022
2 parents 1374e43 + c833365 commit add76c8
Show file tree
Hide file tree
Showing 4 changed files with 402 additions and 0 deletions.
229 changes: 229 additions & 0 deletions 14.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
package main

import (
"fmt"
"strconv"
"strings"
)

type MapPoint int

const (
Air MapPoint = iota
Rock
Sand
)

type AOC202214SandMap struct {
// Point[y][x]
Point map[int]map[int]MapPoint
MaxY int
MinX int
MaxX int
Infinite bool
}

func (sm *AOC202214SandMap) DrawMap() string {
rtn := []string{}
yMax := sm.MaxY
if !sm.Infinite {
yMax += 2
}
for y := 0; y <= yMax; y++ {
line := ""
for x := sm.MinX; x <= sm.MaxX; x++ {
if x == 500 && y == 0 {
line += "+"
continue
}
pt := sm.GetPoint(x, y)
if pt == Air {
line += "."
} else if pt == Rock {
line += "#"
} else if pt == Sand {
line += "o"
}
}
rtn = append(rtn, line)
}

return strings.Join(rtn, "\n")
}

func (sm *AOC202214SandMap) SetPoint(x, y int, pt MapPoint) {
if sm.Point[y] == nil {
sm.Point[y] = make(map[int]MapPoint, 0)
}

sm.Point[y][x] = pt
if x > sm.MaxX {
sm.MaxX = x
} else if x < sm.MinX {
sm.MinX = x
}
}

func (sm *AOC202214SandMap) GetPoint(x, y int) MapPoint {
if !sm.Infinite && y == sm.MaxY+2 {
return Rock
}

if sm.Point[y] == nil {
sm.Point[y] = make(map[int]MapPoint)
return Air
}

elem, ok := sm.Point[y][x]
if !ok {
return Air
}
return elem
}

func (sm *AOC202214SandMap) AddSand() bool {
xPos, yPos := 500, 0
for {
if sm.Infinite {
// check if it fell off
if yPos > sm.MaxY {
return false
}
}

// check below
if sm.GetPoint(xPos, yPos+1) == Air {
yPos += 1
continue
}

// check below & left
if sm.GetPoint(xPos-1, yPos+1) == Air {
xPos -= 1
yPos += 1
continue
}

if sm.GetPoint(xPos+1, yPos+1) == Air {
xPos += 1
yPos += 1
continue
}

sm.SetPoint(xPos, yPos, Sand)
if xPos == 500 && yPos == 0 {
return false
}
return true
}
}

func (sm *AOC202214SandMap) ParseRocks(input string) error {
for _, line := range strings.Split(input, "\n") {
points := [][]int{}
for _, part := range strings.Split(line, " -> ") {
coord := strings.Split(part, ",")
coordX, err := strconv.Atoi(coord[0])
if err != nil {
return fmt.Errorf("can't parse coordinate %s: %v", part, err)
}
coordY, err := strconv.Atoi(coord[1])
if err != nil {
return fmt.Errorf("can't parse coordinate %s: %v", part, err)
}
if coordY > sm.MaxY {
sm.MaxY = coordY
}
if coordX < sm.MinX || sm.MinX == 0 {
sm.MinX = coordX
}
if coordX > sm.MaxX {
sm.MaxX = coordX
}

points = append(points, []int{coordX, coordY})
}

for i := 0; i < len(points)-1; i++ {
startX, startY := points[i][0], points[i][1]
endX, endY := points[i+1][0], points[i+1][1]

if startX == endX {
if startY > endY {
startY, endY = endY, startY
}
for y := startY; y <= endY; y++ {
sm.SetPoint(startX, y, Rock)
}
} else {
if startX > endX {
startX, endX = endX, startX
}
for x := startX; x <= endX; x++ {
sm.SetPoint(x, startY, Rock)
}
}
}
}

return nil
}

func AOC2022141Helper(input string) (int, error) {
sandMap := *&AOC202214SandMap{
Point: make(map[int]map[int]MapPoint),
Infinite: true,
}

err := sandMap.ParseRocks(input)
if err != nil {
return 0, fmt.Errorf("can't parse rocks: %v", err)
}

grains := 0
for {
if !sandMap.AddSand() {
break
}
grains += 1
}

return grains, nil
}

func AOC2022142Helper(input string) (int, error) {
sandMap := *&AOC202214SandMap{
Point: make(map[int]map[int]MapPoint),
}

err := sandMap.ParseRocks(input)
if err != nil {
return 0, fmt.Errorf("can't parse rocks: %v", err)
}

grains := 0
for {
grains += 1
if !sandMap.AddSand() {
break
}
}

return grains, nil
}

func AOC2022141(input string) (string, error) {
grains, err := AOC2022141Helper(input)
if err != nil {
return "", err
}
return fmt.Sprintf("%d", grains), nil
}

func AOC2022142(input string) (string, error) {
grains, err := AOC2022142Helper(input)
if err != nil {
return "", err
}
return fmt.Sprintf("%d", grains), nil
}
43 changes: 43 additions & 0 deletions 14_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package main

import "testing"

func TestAOC202214Part1(t *testing.T) {
test := struct {
input string
output int
}{
input: `498,4 -> 498,6 -> 496,6
503,4 -> 502,4 -> 502,9 -> 494,9`,
output: 24,
}

got, err := AOC2022141Helper(test.input)
if err != nil {
t.Fatalf("AOC202214Helper() err: %v", err)
}

if got != test.output {
t.Errorf("AOC202214Helper() missmatch:\nwant: %d\ngot: %d", test.output, got)
}
}

func TestAOC202214Part2(t *testing.T) {
test := struct {
input string
output int
}{
input: `498,4 -> 498,6 -> 496,6
503,4 -> 502,4 -> 502,9 -> 494,9`,
output: 93,
}

got, err := AOC2022142Helper(test.input)
if err != nil {
t.Fatalf("AOC202214Helper() err: %v", err)
}

if got != test.output {
t.Errorf("AOC202214Helper() missmatch:\nwant: %d\ngot: %d", test.output, got)
}
}
Loading

0 comments on commit add76c8

Please sign in to comment.