mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-06-07 12:45:10 +02:00
2016-day22: really manual solve but wrote some non-generalized code version of it too
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/alexchao26/advent-of-code-go/mathutil"
|
||||
"github.com/alexchao26/advent-of-code-go/util"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var part int
|
||||
flag.IntVar(&part, "part", 1, "part 1 or 2")
|
||||
flag.Parse()
|
||||
fmt.Println("Running part", part)
|
||||
|
||||
var ans int
|
||||
if part == 1 {
|
||||
ans = part1(util.ReadFile("./input.txt"))
|
||||
} else {
|
||||
ans = part2(util.ReadFile("./input.txt"))
|
||||
}
|
||||
fmt.Println("Output:", ans)
|
||||
}
|
||||
|
||||
func part1(input string) int {
|
||||
nodes := parseInput(input)
|
||||
|
||||
var viable int
|
||||
for i1, n1 := range nodes {
|
||||
for i2, n2 := range nodes {
|
||||
if i1 == i2 || n1.used == 0 {
|
||||
continue
|
||||
}
|
||||
if n2.avail >= n1.used {
|
||||
viable++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return viable
|
||||
}
|
||||
|
||||
// NOTE: this is not a generalized solution, this was done after solving it somewhat
|
||||
// manually by printing the entire grid and getting to the top right corner
|
||||
// there was a blocking row that had really large memory usage, these had to be routed around
|
||||
// then swapping the top right tile each step to the left, required 5 steps
|
||||
// 4 to get in front of it and 1 to do the actual swap
|
||||
func part2(input string) int {
|
||||
nodes := parseInput(input)
|
||||
|
||||
var maxX, maxY int
|
||||
var x, y int
|
||||
for c, n := range nodes {
|
||||
maxX = mathutil.MaxInt(c[0], maxX)
|
||||
maxY = mathutil.MaxInt(c[1], maxY)
|
||||
// getting the starting node, i.e. has zero used space
|
||||
if n.used == 0 {
|
||||
x = n.coord[1]
|
||||
y = n.coord[0]
|
||||
}
|
||||
}
|
||||
|
||||
// // uncomment to print a useable grid
|
||||
// grid := make([][]*node, maxY+1)
|
||||
// for i := range grid {
|
||||
// grid[i] = make([]*node, maxX+1)
|
||||
// }
|
||||
// for c, n := range nodes {
|
||||
// grid[c[1]][c[0]] = n
|
||||
// }
|
||||
// for _, line := range grid {
|
||||
// for _, n := range line {
|
||||
// fmt.Print(n)
|
||||
// }
|
||||
// fmt.Println()
|
||||
// }
|
||||
|
||||
var stepsTaken int
|
||||
// get to the cell that's needed
|
||||
for !(x == maxX && y == 0) {
|
||||
if y > 0 {
|
||||
if nodes[[2]int{x, y - 1}].used < 100 { // realizing that x/y are "flipped"..
|
||||
// grid[y-1][x].used < 100 {
|
||||
y--
|
||||
} else {
|
||||
// go left to get around the "blocking" chips who's used size
|
||||
// is so large that it cannot be copied into the zero chip
|
||||
x--
|
||||
}
|
||||
} else if y == 0 {
|
||||
x++
|
||||
}
|
||||
stepsTaken++
|
||||
}
|
||||
// decrement x because we shifted into it already
|
||||
x--
|
||||
|
||||
// then you need five steps to move the target cell to the left by one cell
|
||||
for x != 0 {
|
||||
stepsTaken += 5
|
||||
x--
|
||||
}
|
||||
|
||||
return stepsTaken
|
||||
}
|
||||
|
||||
type node struct {
|
||||
coord [2]int
|
||||
size int
|
||||
used int
|
||||
avail int
|
||||
}
|
||||
|
||||
func (n node) String() string {
|
||||
// str := fmt.Sprintf("%v: %d used of %d, %d avail", n.coord, n.used, n.size, n.avail)
|
||||
str := fmt.Sprintf("| %d/%d ", n.used, n.size)
|
||||
for len(str) < 10 {
|
||||
str += " "
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
func parseInput(input string) map[[2]int]*node {
|
||||
allNodes := map[[2]int]*node{}
|
||||
|
||||
spaces := regexp.MustCompile("[ ]{2,}")
|
||||
for _, line := range strings.Split(input, "\n")[2:] {
|
||||
str := spaces.ReplaceAllString(line, " ")
|
||||
var percentage int
|
||||
n := node{}
|
||||
fmt.Sscanf(str, "/dev/grid/node-x%d-y%d %dT %dT %dT %d%",
|
||||
&n.coord[0], &n.coord[1], &n.size, &n.used, &n.avail, &percentage)
|
||||
allNodes[n.coord] = &n
|
||||
}
|
||||
|
||||
return allNodes
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alexchao26/advent-of-code-go/util"
|
||||
)
|
||||
|
||||
func Test_part1(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want int
|
||||
}{
|
||||
{"actual", util.ReadFile("input.txt"), 946},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := part1(tt.input); got != tt.want {
|
||||
t.Errorf("part1() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_part2(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want int
|
||||
}{
|
||||
{"actual", util.ReadFile("input.txt"), 195},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := part2(tt.input); got != tt.want {
|
||||
t.Errorf("part2() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user