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 }