diff --git a/2017/day21/day21.go b/2017/day21/day21.go index 1c6c70b..4cbd12d 100644 --- a/2017/day21/day21.go +++ b/2017/day21/day21.go @@ -3,296 +3,108 @@ package main import ( "bufio" "fmt" - "log" "math" "os" "strings" - "time" ) -var allRules []Rule +var rules map[string]string func main() { + rules = make(map[string]string) + inp := StdinToStrings() for i := range inp { - allRules = append(allRules, Rule(inp[i])) + pts := strings.Split(inp[i], " ") + rules[pts[0]] = pts[2] + rules[Flip(pts[0])] = pts[2] + rules[Rotate(pts[0], 90)] = pts[2] + rules[Rotate(pts[0], 180)] = pts[2] + rules[Rotate(pts[0], 270)] = pts[2] } - //pattern := Pattern(".#./..#/###") - pattern := Pattern("../##") - fmt.Println(pattern) - if !pattern.IsValid() { - fmt.Println("Invalid Pattern Given. Must be square.") - } - ClearScreen() - pattern.PrettyPrint() - time.Sleep(time.Second) - for iters := 0; iters < 5; iters++ { - ClearScreen() - pattern = Tick(pattern) - pattern.PrettyPrint() - time.Sleep(time.Second) - } - fmt.Println("On:", pattern.GetOnCount()) -} -// Stitch takes a slice of patterns and turns them into one large (square) pattern -func Stitch(inp []Pattern) Pattern { - ppr := int(math.Sqrt(float64(len(inp)))) - newSize := ppr * inp[0].Size() - var currRow int - rows := make(map[int]string) - for i := 0; i < len(inp); i++ { - currRow = (i / ppr) * 2 - for j := 0; j < len(inp[0]); j++ { - if len(rows[currRow+j]) == newSize { - rows[currRow+j] += "/" - } - rows[currRow+j] += inp[i].GetRow(j) + pattern := ".#./..#/###" + for i := 0; i < 2; i++ { + Tick(pattern) + } + /* + pattern = rules[pattern] + pts := SplitBlocks(pattern) + for i := range pts { + pts[i] = rules[pts[i]] } - } - var lines []string - for i := 0; i < newSize; i++ { - lines = append(lines, rows[i]) - } - - return Pattern(strings.Join(lines, "/")) + fmt.Println(pts) + fmt.Println(CombineBlocks(pts)) + */ } -// Run the pattern, or all of it's subpatterns -// through the rules and return the new pattern -func Tick(inp Pattern) Pattern { - if inp.SubpatternCount() > 1 { - var subs []Pattern - // Tick each subpattern - for i := 0; i < inp.SubpatternCount(); i++ { - if s := inp.GetSubpattern(i); s.IsValid() { - subs = append(subs, Tick(s)) - } else { - log.Fatal("Error ticking pattern") - } +func Tick(pt string) string { + fmt.Println(SplitBlocks(pt)) + return "" +} + +func SplitBlocks(pt string) []string { + var ret []string + pts := strings.Split(pt, "/") + if len(pts[0]) <= 3 { + return []string{pt} + } + // Assume 3x3 + blkSize := 3 + if len(pts[0])%2 == 0 { + // 2x2 blocks + blkSize = 2 + } + for j := 0; j < len(pts); j += blkSize { + for i := 0; i < len(pts[j]); i += blkSize { + ret = append(ret, pts[j][i:i+blkSize]+"/"+pts[j+1][i:i+blkSize]) } - return Stitch(subs) - } - - var foundMatch bool - for i := range allRules { - if allRules[i].Matches(inp) { - inp = allRules[i].Output() - foundMatch = true - } - } - if !foundMatch { - fmt.Println("~ ERROR TICKING ~") - inp.PrettyPrint() - fmt.Println("~ ERROR TICKING ~") - os.Exit(1) - } - return inp -} - -/** - * A pattern is a string with some special methods - */ -type Pattern string - -// Print a pattern prettily. (in a square) -func (p Pattern) PrettyPrint() { - pts := strings.Split(string(p), "/") - for i := range pts { - fmt.Println(pts[i]) - } -} - -func (p Pattern) GetOnCount() int { - return strings.Count(string(p), "#") -} - -// Returns if a pattern is valid. -// A pattern is valid if it has more than 0 rows -// and every row is the same length as the number -// of columns -func (p Pattern) IsValid() bool { - pts := strings.Split(string(p), "/") - if len(pts) == 0 { - return false - } - for i := range pts { - if len(pts[i]) != len(pts) { - return false - } - } - return true -} - -// Returns the "size" of the pattern -// That is, how many rows/columns it has -func (p Pattern) Size() int { - return len(strings.Split(string(p), "/")) -} - -// Flip returns a new pattern that has been flipped horizontally -func (p Pattern) Flip() Pattern { - // We can only flip the smallest patterns (2x2 or 3x3) - if p.SubpatternCount() != 1 { - return p - } - pts := strings.Split(string(p), "/") - for i := range pts { - pts[i] = RevString(pts[i]) - } - return Pattern(strings.Join(pts, "/")) -} - -// Rotate returns a new pattern that has been rotated deg degrees -// Only right-angles -func (p Pattern) Rotate(deg int) Pattern { - // We can only rotate the smallest patterns (2x2 or 3x3) - if p.SubpatternCount() != 1 { - return p - } - - if deg < 0 { - deg += 360 - } else if deg == 0 { - return p - } - - pts := strings.Split(string(p), "/") - ret := make([]string, len(pts)) - use := p - switch deg { - case 90: - if p.Size()%3 == 0 { - ret[0] = RevString(use.GetCol(2)) - ret[1] = RevString(use.GetCol(1)) - ret[2] = RevString(use.GetCol(0)) - } else { - ret[0] = RevString(use.GetCol(1)) - ret[1] = RevString(use.GetCol(0)) - } - case 180: - if p.Size()%3 == 0 { - ret[0] = RevString(use.GetRow(2)) - ret[1] = RevString(use.GetRow(1)) - ret[2] = RevString(use.GetRow(0)) - } else { - ret[0] = RevString(use.GetRow(1)) - ret[1] = RevString(use.GetRow(0)) - } - case 270: - if p.Size()%3 == 0 { - ret[0] = use.GetCol(2) - ret[1] = use.GetCol(1) - ret[2] = use.GetCol(0) - } else { - ret[0] = use.GetCol(1) - ret[1] = use.GetCol(0) - } - - } - use = Pattern(strings.Join(ret, "/")) - return Pattern(strings.Join(ret, "/")) -} - -// GetRow returns a row as a string -func (p Pattern) GetRow(row int) string { - pts := strings.Split(string(p), "/") - if row >= len(pts) { - return "" - } - return pts[row] -} - -// GetCol returns a column as a string -func (p Pattern) GetCol(col int) string { - var ret string - pts := strings.Split(string(p), "/") - if col >= len(pts[0]) { - return "" - } - for i := 0; i < len(pts); i++ { - ret = ret + string(pts[i][col]) } return ret } -// Counts the number of subpatterns in the pattern -func (p Pattern) SubpatternCount() int { - if p.Size()%2 == 0 { - return (p.Size() / 2) * (p.Size() / 2) - } else { - return (p.Size() / 3) * (p.Size() / 3) +func CombineBlocks(pts []string) string { + var ret string + sz := int(math.Sqrt(float64(len(pts)))) + fmt.Println("Combining") + fmt.Println(sz) + //var j int + for i := 0; i < len(pts); i++ { } + return ret } -// Gets a specific subpattern out of the pattern -func (p Pattern) GetSubpattern(i int) Pattern { - if i > p.SubpatternCount() { - return Pattern("") +func Flip(pt string) string { + pts := strings.Split(pt, "/") + var newPts []string + for i := range pts { + newPts = append(newPts, RevString(pts[i])) } - subSize := 3 // Assume 3x3 subpatterns - if p.Size()%2 == 0 { - // Subpatterns are actually 2x2 - subSize = 2 + return strings.Join(newPts, "/") +} + +func Rotate(pt string, deg int) string { + if deg == 0 { + return pt } - ppr := p.Size() / subSize - col := i % (p.Size() / subSize) - row := i / ppr - ptString := "" - for j := 0; j < subSize; j++ { - ptString += p.GetRow((row * 2) + j)[(col*subSize):(col*subSize)+subSize] + "/" + if deg%90 != 0 { + // We can't do this + fmt.Println("Invalid Rotation:", deg) + os.Exit(1) } - return Pattern(ptString[:len(ptString)-1]) -} - -/** - * Rule is an interface that can take a pattern and return if it matches, - * report on it's size, or return the resulting pattern from applying itself - * to a pattern - */ -type RuleFace interface { - Matches(inp Pattern) bool - InputSize() int - Apply(inp Pattern) Pattern -} - -/** - * Rule implements the RuleFace interface - * for 2x2 => 3x3 transitions - * or 3x3 => 4x4 transitions - */ -type Rule string - -func (r Rule) Input() Pattern { - pts := strings.Split(string(r), " ") - return Pattern(pts[0]) -} - -func (r Rule) Output() Pattern { - pts := strings.Split(string(r), " ") - return Pattern(pts[2]) -} - -func (r Rule) Matches(inp Pattern) bool { - if inp.Size() != r.InputSize() { - return false + pts := strings.Split(pt, "/") + var tst string + if len(pts[0])%2 == 0 { + // 2x2 pattern + tst = string(pts[1][0]) + string(pts[0][0]) + "/" + tst += string(pts[1][1]) + string(pts[0][1]) + return Rotate(tst, deg-90) } - // Try it rotated 90,180,270 - for i := 0; i < 360; i += 90 { - if r.Equals(inp.Rotate(i)) || r.Equals(inp.Flip().Rotate(i)) { - return true - } - } - return false -} - -func (r Rule) InputSize() int { - return len(strings.Split(string(r.Input()), "/")) -} - -// Equals is a direct string comparison -func (r Rule) Equals(inp Pattern) bool { - return string(r.Input()) == string(inp) + // 3x3 pattern + tst = string(pts[2][0]) + string(pts[1][0]) + string(pts[0][0]) + "/" + tst += string(pts[2][1]) + string(pts[1][1]) + string(pts[0][1]) + "/" + tst += string(pts[2][2]) + string(pts[1][2]) + string(pts[0][2]) + return Rotate(tst, deg-90) } func RevString(s string) string { @@ -303,10 +115,6 @@ func RevString(s string) string { return string(runes) } -func ClearScreen() { - fmt.Println("\033[H\033[2J") -} - func StdinToStrings() []string { var input []string scanner := bufio.NewScanner(os.Stdin) diff --git a/2017/day23/.gitignore b/2017/day23/.gitignore new file mode 100644 index 0000000..523a316 --- /dev/null +++ b/2017/day23/.gitignore @@ -0,0 +1,3 @@ +day23-part2 +day23-part1 +test diff --git a/2017/day23/day23-part1.go b/2017/day23/day23-part1.go new file mode 100644 index 0000000..9f72fbe --- /dev/null +++ b/2017/day23/day23-part1.go @@ -0,0 +1,116 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +func main() { + inp := StdinToStrings() + run(inp) +} + +var reg map[string]int + +func run(inp []string) { + reg = make(map[string]int) + reg["a"] = 1 + var mulCount int + + var instCnt int + for i := 0; i >= 0 && i < len(inp); i++ { + instCnt++ + if instCnt%10 == 0 { + ClearScreen() + printInstructions(inp, i) + } + pts := strings.Split(inp[i], " ") + if pts[1] == "h" || pts[2] == "h" { + fmt.Println("Hit h") + } + switch pts[0] { + case "set": + setReg(pts[1], pts[2]) + case "sub": + subReg(pts[1], pts[2]) + case "mul": + mulCount++ + mulReg(pts[1], pts[2]) + case "jnz": + i += jumpNotZero(pts[1], pts[2]) + } + } + + fmt.Println("Result (H):", reg["h"]) +} + +func setReg(key string, val string) { + reg[key] = getValue(val) +} + +func subReg(key string, val string) { + reg[key] = getValue(key) - getValue(val) +} + +func mulReg(key string, val string) { + reg[key] = getValue(key) * getValue(val) +} + +func jumpNotZero(test string, jump string) int { + var ret int + if getValue(test) != 0 { + ret = getValue(jump) - 1 + } + return ret +} + +func getValue(key string) int { + var ret int + var ok bool + var err error + if ret, err = strconv.Atoi(key); err != nil { + // It's not a number + if ret, ok = reg[key]; !ok { + // The register is empty + reg[key] = 0 + ret = 0 + } + } + return ret +} + +func PrintRegisters() { + fmt.Print("[ ") + for i := 0; i < 26; i++ { + getReg := string('a' + i) + fmt.Printf("%s:%d ", getReg, getValue(getReg)) + } + fmt.Print("]\n") +} + +func printInstructions(inp []string, pos int) { + PrintRegisters() + for i := range inp { + if i == pos { + fmt.Print("> ", inp[i], "\n") + } else { + fmt.Print(" ", inp[i], "\n") + } + } +} + +func ClearScreen() { + fmt.Print("\033[H\033[2J") +} + +func StdinToStrings() []string { + var input []string + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + input = append(input, scanner.Text()) + } + return input +} diff --git a/2017/day23/day23-part2.go b/2017/day23/day23-part2.go new file mode 100644 index 0000000..88e0600 --- /dev/null +++ b/2017/day23/day23-part2.go @@ -0,0 +1,54 @@ +package main + +import ( + "fmt" + "math" +) + +func main() { + var a, b, c, d, e, f, g, h int + // Suppress go warnings + _, _, _, _, _, _, _, _ = a, b, c, d, e, f, g, h + // Derived from test.go + b = 109900 + c = 126900 + + // Unoptimized: + /* + for ; b < c+1; b += 17 { + f = 1 + for d = 2; d < b+1; d++ { + for e = 2; e < b+1; e++ { + if d*e == b { + f = 0 + } + } + } + // When is f 0? + // when d*e == b for "certain values" of b + fmt.Println(d, e, b) + if f == 0 { + h++ + } + // b = 109900 + } + */ + + // Optimized + for ; b < c+1; b += 17 { + if !IsPrime(b) { + h++ + } + } + + fmt.Println(h) +} + +func IsPrime(value int) bool { + for i := 2; i <= int(math.Floor(float64(value)/2)); i++ { + if value%i == 0 { + return false + } + } + return value > 1 +} diff --git a/2017/day23/input b/2017/day23/input new file mode 100644 index 0000000..9b73642 --- /dev/null +++ b/2017/day23/input @@ -0,0 +1,32 @@ +set b 99 +set c b +jnz a 2 +jnz 1 5 +mul b 100 +sub b -100000 +set c b +sub c -17000 +set f 1 +set d 2 +set e 2 +set g d +mul g e +sub g b +jnz g 2 +set f 0 +sub e -1 +set g e +sub g b +jnz g -8 +sub d -1 +set g d +sub g b +jnz g -13 +jnz f 2 +sub h -1 +set g b +sub g c +jnz g 0 +jnz 1 3 +sub b -17 +jnz 1 -23 diff --git a/2017/day23/input-disassemble b/2017/day23/input-disassemble new file mode 100644 index 0000000..825fab6 --- /dev/null +++ b/2017/day23/input-disassemble @@ -0,0 +1,52 @@ +b = 99 +c = b +if a != 0 { + b = b * 100 + b = b + 100000 + c = b + c = c + 17000 +} +// b = 109900 +// c = 126900 + +for { + f = 1 + d = 2 + for { + e = 2 + g = d + for { + g = g * e + g = g - b + + if g == 0 { + f = 0 + } + + e = e + 1 + g = e + g = g - b + if g != 0 { + break + } + } + + d = d + 1 + g = d + g = g - b + if g != 0 { + break + } + } + if f == 0 { + h = h + 1 + } + g = b + g = g - c + + if g == 0 { + break + } + b = b + 17 +} + diff --git a/2017/day23/input-loops b/2017/day23/input-loops new file mode 100644 index 0000000..82fff08 --- /dev/null +++ b/2017/day23/input-loops @@ -0,0 +1,39 @@ +set b 99 +set c b + +jnz a 2 +jnz 1 5 +mul b 100 +sub b -100000 +set c b +sub c -17000 + + set f 1 + set d 2 + set e 2 + set g d + mul g e + sub g b + + jnz g 2 + set f 0 + + sub e -1 + set g e + sub g b + jnz g -8 + sub d -1 + set g d + sub g b + jnz g -13 + + jnz f 2 + sub h -1 + + set g b + sub g c + + jnz g 0 + jnz 1 3 + sub b -17 + jnz 1 -23 diff --git a/2017/day23/test.go b/2017/day23/test.go new file mode 100644 index 0000000..51ba6c9 --- /dev/null +++ b/2017/day23/test.go @@ -0,0 +1,15 @@ +package main + +import "fmt" + +// Logic before any loops (starting values) +func main() { + var a, b, c int + b = 99 + c = b + b = b * 100 + b = b + 100000 + c = b + c = c + 17000 + fmt.Println(a, b, c) +}