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 @@
|
||||
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