day18, example
This commit is contained in:
parent
955bdc78c1
commit
49fc57029f
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
func Run() int {
|
func Run() int {
|
||||||
fmt.Println("hello from day 17")
|
fmt.Println("hello from day 17")
|
||||||
filename := "day17/example"
|
filename := "day17/input"
|
||||||
field := NewField(filename)
|
field := NewField(filename)
|
||||||
log.Printf("%+v\n", field)
|
log.Printf("%+v\n", field)
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ func (p *PathSegmentEnd) NextDirections2() (next []Direction) {
|
||||||
next = append(next, p.lastDirection)
|
next = append(next, p.lastDirection)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("getting directions from %+v they are %+v", p, next)
|
// log.Printf("getting directions from %+v they are %+v", p, next)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
R 6 (#70c710)
|
||||||
|
D 5 (#0dc571)
|
||||||
|
L 2 (#5713f0)
|
||||||
|
D 2 (#d2c081)
|
||||||
|
R 2 (#59c680)
|
||||||
|
D 2 (#411b91)
|
||||||
|
L 5 (#8ceee2)
|
||||||
|
U 2 (#caa173)
|
||||||
|
L 1 (#1b58a2)
|
||||||
|
U 2 (#caa171)
|
||||||
|
R 2 (#7807d2)
|
||||||
|
U 3 (#a77fa3)
|
||||||
|
L 2 (#015232)
|
||||||
|
U 2 (#7a21e3)
|
|
@ -0,0 +1,256 @@
|
||||||
|
package day18
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"slices"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Run() int {
|
||||||
|
fmt.Println("hello day 18")
|
||||||
|
log.Println("problem of lagoon bgins")
|
||||||
|
filename := "day18/example"
|
||||||
|
instructions := ReadInstructionas(filename)
|
||||||
|
h, w := calcHeightWidth(instructions)
|
||||||
|
field := CreateField(h, w)
|
||||||
|
|
||||||
|
fmt.Println(field.String())
|
||||||
|
|
||||||
|
field.digByInstructions(instructions)
|
||||||
|
|
||||||
|
fmt.Println(field.String())
|
||||||
|
// i'll start at (0,0), let's first just dig out the thing and check result
|
||||||
|
field.digInsides()
|
||||||
|
|
||||||
|
fmt.Println(field.String())
|
||||||
|
|
||||||
|
return field.countDugOut()
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine size of field. max(sum(up), sum(down)) for height,
|
||||||
|
// same for left and right,
|
||||||
|
// translate (0,0) into center of the field
|
||||||
|
//
|
||||||
|
// have cells, with coord. and i guess four sides, with color.
|
||||||
|
// i guess have directions, map[direction]color
|
||||||
|
// and have 'opposite' on directoin.
|
||||||
|
// for each direction apply it to cell coord, get cell, get opposite directoin and color it
|
||||||
|
//
|
||||||
|
// then have method on field and cell that excavates cell and colors all neighbors
|
||||||
|
//
|
||||||
|
// last part is filling in isides, should be ok with horizontal scans from left by even crossings
|
||||||
|
|
||||||
|
type Direction int
|
||||||
|
const (Upward Direction = iota
|
||||||
|
Downward
|
||||||
|
Leftward
|
||||||
|
Rightward)
|
||||||
|
|
||||||
|
func (d Direction)opposite() Direction {
|
||||||
|
switch d {
|
||||||
|
case Upward:
|
||||||
|
return Downward
|
||||||
|
case Downward:
|
||||||
|
return Upward
|
||||||
|
case Leftward:
|
||||||
|
return Rightward
|
||||||
|
case Rightward:
|
||||||
|
return Leftward
|
||||||
|
}
|
||||||
|
panic("unaccounted direction")
|
||||||
|
}
|
||||||
|
|
||||||
|
var DirectionNames []string = []string{"U", "D", "L", "R"}
|
||||||
|
|
||||||
|
func (d Direction)String() string {
|
||||||
|
return DirectionNames[d]
|
||||||
|
}
|
||||||
|
func DirectionFromString(s string) Direction {
|
||||||
|
index := slices.Index(DirectionNames, s)
|
||||||
|
if index == -1 {
|
||||||
|
panic(fmt.Sprint("bad direction", s))
|
||||||
|
}
|
||||||
|
return Direction(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Instruction struct {
|
||||||
|
Direction Direction
|
||||||
|
Steps int
|
||||||
|
Color string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadInstructionas(filename string) (result []Instruction) {
|
||||||
|
bytes, err := os.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprint("error reading file: ", filename))
|
||||||
|
}
|
||||||
|
text := strings.TrimSpace(string(bytes))
|
||||||
|
for _, line := range strings.Split(text, "\n") {
|
||||||
|
result = append(result, ReadInstruction(line))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadInstruction(line string) Instruction {
|
||||||
|
fields := strings.Fields(line)
|
||||||
|
direction := DirectionFromString(fields[0])
|
||||||
|
steps, err := strconv.Atoi(fields[1])
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprint("bad steps in line: ", line))
|
||||||
|
}
|
||||||
|
color := fields[2][1 : len(fields[2])-1]
|
||||||
|
|
||||||
|
return Instruction{Direction: direction, Steps: steps, Color: color}
|
||||||
|
}
|
||||||
|
|
||||||
|
func calcHeightWidth(instructions []Instruction) (height, width int) {
|
||||||
|
movements := make(map[Direction]int)
|
||||||
|
for _, instr := range instructions {
|
||||||
|
movements[instr.Direction] += instr.Steps
|
||||||
|
}
|
||||||
|
if movements[Downward] > movements[Upward] {
|
||||||
|
height = 2 * movements[Downward]
|
||||||
|
} else {
|
||||||
|
height = 2 * movements[Upward]
|
||||||
|
}
|
||||||
|
|
||||||
|
if movements[Leftward] > movements[Rightward] {
|
||||||
|
width = 2 * movements[Leftward]
|
||||||
|
} else {
|
||||||
|
width = 2 * movements[Rightward]
|
||||||
|
}
|
||||||
|
|
||||||
|
height += 10
|
||||||
|
width += 10
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type Coord struct {
|
||||||
|
X, Y int
|
||||||
|
}
|
||||||
|
func (c Coord)applyDirection(d Direction) Coord {
|
||||||
|
switch d {
|
||||||
|
case Upward:
|
||||||
|
c.Y -= 1
|
||||||
|
case Downward:
|
||||||
|
c.Y += 1
|
||||||
|
case Leftward:
|
||||||
|
c.X -= 1
|
||||||
|
case Rightward:
|
||||||
|
c.X += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
type Cell struct {
|
||||||
|
IsDug bool
|
||||||
|
Walls map[Direction]string
|
||||||
|
Coord Coord
|
||||||
|
}
|
||||||
|
type Field struct {
|
||||||
|
Height, Width int
|
||||||
|
Cells [][]*Cell
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateField(height, width int) Field {
|
||||||
|
rows := make([][]*Cell, height)
|
||||||
|
for i := 0; i < height; i++ {
|
||||||
|
row := make([]*Cell, width)
|
||||||
|
rows[i] = row
|
||||||
|
for j := 0; j < width; j++ {
|
||||||
|
row[j] = &Cell{
|
||||||
|
Walls: make(map[Direction]string),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Field{
|
||||||
|
Height: height, Width: width,
|
||||||
|
Cells: rows,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field)coordToIndices(c Coord) (row, col int) {
|
||||||
|
row = c.Y + (f.Height/2)
|
||||||
|
col = c.X + (f.Width/2)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field)digByInstructions(instructions []Instruction) {
|
||||||
|
runnerCoord := Coord{X: 0, Y: 0}
|
||||||
|
row, col := f.coordToIndices(runnerCoord)
|
||||||
|
f.Cells[row][col].IsDug = true
|
||||||
|
|
||||||
|
for _, instruction := range instructions {
|
||||||
|
for i := 0; i < instruction.Steps; i++ {
|
||||||
|
runnerCoord = runnerCoord.applyDirection(instruction.Direction)
|
||||||
|
row, col := f.coordToIndices(runnerCoord)
|
||||||
|
f.Cells[row][col].IsDug = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field)String() string {
|
||||||
|
s := "\n"
|
||||||
|
for _, row := range f.Cells {
|
||||||
|
for _, cell := range row {
|
||||||
|
if cell.IsDug {
|
||||||
|
s += "#"
|
||||||
|
} else {
|
||||||
|
s += "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s += "\n"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field)digInsides() {
|
||||||
|
for row := 0; row < f.Height; row++ {
|
||||||
|
isInside := false
|
||||||
|
seenUp, seenDown := false, false // for detecting L---7 walls
|
||||||
|
for col := 0; col < f.Width - 1; col++ {
|
||||||
|
cellPtr := f.Cells[row][col]
|
||||||
|
rightCell := f.Cells[row][col+1]
|
||||||
|
if cellPtr.IsDug {
|
||||||
|
upCell := f.Cells[row-1][col]
|
||||||
|
downCell := f.Cells[row+1][col]
|
||||||
|
if !rightCell.IsDug {
|
||||||
|
if (upCell.IsDug && seenDown) || (downCell.IsDug && seenUp) {
|
||||||
|
isInside = !isInside
|
||||||
|
}
|
||||||
|
seenUp, seenDown = false, false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// not a dug out cell, maybe inside and needs to be dug out
|
||||||
|
if isInside {
|
||||||
|
cellPtr.IsDug = true
|
||||||
|
}
|
||||||
|
if rightCell.IsDug {
|
||||||
|
nextUpCell := f.Cells[row-1][col+1]
|
||||||
|
nextDownCell := f.Cells[row+1][col+1]
|
||||||
|
seenUp = nextUpCell.IsDug
|
||||||
|
seenDown = nextDownCell.IsDug
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field)countDugOut() (result int) {
|
||||||
|
for _, row := range f.Cells {
|
||||||
|
for _, cell := range row {
|
||||||
|
if cell.IsDug {
|
||||||
|
result += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
6
main.go
6
main.go
|
@ -3,12 +3,12 @@ package main
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"sunshine.industries/aoc2023/day17"
|
"sunshine.industries/aoc2023/day18"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.Print("> starting run:")
|
log.Print("> starting run:")
|
||||||
|
|
||||||
result := day17.Run()
|
result := day18.Run()
|
||||||
log.Printf("\n\nday17 result: %d\n****\n", result)
|
log.Printf("\n\nday18 result: %d\n****\n", result)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue