mirror of
https://github.com/onyx-and-iris/aoc2023.git
synced 2024-11-22 02:10:48 +00:00
day-10
This commit is contained in:
parent
4a7c9082ba
commit
f24a9085b3
53
day-10/check.go
Normal file
53
day-10/check.go
Normal file
@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
/*
|
||||
functions that check connections between pipes in each direction
|
||||
*/
|
||||
|
||||
func checkSouth(point point) point {
|
||||
if point.Y == len(pointsArray)-1 {
|
||||
return point
|
||||
}
|
||||
|
||||
target := pointsArray[point.Y+1].points[point.X]
|
||||
if point.S && target.N {
|
||||
return target
|
||||
}
|
||||
return point
|
||||
}
|
||||
|
||||
func checkEast(point point) point {
|
||||
if point.X == len(pointsArray[point.Y].points)-1 {
|
||||
return point
|
||||
}
|
||||
|
||||
target := pointsArray[point.Y].points[point.X+1]
|
||||
if point.E && target.W {
|
||||
return target
|
||||
}
|
||||
return point
|
||||
}
|
||||
|
||||
func checkNorth(point point) point {
|
||||
if point.Y == 0 {
|
||||
return point
|
||||
}
|
||||
|
||||
target := pointsArray[point.Y-1].points[point.X]
|
||||
if point.N && target.S {
|
||||
return target
|
||||
}
|
||||
return point
|
||||
}
|
||||
|
||||
func checkWest(point point) point {
|
||||
if point.X == 0 {
|
||||
return point
|
||||
}
|
||||
|
||||
target := pointsArray[point.Y].points[point.X-1]
|
||||
if point.W && target.E {
|
||||
return target
|
||||
}
|
||||
return point
|
||||
}
|
3
day-10/go.mod
Normal file
3
day-10/go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/onyx-and-iris/aoc2023/day-10
|
||||
|
||||
go 1.21.5
|
142
day-10/one.go
Normal file
142
day-10/one.go
Normal file
@ -0,0 +1,142 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type coords struct {
|
||||
X int
|
||||
Y int
|
||||
}
|
||||
|
||||
type points struct {
|
||||
points []point
|
||||
}
|
||||
|
||||
type point struct {
|
||||
N bool
|
||||
S bool
|
||||
E bool
|
||||
W bool
|
||||
coords
|
||||
identifier rune
|
||||
}
|
||||
|
||||
var pointsArray = []points{}
|
||||
|
||||
type tracker struct {
|
||||
init point
|
||||
point point
|
||||
last []coords
|
||||
}
|
||||
|
||||
func (t tracker) X() int {
|
||||
return t.point.X
|
||||
}
|
||||
|
||||
func (t tracker) Y() int {
|
||||
return t.point.Y
|
||||
}
|
||||
|
||||
// mapPoints builds the points array mapping connection types for each coordinate
|
||||
func mapPoints(lines []string) {
|
||||
pointsArray = make([]points, 0)
|
||||
|
||||
for i, line := range lines {
|
||||
var ps = make([]point, 0)
|
||||
for j, r := range line {
|
||||
switch r {
|
||||
case '|':
|
||||
ps = append(ps, point{N: true, S: true, E: false, W: false}) // N,S
|
||||
case '-':
|
||||
ps = append(ps, point{N: false, S: false, E: true, W: true}) // E, W
|
||||
case 'L':
|
||||
ps = append(ps, point{N: true, S: false, E: true, W: false}) // N, E
|
||||
case 'J':
|
||||
ps = append(ps, point{N: true, S: false, E: false, W: true}) // N, W
|
||||
case '7':
|
||||
ps = append(ps, point{N: false, S: true, E: false, W: true}) // S, W
|
||||
case 'F':
|
||||
ps = append(ps, point{N: false, S: true, E: true, W: false}) // S, E
|
||||
case '.':
|
||||
ps = append(ps, point{N: false, S: false, E: false, W: false}) // ground
|
||||
case 'S':
|
||||
ps = append(ps, point{N: true, S: true, E: true, W: true}) // start
|
||||
default:
|
||||
log.Debug("ground point")
|
||||
}
|
||||
ps[j].identifier = r
|
||||
ps[j].coords.Y = i
|
||||
ps[j].coords.X = j
|
||||
}
|
||||
pointsArray = append(pointsArray, points{points: ps})
|
||||
}
|
||||
}
|
||||
|
||||
// initializeTracker stores the starting point, creates coords array for tracking last moves
|
||||
func initializeTracker() tracker {
|
||||
tracker := tracker{last: make([]coords, 0)}
|
||||
for _, each := range pointsArray {
|
||||
for _, point := range each.points {
|
||||
if point.identifier == 'S' {
|
||||
tracker.init = point
|
||||
tracker.point = tracker.init
|
||||
tracker.last = make([]coords, 1)
|
||||
tracker.last = append(tracker.last, tracker.point.coords)
|
||||
}
|
||||
}
|
||||
}
|
||||
return tracker
|
||||
}
|
||||
|
||||
// walk moves along the pipes storing poinst that mark loop locations
|
||||
// it also keeps a track of last two moves
|
||||
// returns the number of steps to traverse all pipes
|
||||
func walk(tracker tracker) int {
|
||||
var steps int
|
||||
for steps := 0; steps == 0 || !comparePoints(tracker.init, tracker.point); steps++ {
|
||||
next := checkSouth(tracker.point)
|
||||
if !inLastMoves(tracker.last, next.coords) {
|
||||
log.Debug("moving south from ", string(tracker.point.identifier), " to ", string(next.identifier))
|
||||
tracker.point = next
|
||||
loop = append(loop, pointsArray[tracker.Y()].points[tracker.X()].coords)
|
||||
tracker.last = append(tracker.last[1:], next.coords)
|
||||
continue
|
||||
}
|
||||
next = checkEast(tracker.point)
|
||||
if !inLastMoves(tracker.last, next.coords) {
|
||||
log.Debug("moving east from ", string(tracker.point.identifier), " to ", string(next.identifier))
|
||||
tracker.point = next
|
||||
loop = append(loop, pointsArray[tracker.Y()].points[tracker.X()].coords)
|
||||
tracker.last = append(tracker.last[1:], next.coords)
|
||||
continue
|
||||
}
|
||||
next = checkNorth(tracker.point)
|
||||
if !inLastMoves(tracker.last, next.coords) {
|
||||
log.Debug("moving north from ", string(tracker.point.identifier), " to ", string(next.identifier))
|
||||
tracker.point = next
|
||||
loop = append(loop, pointsArray[tracker.Y()].points[tracker.X()].coords)
|
||||
tracker.last = append(tracker.last[1:], next.coords)
|
||||
continue
|
||||
}
|
||||
next = checkWest(tracker.point)
|
||||
if !inLastMoves(tracker.last, next.coords) {
|
||||
log.Debug("moving west from ", string(tracker.point.identifier), " to ", string(next.identifier))
|
||||
tracker.point = next
|
||||
loop = append(loop, pointsArray[tracker.Y()].points[tracker.X()].coords)
|
||||
tracker.last = append(tracker.last[1:], next.coords)
|
||||
continue
|
||||
}
|
||||
steps++
|
||||
}
|
||||
return steps
|
||||
}
|
||||
|
||||
// one returns the number of steps to reach the furthest point from the start
|
||||
func one(lines []string) int {
|
||||
mapPoints(lines)
|
||||
|
||||
tracker := initializeTracker()
|
||||
|
||||
return walk(tracker) / 2
|
||||
}
|
5
day-10/run.sh
Normal file
5
day-10/run.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
INPUT="input.txt"
|
||||
|
||||
cat $INPUT | go run .
|
21
day-10/solution.go
Normal file
21
day-10/solution.go
Normal file
@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetLevel(log.InfoLevel)
|
||||
}
|
||||
|
||||
func main() {
|
||||
lines := readlines()
|
||||
|
||||
ans := one(lines)
|
||||
fmt.Printf("solution one: %d\n", ans)
|
||||
|
||||
ans = two(lines)
|
||||
fmt.Printf("solution two: %d\n", ans)
|
||||
}
|
40
day-10/two.go
Normal file
40
day-10/two.go
Normal file
@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func debugPrint() {
|
||||
for _, points := range pointsArray {
|
||||
for _, point := range points.points {
|
||||
if contains(loop, point.coords) {
|
||||
fmt.Printf("%c ", point.identifier)
|
||||
} else {
|
||||
fmt.Printf(". ")
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
}
|
||||
|
||||
var loop []coords
|
||||
|
||||
// two
|
||||
func two(lines []string) int {
|
||||
if log.GetLevel() == log.DebugLevel {
|
||||
debugPrint()
|
||||
}
|
||||
|
||||
area := 0
|
||||
for i := 0; i < len(loop); i++ {
|
||||
next := loop[(i+1)%len(loop)]
|
||||
area += loop[i].X*next.Y - loop[i].Y*next.X
|
||||
}
|
||||
|
||||
area = int(math.Abs(float64(area))) / 2
|
||||
|
||||
return area - len(loop)/2 + 1
|
||||
}
|
50
day-10/util.go
Normal file
50
day-10/util.go
Normal file
@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// readlines reads lines from stdin.
|
||||
// returns input as an array of strings
|
||||
func readlines() []string {
|
||||
lines := []string{}
|
||||
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
// inLastMoves checks if next coords exists in past moves
|
||||
func inLastMoves(last []coords, b coords) bool {
|
||||
for _, co := range last {
|
||||
if co.X == b.X && co.Y == b.Y {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// comparePoints returns true if coordinates for two points match
|
||||
func comparePoints(a, b point) bool {
|
||||
return a.X == b.X && a.Y == b.Y
|
||||
}
|
||||
|
||||
// contains returns true if a slice of elements contains a given element
|
||||
func contains[T comparable](elems []T, v T) bool {
|
||||
for _, s := range elems {
|
||||
if v == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
Loading…
Reference in New Issue
Block a user