adventofcode/2016/day08/main.go

209 lines
3.5 KiB
Go

package main
import (
"bufio"
"errors"
"fmt"
"log"
"os"
"strconv"
"strings"
"time"
)
func main() {
width := 50
height := 6
if len(os.Args) >= 2 {
width = atoi(os.Args[1])
}
if len(os.Args) >= 3 {
height = atoi(os.Args[2])
}
input := stdinToStringSlice()
d := CreateDisplay(width, height)
for idx, ins := range input {
fmt.Println(idx, ins)
d.ClearScreen()
d.ProcInstruction(ins)
d.PrintScreen()
time.Sleep(time.Millisecond * 25)
}
fmt.Println("Voltage Used: ", d.GetVoltage())
}
type Display struct {
Width int
Height int
Screen [][]bool
}
func CreateDisplay(w, h int) *Display {
d := Display{Width: w, Height: h}
for i := 0; i < h; i++ {
var row []bool
for j := 0; j < w; j++ {
row = append(row, false)
}
d.Screen = append(d.Screen, row)
}
return &d
}
func (d *Display) ClearScreen() {
fmt.Print("\033[H\033[2J")
}
func (d *Display) PrintScreen() {
fmt.Print("\u250C")
for i := 0; i < d.Width; i++ {
fmt.Print("\u2500")
}
fmt.Println("\u2510")
for y := range d.Screen {
fmt.Print("\u2502")
for x := range d.Screen[y] {
if d.Screen[y][x] {
fmt.Print("\u2588")
} else {
fmt.Print(" ")
}
}
fmt.Println("\u2502")
}
fmt.Print("\u2514")
for i := 0; i < d.Width; i++ {
fmt.Print("\u2500")
}
fmt.Println("\u2518")
}
func (d *Display) SetWidth(w int) {
d.Width = w
}
func (d *Display) SetHeight(h int) {
d.Height = h
}
func (d *Display) ProcInstruction(ins string) {
pts := strings.Fields(ins)
switch pts[0] {
case "rect":
if len(pts) < 2 {
return
}
dim := strings.Split(pts[1], "x")
bldX := atoi(dim[0])
bldY := atoi(dim[1])
d.CreateRect(bldX, bldY)
case "rotate":
if len(pts) < 5 {
return
}
args := strings.Split(pts[2], "=")
switch pts[1] {
case "row":
if args[0] != "y" {
return
}
d.RotateRow(atoi(args[1]), atoi(pts[4]))
case "column":
if args[0] != "x" {
return
}
d.RotateCol(atoi(args[1]), atoi(pts[4]))
}
}
}
func (d *Display) CreateRect(x, y int) {
if y >= d.Height && x >= d.Width {
fmt.Println(" Error creating rect", x, y)
return
}
for i := 0; i < y; i++ {
for j := 0; j < x; j++ {
d.Screen[i][j] = true
}
}
}
func (d *Display) RotateRow(y, dist int) {
orig, err := d.GetRow(y)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
return
}
for i := range orig {
d.Screen[y][(i+dist)%d.Width] = orig[i]
}
}
func (d *Display) RotateCol(x, dist int) {
orig, err := d.GetCol(x)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
return
}
for i := range orig {
d.Screen[(i+dist)%d.Height][x] = orig[i]
}
}
func (d *Display) GetRow(y int) ([]bool, error) {
var ret []bool
if d.Height <= y {
return ret, errors.New("Invalid Row Requested")
}
for i := 0; i < d.Width; i++ {
ret = append(ret, d.Screen[y][i])
}
return ret, nil
}
func (d *Display) GetCol(x int) ([]bool, error) {
var ret []bool
if d.Width <= x {
return ret, errors.New("Invalid Column Requested")
}
for i := 0; i < d.Height; i++ {
ret = append(ret, d.Screen[i][x])
}
return ret, nil
}
func (d *Display) GetVoltage() int {
var ret int
for i := range d.Screen {
for j := range d.Screen[i] {
if d.Screen[i][j] {
ret++
}
}
}
return ret
}
func stdinToStringSlice() []string {
var input []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input = append(input, scanner.Text())
}
return input
}
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
}