question 6
This commit is contained in:
1 parent
4039abe414
commit
780d9a52c7
4 files changed
+261
No files matched your search
@@ -0,0 +1,3 @@
|
|||||||
|
go 1.23
|
||||||
|
|
||||||
|
use .
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const realInput = "...#........................................#........#.................#............#.#.......................#...............#..#\n...#........#.....#..................................................................................#......#..#..................\n.................#.......................#.#........#......#...........................................#...#..........#...........\n..................#..................#...#.....................................#........#.........................................\n...#.....#.......#..............#.#....##.............#....##......................................#...................#..........\n...#..........................................................................................................................#...\n..#..#.............#.....#...............#.......#..............................................#....#............................\n......................#..#...............#...................#....#..........................#...#............#...#....##.........\n..#.#.........#................#............#............#.#.......#................#....#..#.....................................\n.......................................................................#.....................................#...........#........\n...........#.....................................................................#.................................#......#.......\n...#.........#....................................................#..............#.............#..........#.......................\n.................................................................................................#................................\n..................................#.#.#...#.......#.............#.......................#..#.......................#.#............\n.......................#.........................................#..........#...#.....#....................................#......\n.......#.......#.#...........#......................#.....#..#...#.#...............#.............................#...#............\n............##...#......#.........#......#............................................................#.........#..............#..\n..#........................................#........##..#...............................................................#.........\n...........#..............##................................................................................#.....................\n..#................................................................................#..............#...............................\n...................................##..............#..........................#.......#..#...............#........#...............\n....#............#.........................#................................................................#........#............\n............#.....................................................................#.............................................#.\n............#..........#.......#...........#.#......#..............#.........#.......................................#......#.....\n..#...............................................#..................................#.............................#.............#\n.........................................................................#........#................#......#.......#....#........#.\n.......................................................................#.....##.................................................#.\n..............#.............#...........................#...#..#....................................................#.............\n.......#..........................#.......................###..................................#.....................#..#.........\n................#.................#.............#......................................................................#........#.\n.#.....#................#......................................................................#................#.................\n................................#........................#........#..#........................#...................................\n..............................................................................................#.....................#.........#...\n..................#.................#.........................#.....#................#............................................\n......#...................#...#...................#..................#...........................#......###...................#...\n.............................##.....#..............#..............................................................#....#..........\n......#..................#....................................................###....................#..............#.............\n............#...#..................#........#.............#..............................#......Line truncated
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const mockInput = "....#.....\n.........#\n..........\n..#.......\n.......#..\n..........\n.#..^.....\n........#.\n#.........\n......#..."
|
||||||
|
|
||||||
|
type Direction uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
UP Direction = iota
|
||||||
|
RIGHT
|
||||||
|
DOWN
|
||||||
|
LEFT
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d Direction) Next() Direction {
|
||||||
|
return (d + 1) % 4
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Direction) NextPoint(p *Point) *Point {
|
||||||
|
if d == UP {
|
||||||
|
return &Point{p.x, p.y - 1}
|
||||||
|
}
|
||||||
|
if d == DOWN {
|
||||||
|
return &Point{p.x, p.y + 1}
|
||||||
|
}
|
||||||
|
if d == LEFT {
|
||||||
|
return &Point{p.x - 1, p.y}
|
||||||
|
}
|
||||||
|
return &Point{p.x + 1, p.y}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Point struct {
|
||||||
|
x, y int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Point) String() string {
|
||||||
|
return fmt.Sprintf("(%d, %d)", p.x, p.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Map struct {
|
||||||
|
data []rune
|
||||||
|
width int
|
||||||
|
height int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) isInbound(point *Point) bool {
|
||||||
|
return point.x >= 0 && point.x < m.width && point.y >= 0 && point.y < m.width
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) Get(point *Point) (rune, bool) {
|
||||||
|
if !m.isInbound(point) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
idx := point.x + m.width*point.y
|
||||||
|
return m.data[idx], true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) Set(point *Point, r rune) {
|
||||||
|
idx := point.x + m.width*point.y
|
||||||
|
m.data[idx] = r
|
||||||
|
}
|
||||||
|
|
||||||
|
type Guard struct {
|
||||||
|
position *Point
|
||||||
|
direction Direction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Guard) String() string {
|
||||||
|
return fmt.Sprintf("%s[%d]", g.position, g.direction)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindGuard(input string) *Guard {
|
||||||
|
m := NewMap(input)
|
||||||
|
input = strings.ReplaceAll(input, "\n", "")
|
||||||
|
rawIndex := strings.Index(input, "^")
|
||||||
|
|
||||||
|
x := rawIndex % m.width
|
||||||
|
y := rawIndex / m.width
|
||||||
|
return &Guard{&Point{x, y}, UP}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMap(input string) *Map {
|
||||||
|
if !strings.HasSuffix(input, "\n") {
|
||||||
|
input += "\n"
|
||||||
|
}
|
||||||
|
input = strings.ReplaceAll(input, "^", ".")
|
||||||
|
width := strings.Index(input, "\n")
|
||||||
|
height := strings.Count(input, "\n")
|
||||||
|
data := []rune(strings.ReplaceAll(input, "\n", ""))
|
||||||
|
return &Map{data, width, height}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isWall(v rune) bool {
|
||||||
|
return v == '#'
|
||||||
|
}
|
||||||
|
|
||||||
|
func nextGuard(m *Map, guard *Guard) (*Guard, bool) {
|
||||||
|
nextPosition := guard.direction.NextPoint(guard.position)
|
||||||
|
if v, ok := m.Get(nextPosition); !ok {
|
||||||
|
return nil, false
|
||||||
|
} else if isWall(v) {
|
||||||
|
return &Guard{guard.position, guard.direction.Next()}, true
|
||||||
|
} else {
|
||||||
|
return &Guard{nextPosition, guard.direction}, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WalkGuard(m *Map, guard *Guard) chan *Guard {
|
||||||
|
out := make(chan *Guard)
|
||||||
|
go func() {
|
||||||
|
for guard, ok := guard, true; ok; guard, ok = nextGuard(m, guard) {
|
||||||
|
out <- guard
|
||||||
|
}
|
||||||
|
close(out)
|
||||||
|
}()
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func UniquePoints(guards chan *Guard) chan *Guard {
|
||||||
|
out := make(chan *Guard)
|
||||||
|
m := make(map[int]map[int]bool)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for guard := range guards {
|
||||||
|
p := guard.position
|
||||||
|
if v, ok := m[p.x]; ok {
|
||||||
|
if _, ok2 := v[p.y]; ok2 {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
m[p.x][p.y] = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m[p.x] = make(map[int]bool)
|
||||||
|
m[p.x][p.y] = true
|
||||||
|
}
|
||||||
|
out <- guard
|
||||||
|
}
|
||||||
|
close(out)
|
||||||
|
}()
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func Question6A(input string) int {
|
||||||
|
m := NewMap(input)
|
||||||
|
guard := FindGuard(input)
|
||||||
|
i := 0
|
||||||
|
for _ = range UniquePoints(WalkGuard(m, guard)) {
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkIfGuardMakesALoop(m *Map, guard *Guard) <-chan bool {
|
||||||
|
out := make(chan bool)
|
||||||
|
go func() {
|
||||||
|
out <- isGuardMakingALoop(m, guard)
|
||||||
|
close(out)
|
||||||
|
}()
|
||||||
|
return out
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Question6B(input string) int {
|
||||||
|
m := NewMap(input)
|
||||||
|
guard := FindGuard(input)
|
||||||
|
chans := make([]<-chan bool, 0)
|
||||||
|
possibleWallPositions := Rest(GetPoints(UniquePoints(WalkGuard(m, guard))))
|
||||||
|
for point := range possibleWallPositions {
|
||||||
|
newMap := placeBlock(m, point)
|
||||||
|
chans = append(chans, checkIfGuardMakesALoop(newMap, guard))
|
||||||
|
}
|
||||||
|
|
||||||
|
sum := 0
|
||||||
|
for _, f := range chans {
|
||||||
|
if <-f {
|
||||||
|
sum++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum
|
||||||
|
}
|
||||||
|
|
||||||
|
func isGuardMakingALoop(m *Map, guard *Guard) bool {
|
||||||
|
visited := make(map[int]map[int]map[Direction]bool)
|
||||||
|
for guard := range WalkGuard(m, guard) {
|
||||||
|
if _, ok := visited[guard.position.x]; ok {
|
||||||
|
if _, ok2 := visited[guard.position.x][guard.position.y]; ok2 {
|
||||||
|
if _, ok3 := visited[guard.position.x][guard.position.y][guard.direction]; ok3 {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
visited[guard.position.x][guard.position.y][guard.direction] = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
visited[guard.position.x][guard.position.y] = make(map[Direction]bool)
|
||||||
|
visited[guard.position.x][guard.position.y][guard.direction] = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
visited[guard.position.x] = make(map[int]map[Direction]bool)
|
||||||
|
visited[guard.position.x][guard.position.y] = make(map[Direction]bool)
|
||||||
|
visited[guard.position.x][guard.position.y][guard.direction] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func placeBlock(m *Map, point *Point) *Map {
|
||||||
|
data := make([]rune, len(m.data))
|
||||||
|
copy(data, m.data)
|
||||||
|
ret := &Map{data, m.width, m.height}
|
||||||
|
ret.Set(point, rune('#'))
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func Rest(points <-chan *Point) <-chan *Point {
|
||||||
|
out := make(chan *Point)
|
||||||
|
go func() {
|
||||||
|
first := true
|
||||||
|
for p := range points {
|
||||||
|
if first {
|
||||||
|
first = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out <- p
|
||||||
|
}
|
||||||
|
close(out)
|
||||||
|
}()
|
||||||
|
return out
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPoints(guards <-chan *Guard) <-chan *Point {
|
||||||
|
out := make(chan *Point)
|
||||||
|
go func() {
|
||||||
|
for guard := range guards {
|
||||||
|
out <- guard.position
|
||||||
|
}
|
||||||
|
close(out)
|
||||||
|
}()
|
||||||
|
return out
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
//answer6A := Question6A(realInput)
|
||||||
|
//fmt.Printf("The answer to question 6A is %d\n", answer6A)
|
||||||
|
|
||||||
|
answer6B := Question6B(realInput)
|
||||||
|
fmt.Printf("The answer to question 6A is %d\n", answer6B)
|
||||||
|
}
|
||||||
Reference in new issue
Block a user