Files
advent-of-code-go/2022/day10/main.go
T
alexchao26 6bef9a0721 8 9 10 11
2022-12-12 00:22:00 -05:00

168 lines
3.2 KiB
Go

package main
import (
_ "embed"
"flag"
"fmt"
"strings"
"github.com/alexchao26/advent-of-code-go/cast"
"github.com/alexchao26/advent-of-code-go/util"
)
//go:embed input.txt
var input string
func init() {
// do this in init (not main) so test file has same input
input = strings.TrimRight(input, "\n")
if len(input) == 0 {
panic("empty input.txt file")
}
}
func main() {
var part int
flag.IntVar(&part, "part", 1, "part 1 or 2")
flag.Parse()
fmt.Println("Running part", part)
if part == 1 {
ans := part1(input)
util.CopyToClipboard(fmt.Sprintf("%v", ans))
fmt.Println("Output:", ans)
} else {
ans := part2(input)
util.CopyToClipboard(fmt.Sprintf("%v", ans))
fmt.Println("Output:", ans)
}
}
func part1(input string) int {
instructions := parseInput(input)
X := 1
sum := 0
i := 0 // what the current instruction is
for cycle := 1; cycle <= 220; cycle++ {
// "during" equates to the start of the cycle...
if (cycle-20)%40 == 0 {
sum += X * cycle
}
switch instructions[i].name {
case "addx":
// decrement cycles on that instruction
// IF it hits zero add V
// AND move to next step
instructions[i].cycles--
if instructions[i].cycles == 0 {
X += instructions[i].val
i++
}
case "noop":
// just increment to next instruction
i++
}
}
return sum
}
func part2(input string) string {
instructions := parseInput(input)
X := 1 // doubles as sprite's center coordinate
// 6 rows by 40 wide screen, starts all off
CRT := [6][40]string{}
for i, rows := range CRT {
for j := range rows {
CRT[i][j] = "."
}
}
i := 0 // what the current instruction is
for cycle := 1; i < len(instructions); cycle++ {
// if (cycle-20)%40 == 0 {
// sum += X * cycle
// }
/*
X = horizontal position of middle of (3 pixel wide) sprite
axis draws left to right, top to bottom, 40 wide x 6 high
1---40
41---80
...
201---240
draws 1 pixel per cycle
light up pixels IF the pixel being drawn is the same as one of the sprite's 3 pixels
*/
// calculate which pixel is being drawn... ZERO INDEXED
pixelRow := (cycle - 1) / 40
pixelCol := (cycle - 1) % 40
// see if the spite's horizontal location overlaps that pixelCol
spriteLeft, spriteRight := X-1, X+1
if spriteLeft <= pixelCol && spriteRight >= pixelCol {
CRT[pixelRow][pixelCol] = "#"
}
switch instructions[i].name {
case "addx":
// decrement cycles on that instruction
// IF it hits zero add V
// AND move to next step
instructions[i].cycles--
if instructions[i].cycles == 0 {
X += instructions[i].val
i++
}
case "noop":
// just increment to next instruction
i++
}
}
log := ""
for _, rows := range CRT {
for _, cell := range rows {
log += cell
}
log += "\n"
}
fmt.Println(log)
return log
}
type instruction struct {
name string
val int
cycles int
}
func parseInput(input string) (ans []instruction) {
for _, l := range strings.Split(input, "\n") {
switch l[:4] {
case "addx":
ans = append(ans, instruction{
name: "addx",
val: cast.ToInt(l[5:]),
cycles: 2,
})
case "noop":
ans = append(ans, instruction{
name: "noop",
cycles: 1,
})
default:
panic("input line: " + l)
}
}
return ans
}