diff --git a/2016/day13/day13.gif b/2016/day13/day13.gif new file mode 100644 index 0000000..a9c91ce Binary files /dev/null and b/2016/day13/day13.gif differ diff --git a/2016/day22/day22.gif b/2016/day22/day22.gif new file mode 100644 index 0000000..67a93a7 Binary files /dev/null and b/2016/day22/day22.gif differ diff --git a/2016/day23/day23.gif b/2016/day23/day23.gif new file mode 100644 index 0000000..f42cd72 Binary files /dev/null and b/2016/day23/day23.gif differ diff --git a/2017/day21/2017day21.gif b/2017/day21/2017day21.gif new file mode 100644 index 0000000..1524b29 Binary files /dev/null and b/2017/day21/2017day21.gif differ diff --git a/2017/day21/day21.go b/2017/day21/day21.go index 4cbd12d..dfb7c10 100644 --- a/2017/day21/day21.go +++ b/2017/day21/day21.go @@ -6,11 +6,13 @@ import ( "math" "os" "strings" + "time" ) var rules map[string]string func main() { + numIters := 18 rules = make(map[string]string) inp := StdinToStrings() @@ -19,27 +21,46 @@ func main() { rules[pts[0]] = pts[2] rules[Flip(pts[0])] = pts[2] rules[Rotate(pts[0], 90)] = pts[2] + rules[Flip(Rotate(pts[0], 90))] = pts[2] rules[Rotate(pts[0], 180)] = pts[2] + rules[Flip(Rotate(pts[0], 180))] = pts[2] rules[Rotate(pts[0], 270)] = pts[2] + rules[Flip(Rotate(pts[0], 270))] = pts[2] } pattern := ".#./..#/###" - for i := 0; i < 2; i++ { - Tick(pattern) + PrettyPrint(pattern) + for i := 0; i < numIters; i++ { + ClearScreen() + PrettyPrint(pattern) + time.Sleep(time.Second / 2) + pattern = Tick(pattern) + } + fmt.Println("Bits On", strings.Count(pattern, "#")) +} + +func PrettyPrint(inp string) { + for _, v := range strings.Split(inp, "/") { + fmt.Println(v) } - /* - pattern = rules[pattern] - pts := SplitBlocks(pattern) - for i := range pts { - pts[i] = rules[pts[i]] - } - fmt.Println(pts) - fmt.Println(CombineBlocks(pts)) - */ } func Tick(pt string) string { - fmt.Println(SplitBlocks(pt)) + subPatterns := SplitBlocks(pt) + var tickSubs []string + for i := range subPatterns { + tickSubs = append(tickSubs, ApplyRule(subPatterns[i])) + } + return CombineBlocks(tickSubs) +} + +func ApplyRule(inp string) string { + if v, ok := rules[inp]; ok { + return v + } + // This is an error. + fmt.Println("No rule for", inp) + os.Exit(1) return "" } @@ -55,23 +76,43 @@ func SplitBlocks(pt string) []string { // 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]) + if blkSize == 2 { + ret = append(ret, pts[j][i:i+blkSize]+"/"+pts[j+1][i:i+blkSize]) + } else { + ret = append(ret, pts[j][i:i+blkSize]+"/"+pts[j+1][i:i+blkSize]+"/"+pts[j+2][i:i+blkSize]) + } } } return ret } 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++ { + var ret []string + if len(pts) == 1 { + return pts[0] } - return ret + var subPts [][]string + for i := range pts { + subPts = append(subPts, strings.Split(pts[i], "/")) + } + subPtSz := len(subPts[0]) + ptSize := int(math.Sqrt(float64(len(subPts) * subPtSz * subPtSz))) + w, h := (ptSize / subPtSz), (ptSize / subPtSz) + for i := 0; i < h; i++ { + st := i * w + for j := 0; j < subPtSz; j++ { + var bld string + for k := 0; k < w; k++ { + bld += subPts[st+k][j] + } + ret = append(ret, bld) + } + } + + return strings.Join(ret, "/") } func Flip(pt string) string { @@ -115,6 +156,10 @@ 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/day24/day24.go b/2017/day24/day24.go index 95e0b58..e2f4fb8 100644 --- a/2017/day24/day24.go +++ b/2017/day24/day24.go @@ -10,106 +10,56 @@ import ( ) var comps []Component +var strongest, best Bridge -// Greater than 907 func main() { inp := StdinToStrings() for i := range inp { comps = append(comps, NewComponent(inp[i])) } - // Need to build chains of all permutations - var perms []Bridge - for i := range comps { - if comps[i].Has(0) { - perms = append(perms, Bridge([]Component{comps[i]})) - } - } + FindStrongest([]Component{NewComponent("0/0")}) + fmt.Println("Strongest:\n", strongest) - changed := true - for changed { - perms, changed = GetNextPerms(perms) - } - - var highB Bridge - highest := 0 - for _, b := range perms { - if b.Value() > highest { - highB = b - highest = b.Value() - } - } - fmt.Println(highB) - /* - for _, b := range perms { - tst := GetAllThatFit(b) - for i := range tst { - - } - - for tst != nil { - b = b.Add(*tst) - tst = GetNextBest(b) - } - fmt.Println(b) - } - */ + FindBest([]Component{NewComponent("0/0")}) + fmt.Println("Best:\n", best) } -func GetNextPerms(perms []Bridge) ([]Bridge, bool) { - var ret []Bridge - var changed bool - for i := range perms { - if !perms[i].IsDone() { - allComps := GetAllThatFit(perms[i]) - if len(allComps) == 0 { - ret = append(ret, perms[i].Add(NewComponent("0/0"))) - } - for j := range allComps { - ret = append(ret, perms[i].Add(allComps[j])) - changed = true - } +// Strongest, regardless of length +func FindStrongest(bridge Bridge) { + if bridge.Strength() > strongest.Strength() { + strongest = bridge + } + for i := range comps { + if comps[i].Has(bridge.Needs()) && !bridge.Has(comps[i]) { + FindStrongest(append(bridge, comps[i])) } } - return ret, changed } -func GetAllThatFit(b Bridge) []Component { - var ret []Component - port := b.Needs() - for i := range comps { - if comps[i].Has(port) && !b.Has(comps[i]) { - ret = append(ret, comps[i]) +// Longest and Strongest +func FindBest(bridge Bridge) { + if bridge.Length() > best.Length() { + best = append([]Component{}, bridge...) + } else if bridge.Length() == best.Length() { + if bridge.Strength() > best.Strength() { + best = bridge } } - return ret -} -func GetNextBest(b Bridge) *Component { - var best *Component - port := b.Needs() for i := range comps { - if comps[i].Has(port) && !b.Has(comps[i]) { - if best == nil || comps[i].Value() > best.Value() { - best = &comps[i] - } + if comps[i].Has(bridge.Needs()) && !bridge.Has(comps[i]) { + FindBest(append(bridge, comps[i])) } } - return best } type Bridge []Component -func (b Bridge) IsDone() bool { - t := []Component(b) - c := t[len(t)-1] - return c.Value() == 0 -} - -func (b Bridge) Value() int { +func (b Bridge) Strength() int { var ret int for _, v := range []Component(b) { - ret += v.Value() + ret += v.Strength() } return ret } @@ -143,12 +93,16 @@ func (b Bridge) Needs() int { return c.Other(c1.Side2) } +func (b Bridge) Length() int { + return len([]Component(b)) +} + func (b Bridge) String() string { ret := "[ " for _, v := range []Component(b) { ret += v.Name + " " } - return fmt.Sprint(ret+"] ", b.Value()) + return fmt.Sprint(ret+"(", b.Strength(), ";", b.Length(), ") ]") } type Component struct { @@ -169,7 +123,7 @@ func (c *Component) Equals(t Component) bool { return c.Side1 == t.Side1 && c.Side2 == t.Side2 } -func (c *Component) Value() int { +func (c *Component) Strength() int { return c.Side1 + c.Side2 } @@ -184,6 +138,10 @@ func (c *Component) Other(v int) int { return c.Side1 } +func (c *Component) String() string { + return c.Name +} + func Atoi(i string) int { var ret int var err error diff --git a/2017/day25/day25.go b/2017/day25/day25.go new file mode 100644 index 0000000..090fbdb --- /dev/null +++ b/2017/day25/day25.go @@ -0,0 +1,147 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + "log" + "os" + "strconv" + "strings" +) + +var currState string +var diagAfterSteps, currStep, currPos int + +var allStates map[string]State + +var tape map[int]bool + +func main() { + inp := StdinToStrings() + tape = make(map[int]bool) + allStates = make(map[string]State) + + // Parse 'Begin' line + pts := strings.Split(inp[0], " ") + st := pts[len(pts)-1] + currState = st[:len(st)-1] + pts = strings.Split(inp[1], " ") + // Parse 'Diagnostic' line + diagAfterSteps = Atoi(pts[5]) + // Parse all of the 'state' lines + for i := 3; i < len(inp); i += 10 { + if state, err := NewState(inp[i:]); err == nil { + allStates[state.Name] = state + } + } + + fmt.Println("Beginning in State", currState) + fmt.Println("Diagnostic After", diagAfterSteps) + + for i := 0; i < diagAfterSteps; i++ { + //fmt.Printf("Steps: %d; State %s; Diag: %d; Tape: %s\n", i, currState, RunDiagnostic(), GetTapeString()) + currState = allStates[currState].Process() + } + fmt.Println("Diagnostic Checksum:", RunDiagnostic()) +} + +func GetTapeString() string { + ret := "[ " + min, max := 0, 0 + for k := range tape { + if k < min { + min = k + } + if k > max { + max = k + } + } + + for i := min; i < max; i++ { + ret += fmt.Sprint("(", i, tape[i], ") ") + } + return ret + "]" +} + +func RunDiagnostic() int { + var chk int + for _, v := range tape { + if v { + chk++ + } + } + return chk +} + +type State struct { + Name string + State1Ins Instruction + State0Ins Instruction +} + +// NewState takes a slice of strings and returns a state built from the _next_ description found +func NewState(inp []string) (State, error) { + if len(inp) < 9 { + return State{}, errors.New("Invalid state instructions") + } + ret := State{} + // The first line should have the state name + ln := inp[0] + ret.Name = ln[len(ln)-2 : len(ln)-1] + ret.State0Ins = NewInstruction(inp[2:5]) + ret.State1Ins = NewInstruction(inp[6:9]) + + return ret, nil +} + +// Process makes the needed changes to the tape and returns the +// next state +func (s State) Process() string { + ins := s.State0Ins + if tape[currPos] { + ins = s.State1Ins + } + tape[currPos] = ins.WriteValue + currPos += ins.Move + return ins.NextState +} + +type Instruction struct { + WriteValue bool + Move int + NextState string +} + +func NewInstruction(inp []string) Instruction { + ret := Instruction{} + tmp := strings.Split(strings.TrimSpace(inp[0]), " ") + ret.WriteValue = (tmp[4][len(tmp[4])-2] == '1') + tmp = strings.Split(strings.TrimSpace(inp[1]), " ") + ret.Move = 1 + if tmp[6] == "left." { + ret.Move = -1 + } + tmp = strings.Split(strings.TrimSpace(inp[2]), " ") + state := tmp[len(tmp)-1] + ret.NextState = state[len(state)-2 : len(state)-1] + return ret +} + +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 +} + +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/day25/input b/2017/day25/input new file mode 100644 index 0000000..84dfd33 --- /dev/null +++ b/2017/day25/input @@ -0,0 +1,62 @@ +Begin in state A. +Perform a diagnostic checksum after 12134527 steps. + +In state A: + If the current value is 0: + - Write the value 1. + - Move one slot to the right. + - Continue with state B. + If the current value is 1: + - Write the value 0. + - Move one slot to the left. + - Continue with state C. + +In state B: + If the current value is 0: + - Write the value 1. + - Move one slot to the left. + - Continue with state A. + If the current value is 1: + - Write the value 1. + - Move one slot to the right. + - Continue with state C. + +In state C: + If the current value is 0: + - Write the value 1. + - Move one slot to the right. + - Continue with state A. + If the current value is 1: + - Write the value 0. + - Move one slot to the left. + - Continue with state D. + +In state D: + If the current value is 0: + - Write the value 1. + - Move one slot to the left. + - Continue with state E. + If the current value is 1: + - Write the value 1. + - Move one slot to the left. + - Continue with state C. + +In state E: + If the current value is 0: + - Write the value 1. + - Move one slot to the right. + - Continue with state F. + If the current value is 1: + - Write the value 1. + - Move one slot to the right. + - Continue with state A. + +In state F: + If the current value is 0: + - Write the value 1. + - Move one slot to the right. + - Continue with state A. + If the current value is 1: + - Write the value 1. + - Move one slot to the right. + - Continue with state E. diff --git a/2017/day25/testinput b/2017/day25/testinput new file mode 100644 index 0000000..3fab6c1 --- /dev/null +++ b/2017/day25/testinput @@ -0,0 +1,22 @@ +Begin in state A. +Perform a diagnostic checksum after 6 steps. + +In state A: + If the current value is 0: + - Write the value 1. + - Move one slot to the right. + - Continue with state B. + If the current value is 1: + - Write the value 0. + - Move one slot to the left. + - Continue with state B. + +In state B: + If the current value is 0: + - Write the value 1. + - Move one slot to the left. + - Continue with state A. + If the current value is 1: + - Write the value 1. + - Move one slot to the right. + - Continue with state A.