212 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package main
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"os/exec"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| var lights [][]bool
 | |
| 
 | |
| func main() {
 | |
| 	ticks := -1
 | |
| 	speed := 2
 | |
| 	var hideSim, lockedCorners bool
 | |
| 	for i := range os.Args {
 | |
| 		if os.Args[i] == "-help" {
 | |
| 			fmt.Println("Usage: day18 [-ticks=<num>] [-speed=<num>]")
 | |
| 			fmt.Println("\t-ticks=<num>\tSpecify how many iterations should be performed")
 | |
| 			fmt.Println("\t\t\t\tIf not manually set, run forever.")
 | |
| 			fmt.Println("\t-speed=<num>\tSpecify how many times/second we iterate")
 | |
| 			fmt.Println("\t-hide\t\tHide the actual simulation (for AoC)")
 | |
| 			fmt.Println("\t-lockcorners\t\tLock the corner lights 'on' (for AoC pt 2)")
 | |
| 			os.Exit(1)
 | |
| 		}
 | |
| 		if j := strings.Index(os.Args[i], "="); j > 0 {
 | |
| 			flagKey := os.Args[i][:j]
 | |
| 			flagVal := os.Args[i][j+1:]
 | |
| 			if flagKey == "-ticks" {
 | |
| 				ticks = mustAtoi(flagVal)
 | |
| 			} else if flagKey == "-speed" {
 | |
| 				speed = mustAtoi(flagVal)
 | |
| 			}
 | |
| 		}
 | |
| 		if os.Args[i] == "-hide" {
 | |
| 			hideSim = true
 | |
| 		}
 | |
| 		if os.Args[i] == "-lockcorners" {
 | |
| 			lockedCorners = true
 | |
| 		}
 | |
| 	}
 | |
| 	if hideSim && ticks == -1 {
 | |
| 		// Doesn't make sense to run this configuration
 | |
| 		fmt.Println("You asked to run indefinitely and hide the simulation...")
 | |
| 		fmt.Println("Refusing to needlessly consume your CPU.")
 | |
| 		os.Exit(1)
 | |
| 	}
 | |
| 
 | |
| 	var input []string
 | |
| 	scanner := bufio.NewScanner(os.Stdin)
 | |
| 	for scanner.Scan() {
 | |
| 		input = append(input, scanner.Text())
 | |
| 	}
 | |
| 
 | |
| 	for i := range input {
 | |
| 		var bldRow []bool
 | |
| 		for j := range input[i] {
 | |
| 			bldRow = append(bldRow, (input[i][j] == '#'))
 | |
| 		}
 | |
| 		lights = append(lights, bldRow)
 | |
| 	}
 | |
| 
 | |
| 	if !hideSim {
 | |
| 		cls()
 | |
| 		printLights(lights)
 | |
| 	}
 | |
| 	for i := 0; i < ticks || ticks == -1; i++ {
 | |
| 		if lockedCorners {
 | |
| 			lights = lockCorners(lights)
 | |
| 		}
 | |
| 		lights = tick(lights)
 | |
| 		if lockedCorners {
 | |
| 			lights = lockCorners(lights)
 | |
| 		}
 | |
| 		if !hideSim {
 | |
| 			cls()
 | |
| 			printLights(lights)
 | |
| 		}
 | |
| 		if !hideSim {
 | |
| 			// No reason to sleep if we're hiding the simulation
 | |
| 			time.Sleep(time.Second / time.Duration(speed))
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	fmt.Println("After " + strconv.Itoa(ticks) + " ticks, " + strconv.Itoa(countLights(lights)) + " are on")
 | |
| }
 | |
| 
 | |
| func lockCorners(c [][]bool) [][]bool {
 | |
| 	c[0][0] = true
 | |
| 	c[0][len(c[0])-1] = true
 | |
| 	c[len(c)-1][0] = true
 | |
| 	c[len(c)-1][len(c[0])-1] = true
 | |
| 	return c
 | |
| }
 | |
| 
 | |
| func cls() {
 | |
| 	cmd := exec.Command("clear")
 | |
| 	cmd.Stdout = os.Stdout
 | |
| 	cmd.Run()
 | |
| }
 | |
| 
 | |
| func printLights(curr [][]bool) {
 | |
| 	for i := range curr {
 | |
| 		for j := range curr {
 | |
| 			if curr[i][j] {
 | |
| 				fmt.Print("#")
 | |
| 			} else {
 | |
| 				fmt.Print(".")
 | |
| 			}
 | |
| 		}
 | |
| 		fmt.Println()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func tick(curr [][]bool) [][]bool {
 | |
| 	var next [][]bool
 | |
| 	for i := range curr {
 | |
| 		var bldRow []bool
 | |
| 		for j := range curr[i] {
 | |
| 			num := checkNeighbors(curr, i, j)
 | |
| 			var newVal bool
 | |
| 			if curr[i][j] {
 | |
| 				// On proc
 | |
| 				if num == 2 || num == 3 {
 | |
| 					newVal = true
 | |
| 				}
 | |
| 			} else {
 | |
| 				// Off proc
 | |
| 				if num == 3 {
 | |
| 					newVal = true
 | |
| 				}
 | |
| 			}
 | |
| 			bldRow = append(bldRow, newVal)
 | |
| 		}
 | |
| 		next = append(next, bldRow)
 | |
| 	}
 | |
| 	return next
 | |
| }
 | |
| 
 | |
| // Returns how many neighbors are on
 | |
| func checkNeighbors(curr [][]bool, i, j int) int {
 | |
| 	var ret int
 | |
| 	// nw
 | |
| 	if isOn(curr, (i - 1), (j - 1)) {
 | |
| 		ret++
 | |
| 	}
 | |
| 	// n
 | |
| 	if isOn(curr, (i - 1), j) {
 | |
| 		ret++
 | |
| 	}
 | |
| 	// ne
 | |
| 	if isOn(curr, (i - 1), (j + 1)) {
 | |
| 		ret++
 | |
| 	}
 | |
| 	// w
 | |
| 	if isOn(curr, i, (j - 1)) {
 | |
| 		ret++
 | |
| 	}
 | |
| 	// e
 | |
| 	if isOn(curr, i, (j + 1)) {
 | |
| 		ret++
 | |
| 	}
 | |
| 	// sw
 | |
| 	if isOn(curr, (i + 1), (j - 1)) {
 | |
| 		ret++
 | |
| 	}
 | |
| 	// s
 | |
| 	if isOn(curr, (i + 1), j) {
 | |
| 		ret++
 | |
| 	}
 | |
| 	// se
 | |
| 	if isOn(curr, (i + 1), (j + 1)) {
 | |
| 		ret++
 | |
| 	}
 | |
| 	return ret
 | |
| }
 | |
| 
 | |
| func isOn(curr [][]bool, i, j int) bool {
 | |
| 	if i < 0 || i >= len(curr) {
 | |
| 		return false
 | |
| 	}
 | |
| 	if j < 0 || j >= len(curr[i]) {
 | |
| 		return false
 | |
| 	}
 | |
| 	return curr[i][j]
 | |
| }
 | |
| 
 | |
| func countLights(c [][]bool) int {
 | |
| 	var ttl int
 | |
| 	for i := range c {
 | |
| 		for j := range c[i] {
 | |
| 			if c[i][j] {
 | |
| 				ttl++
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return ttl
 | |
| }
 | |
| 
 | |
| func mustAtoi(s string) int {
 | |
| 	var i int
 | |
| 	var err error
 | |
| 	if i, err = strconv.Atoi(s); err != nil {
 | |
| 		fmt.Println("Tried to atoi " + s)
 | |
| 		os.Exit(1)
 | |
| 	}
 | |
| 	return i
 | |
| }
 |