question 6

This commit is contained in:
didier committed 2024-12-07 09:30:44 -05:00
1 parent 4039abe414
commit 780d9a52c7
4 files changed
+261

No files matched your search

+3
View File
@@ -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
+252
View File
@@ -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)
}