Combine AoC Repos
This commit is contained in:
341
2016/day13/main.go
Normal file
341
2016/day13/main.go
Normal file
@@ -0,0 +1,341 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
termbox "github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
var tWidth, tHeight int
|
||||
|
||||
// Puzzle 1 Input: 1364 31 39
|
||||
// Puzzle 1 Test Input: 10 7 4
|
||||
func main() {
|
||||
mode := "solve"
|
||||
if len(os.Args) < 4 {
|
||||
fmt.Println("Usage: day13 <seed> <dest-x> <dest-y>")
|
||||
os.Exit(1)
|
||||
}
|
||||
seed := atoi(os.Args[1])
|
||||
destX, destY := atoi(os.Args[2]), atoi(os.Args[3])
|
||||
if len(os.Args) >= 5 {
|
||||
mode = os.Args[4]
|
||||
}
|
||||
f := CreateFloor(1, 1, destX, destY, seed)
|
||||
|
||||
if err := termbox.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tWidth, tHeight = termbox.Size()
|
||||
termbox.Close()
|
||||
switch mode {
|
||||
case "solve":
|
||||
if f.Solve(f.start.x, f.start.y, 0, true) {
|
||||
f.dispCoord = f.end
|
||||
}
|
||||
ClearScreen()
|
||||
f.Print()
|
||||
fmt.Println("Shortest Path:", len(f.solvePath.coords))
|
||||
case "walk":
|
||||
dist := 50
|
||||
f.Walk(f.start.x, f.start.y, 0, dist, true)
|
||||
fmt.Println("Within", dist, "steps: ", len(f.testedPath.coords))
|
||||
}
|
||||
}
|
||||
|
||||
type Coord struct {
|
||||
x, y, dist int
|
||||
}
|
||||
|
||||
func (c *Coord) Is(x, y int) bool {
|
||||
return c.x == x && c.y == y
|
||||
}
|
||||
|
||||
func (c *Coord) Equals(t *Coord) bool {
|
||||
return c.x == t.x && c.y == t.y
|
||||
}
|
||||
|
||||
func NewCoord(x, y int) *Coord {
|
||||
return &Coord{x, y, -1}
|
||||
}
|
||||
|
||||
type Path struct {
|
||||
coords []Coord
|
||||
}
|
||||
|
||||
func (p *Path) Append(c Coord) {
|
||||
p.coords = append(p.coords, c)
|
||||
}
|
||||
|
||||
func (p *Path) ContainsCoord(x, y int) bool {
|
||||
for i := range p.coords {
|
||||
if p.coords[i].Is(x, y) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Path) GetCoordAt(x, y int) *Coord {
|
||||
for i := range p.coords {
|
||||
if p.coords[i].Is(x, y) {
|
||||
return &p.coords[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Floor struct {
|
||||
start *Coord
|
||||
end *Coord
|
||||
seed int
|
||||
testedPath Path
|
||||
solvePath Path
|
||||
dispCoord *Coord
|
||||
}
|
||||
|
||||
func CreateFloor(stX, stY, endX, endY, seed int) *Floor {
|
||||
f := Floor{
|
||||
start: NewCoord(stX, stY),
|
||||
end: NewCoord(endX, endY),
|
||||
seed: seed,
|
||||
}
|
||||
return &f
|
||||
}
|
||||
|
||||
func (f *Floor) Walk(x, y, dist, maxDist int, print bool) {
|
||||
wrkCoord := Coord{x, y, dist}
|
||||
if f.IsWall(x, y) || f.testedPath.ContainsCoord(x, y) {
|
||||
return
|
||||
}
|
||||
if dist == maxDist {
|
||||
f.testedPath.Append(wrkCoord)
|
||||
return
|
||||
}
|
||||
if print {
|
||||
f.dispCoord = &wrkCoord
|
||||
ClearScreen()
|
||||
f.Print()
|
||||
fmt.Println("Tested Spots:", len(f.testedPath.coords))
|
||||
time.Sleep(time.Millisecond * 70)
|
||||
}
|
||||
if !f.IsWall(x-1, y) {
|
||||
if t := f.testedPath.GetCoordAt(x-1, y); t != nil {
|
||||
if t.dist+1 < wrkCoord.dist {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if !f.IsWall(x+1, y) {
|
||||
if t := f.testedPath.GetCoordAt(x+1, y); t != nil {
|
||||
if t.dist+1 < wrkCoord.dist {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if !f.IsWall(x, y-1) {
|
||||
if t := f.testedPath.GetCoordAt(x, y-1); t != nil {
|
||||
if t.dist+1 < wrkCoord.dist {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if !f.IsWall(x, y+1) {
|
||||
if t := f.testedPath.GetCoordAt(x, y+1); t != nil {
|
||||
if t.dist+1 < wrkCoord.dist {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
f.testedPath.Append(wrkCoord)
|
||||
// Try intelligently first
|
||||
// (Attempt to move towards the exit)
|
||||
if x > 0 {
|
||||
f.Walk(x-1, y, wrkCoord.dist+1, maxDist, print)
|
||||
}
|
||||
if y > 0 {
|
||||
f.Walk(x, y-1, wrkCoord.dist+1, maxDist, print)
|
||||
}
|
||||
f.Walk(x+1, y, wrkCoord.dist+1, maxDist, print)
|
||||
f.Walk(x, y+1, wrkCoord.dist+1, maxDist, print)
|
||||
}
|
||||
|
||||
func (f *Floor) Solve(x, y, dist int, print bool) bool {
|
||||
wrkCoord := Coord{x, y, dist}
|
||||
if f.end.Is(x, y) {
|
||||
return true
|
||||
}
|
||||
if f.IsWall(x, y) || f.testedPath.ContainsCoord(x, y) {
|
||||
return false
|
||||
}
|
||||
// Test if there is a shorter path to this coordinate
|
||||
if !f.IsWall(x-1, y) {
|
||||
if t := f.testedPath.GetCoordAt(x-1, y); t != nil {
|
||||
if t.dist+1 < wrkCoord.dist {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !f.IsWall(x+1, y) {
|
||||
if t := f.testedPath.GetCoordAt(x+1, y); t != nil {
|
||||
if t.dist+1 < wrkCoord.dist {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !f.IsWall(x, y-1) {
|
||||
if t := f.testedPath.GetCoordAt(x, y-1); t != nil {
|
||||
if t.dist+1 < wrkCoord.dist {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !f.IsWall(x, y+1) {
|
||||
if t := f.testedPath.GetCoordAt(x, y+1); t != nil {
|
||||
if t.dist+1 < wrkCoord.dist {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if print {
|
||||
f.dispCoord = &wrkCoord
|
||||
ClearScreen()
|
||||
f.Print()
|
||||
fmt.Println("Tested Spots:", len(f.testedPath.coords))
|
||||
time.Sleep(time.Millisecond * 70)
|
||||
}
|
||||
f.testedPath.Append(wrkCoord)
|
||||
// Try intelligently first
|
||||
// (Attempt to move towards the exit)
|
||||
if x > f.end.x && x > 0 {
|
||||
if f.Solve(x-1, y, wrkCoord.dist+1, print) {
|
||||
f.solvePath.Append(wrkCoord)
|
||||
return true
|
||||
}
|
||||
}
|
||||
if y > f.end.y && y > 0 {
|
||||
if f.Solve(x, y-1, wrkCoord.dist+1, print) {
|
||||
f.solvePath.Append(wrkCoord)
|
||||
return true
|
||||
}
|
||||
}
|
||||
if x < f.end.x {
|
||||
if f.Solve(x+1, y, wrkCoord.dist+1, print) {
|
||||
f.solvePath.Append(wrkCoord)
|
||||
return true
|
||||
}
|
||||
}
|
||||
if y < f.end.y {
|
||||
if f.Solve(x, y+1, wrkCoord.dist+1, print) {
|
||||
f.solvePath.Append(wrkCoord)
|
||||
return true
|
||||
}
|
||||
}
|
||||
// Intelligence failed us... Just find a move
|
||||
if x > 0 {
|
||||
if f.Solve(x-1, y, wrkCoord.dist+1, print) {
|
||||
f.solvePath.Append(wrkCoord)
|
||||
return true
|
||||
}
|
||||
}
|
||||
if y > 0 {
|
||||
if f.Solve(x, y-1, wrkCoord.dist+1, print) {
|
||||
f.solvePath.Append(wrkCoord)
|
||||
return true
|
||||
}
|
||||
}
|
||||
// This is where it gets shaky...
|
||||
// Since we have an infinite maze, this could run forever
|
||||
// So we have a hard cutoff at:
|
||||
var MaxInt = int(^uint(0) >> 1)
|
||||
if len(f.testedPath.coords) >= MaxInt {
|
||||
fmt.Println("ERROR: Couldn't find a path.")
|
||||
os.Exit(1)
|
||||
}
|
||||
if f.Solve(x+1, y, wrkCoord.dist+1, print) {
|
||||
f.solvePath.Append(wrkCoord)
|
||||
return true
|
||||
}
|
||||
if f.Solve(x, y+1, wrkCoord.dist+1, print) {
|
||||
f.solvePath.Append(wrkCoord)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *Floor) IsWall(x, y int) bool {
|
||||
sum := (x*x + 3*x + 2*x*y + y + y*y + f.seed)
|
||||
s := fmt.Sprintf("%b", sum)
|
||||
if strings.Count(s, "1")%2 == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (f *Floor) Print() {
|
||||
wall := color.New(color.BgWhite)
|
||||
space := color.New(color.FgWhite)
|
||||
g := color.New(color.BgGreen).Add(color.FgBlack)
|
||||
g.Add(color.Bold)
|
||||
r := color.New(color.BgRed)
|
||||
b := color.New(color.BgBlue).Add(color.BgBlack)
|
||||
b.Add(color.Bold)
|
||||
topY, topX := tHeight, tWidth
|
||||
botY, botX := 0, 0
|
||||
// We want to center approx 20x20 on our current location
|
||||
// f.testedPath[len(f.testedPath)-1]?
|
||||
if len(f.testedPath.coords) > 0 {
|
||||
cntrCoord := f.testedPath.coords[len(f.testedPath.coords)-1]
|
||||
if topY < cntrCoord.y+(tHeight/2) {
|
||||
topY = cntrCoord.y + (tHeight / 2)
|
||||
}
|
||||
if topY > tHeight {
|
||||
botY = topY - tHeight
|
||||
}
|
||||
if topX < cntrCoord.x+(tWidth/2) {
|
||||
topX = cntrCoord.x + (tWidth / 2)
|
||||
}
|
||||
if topX > tWidth {
|
||||
botX = topX - tWidth
|
||||
}
|
||||
}
|
||||
for y := botY; y < topY; y++ {
|
||||
for x := botX; x < topX; x++ {
|
||||
if f.dispCoord != nil && f.dispCoord.Is(x, y) {
|
||||
g.Print("O")
|
||||
} else if f.solvePath.ContainsCoord(x, y) {
|
||||
g.Print(".")
|
||||
} else if f.testedPath.ContainsCoord(x, y) {
|
||||
r.Print(" ")
|
||||
} else {
|
||||
if f.end.Is(x, y) {
|
||||
b.Print("X")
|
||||
} else if f.IsWall(x, y) {
|
||||
wall.Print(" ")
|
||||
} else {
|
||||
space.Print(".")
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func ClearScreen() {
|
||||
fmt.Print("\033[H\033[2J")
|
||||
}
|
||||
|
||||
func atoi(i string) int {
|
||||
var ret int
|
||||
var err error
|
||||
if ret, err = strconv.Atoi(i); err != nil {
|
||||
log.Fatal("Invalid Atoi")
|
||||
}
|
||||
return ret
|
||||
}
|
77
2016/day13/problem
Normal file
77
2016/day13/problem
Normal file
@@ -0,0 +1,77 @@
|
||||
Advent of Code
|
||||
|
||||
--- Day 13: A Maze of Twisty Little Cubicles ---
|
||||
|
||||
You arrive at the first floor of this new building to discover a much less welcoming environment than the shiny atrium of the
|
||||
last one. Instead, you are in a maze of twisty little cubicles, all alike.
|
||||
|
||||
Every location in this area is addressed by a pair of non-negative integers (x,y). Each such coordinate is either a wall or an
|
||||
open space. You can't move diagonally. The cube maze starts at 0,0 and seems to extend infinitely toward positive x and y;
|
||||
negative values are invalid, as they represent a location outside the building. You are in a small waiting area at 1,1.
|
||||
|
||||
While it seems chaotic, a nearby morale-boosting poster explains, the layout is actually quite logical. You can determine
|
||||
whether a given x,y coordinate will be a wall or an open space using a simple system:
|
||||
|
||||
• Find x*x + 3*x + 2*x*y + y + y*y.
|
||||
• Add the office designer's favorite number (your puzzle input).
|
||||
• Find the binary representation of that sum; count the number of bits that are 1.
|
||||
|
||||
• If the number of bits that are 1 is even, it's an open space.
|
||||
• If the number of bits that are 1 is odd, it's a wall.
|
||||
|
||||
For example, if the office designer's favorite number were 10, drawing walls as # and open spaces as ., the corner of the
|
||||
building containing 0,0 would look like this:
|
||||
|
||||
0123456789
|
||||
0 .#.####.##
|
||||
1 ..#..#...#
|
||||
2 #....##...
|
||||
3 ###.#.###.
|
||||
4 .##..#..#.
|
||||
5 ..##....#.
|
||||
6 #...##.###
|
||||
|
||||
Now, suppose you wanted to reach 7,4. The shortest route you could take is marked as O:
|
||||
|
||||
0123456789
|
||||
0 .#.####.##
|
||||
1 .O#..#...#
|
||||
2 #OOO.##...
|
||||
3 ###O#.###.
|
||||
4 .##OO#OO#.
|
||||
5 ..##OOO.#.
|
||||
6 #...##.###
|
||||
|
||||
Thus, reaching 7,4 would take a minimum of 11 steps (starting from your current location, 1,1).
|
||||
|
||||
What is the fewest number of steps required for you to reach 31,39?
|
||||
|
||||
Your puzzle answer was _____.
|
||||
|
||||
The first half of this puzzle is complete! It provides one gold star: *
|
||||
|
||||
--- Part Two ---
|
||||
|
||||
How many locations (distinct x,y coordinates, including your starting location) can you reach in at most 50 steps?
|
||||
|
||||
Your puzzle input is still 1364.
|
||||
|
||||
Answer: _____________________
|
||||
|
||||
References
|
||||
|
||||
Visible links
|
||||
. http://adventofcode.com/
|
||||
. http://adventofcode.com/2016/about
|
||||
. http://adventofcode.com/2016/support
|
||||
. http://adventofcode.com/2016/events
|
||||
. http://adventofcode.com/2016/settings
|
||||
. http://adventofcode.com/2016/auth/logout
|
||||
. http://adventofcode.com/2016
|
||||
. http://adventofcode.com/2016
|
||||
. http://adventofcode.com/2016/leaderboard
|
||||
. http://adventofcode.com/2016/stats
|
||||
. http://adventofcode.com/2016/sponsors
|
||||
. http://adventofcode.com/2016/sponsors
|
||||
. https://en.wikipedia.org/wiki/Binary_number
|
||||
. https://en.wikipedia.org/wiki/Bit
|
Reference in New Issue
Block a user