2018 day 12 done
This commit is contained in:
parent
c7af2e1eb7
commit
18d07e81db
@ -7,136 +7,177 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var row map[int]bool
|
const (
|
||||||
var transitions []*Transition
|
MaxInt = int(^uint(0) >> 1)
|
||||||
|
MinInt = -MaxInt - 1
|
||||||
|
)
|
||||||
|
|
||||||
|
var lastState string
|
||||||
|
var garden *Garden
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
inp := StdinToStringSlice()
|
inp := StdinToStringSlice()
|
||||||
BuildRow(inp[0])
|
garden = NewGarden(strings.Trim(inp[0], "intalsae: "), 0)
|
||||||
for _, v := range inp[2:] {
|
for _, v := range inp[2:] {
|
||||||
transitions = append(transitions, NewTransition(v))
|
garden.transitions = append(garden.transitions, NewTransition(v))
|
||||||
}
|
}
|
||||||
fmt.Print("St: ")
|
generations := 50000000000
|
||||||
PrintState()
|
var i int
|
||||||
for i := 0; i < 20; i++ {
|
for i = 0; i < generations; i++ {
|
||||||
Tick()
|
lastState = garden.string()
|
||||||
fmt.Printf("%2d: ", i)
|
garden = garden.tick()
|
||||||
PrintState()
|
if garden.string() == lastState {
|
||||||
|
i++
|
||||||
|
break
|
||||||
}
|
}
|
||||||
fmt.Println("Total:", GetSum())
|
}
|
||||||
|
garden.shiftPots(generations - i)
|
||||||
|
fmt.Println(garden.sum())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Tick() {
|
/**
|
||||||
m := make(map[int]bool)
|
* A Garden
|
||||||
lowest, highest := 0, 0
|
*/
|
||||||
for i := range row {
|
type Garden struct {
|
||||||
if i < lowest {
|
pots []*Pot
|
||||||
lowest = i
|
transitions []*Transition
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGarden(inp string, start int) *Garden {
|
||||||
|
g := &Garden{}
|
||||||
|
for k, v := range inp {
|
||||||
|
p := &Pot{
|
||||||
|
id: k + start,
|
||||||
|
value: rb(v),
|
||||||
}
|
}
|
||||||
if i > highest {
|
g.pots = append(g.pots, p)
|
||||||
highest = i
|
|
||||||
}
|
}
|
||||||
}
|
return g
|
||||||
for i := lowest - 2; i <= highest+2; i++ {
|
}
|
||||||
m[i] = GetNextValue(i)
|
|
||||||
}
|
func (g *Garden) shiftPots(val int) {
|
||||||
lowest, highest = 0, 0
|
for i := range g.pots {
|
||||||
for k := range m {
|
g.pots[i].id = g.pots[i].id + val
|
||||||
if k < lowest && m[k] {
|
|
||||||
lowest = k
|
|
||||||
}
|
|
||||||
if k > highest && m[k] {
|
|
||||||
highest = k
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row = make(map[int]bool)
|
|
||||||
for i := lowest; i <= highest; i++ {
|
|
||||||
row[i] = m[i]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSum() int {
|
func (g *Garden) sum() int64 {
|
||||||
var ret int
|
var ret int64
|
||||||
lowest, highest := 0, 0
|
st, ed := g.getStartIndex(), g.getEndIndex()
|
||||||
for i := range row {
|
for i := st; i <= ed; i++ {
|
||||||
if i < lowest {
|
if g.getPot(i).value {
|
||||||
lowest = i
|
ret += int64(i)
|
||||||
}
|
|
||||||
if i > highest {
|
|
||||||
highest = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := lowest; i <= highest; i++ {
|
|
||||||
if row[i] {
|
|
||||||
ret += i
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildRow(inp string) {
|
func (g *Garden) tick() *Garden {
|
||||||
inp = strings.Split(inp, ": ")[1]
|
earliest, latest := g.getStartIndex(), g.getEndIndex()
|
||||||
row = make(map[int]bool)
|
st := earliest - 2
|
||||||
for i, v := range inp {
|
ed := latest + 2
|
||||||
row[i] = rb(v)
|
ret := &Garden{
|
||||||
|
transitions: g.transitions,
|
||||||
}
|
}
|
||||||
|
for i := st; i <= ed; i++ {
|
||||||
|
next := g.getNextStateForPot(i)
|
||||||
|
if next {
|
||||||
|
ret.pots = append(ret.pots, &Pot{
|
||||||
|
id: i,
|
||||||
|
value: next,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetIdxValue(idx int) byte {
|
func (g *Garden) getNextStateForPot(id int) bool {
|
||||||
var ret byte
|
var ret byte
|
||||||
for i := idx + 2; i >= idx-2; i-- {
|
for i := id - 2; i <= id+2; i++ {
|
||||||
ret = ret << 1
|
ret = ret << 1
|
||||||
if row[i] {
|
if g.getPot(i).value {
|
||||||
ret = ret | 1
|
ret = ret | 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
for _, v := range g.transitions {
|
||||||
}
|
if v.GetValue() == ret {
|
||||||
|
|
||||||
func GetNextValue(idx int) bool {
|
|
||||||
idxVal := GetIdxValue(idx)
|
|
||||||
for _, v := range transitions {
|
|
||||||
if v.GetValue() == idxVal {
|
|
||||||
return v.next
|
return v.next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false //g.getPot(id).value
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetValueString(b byte) string {
|
func (g *Garden) substring(st, ed int) string {
|
||||||
var ret string
|
var ret string
|
||||||
for i := 0; i < 5; i++ {
|
for i := st; i <= ed; i++ {
|
||||||
if (b & 1) == 1 {
|
ret += g.getPot(i).string()
|
||||||
ret = ret + "#"
|
|
||||||
} else {
|
|
||||||
ret = ret + "."
|
|
||||||
}
|
|
||||||
b = b >> 1
|
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrintState() {
|
func (g *Garden) string() string {
|
||||||
lowest, highest := -2, 30
|
var ret string
|
||||||
for i := range row {
|
for i := g.getStartIndex(); i <= g.getEndIndex(); i++ {
|
||||||
if i < lowest {
|
ret += g.getPot(i).string()
|
||||||
lowest = i
|
|
||||||
}
|
}
|
||||||
if i > highest {
|
return ret
|
||||||
highest = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Print("(", lowest, ") ")
|
|
||||||
for i := lowest; i <= highest; i++ {
|
|
||||||
if row[i] {
|
|
||||||
fmt.Print("#")
|
|
||||||
} else {
|
|
||||||
fmt.Print(".")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Println(" (", highest, ") ")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Garden) transitionStrings() string {
|
||||||
|
var ret string
|
||||||
|
for _, v := range g.transitions {
|
||||||
|
ret = ret + v.string() + "\n"
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Garden) getStartIndex() int {
|
||||||
|
min := MaxInt
|
||||||
|
for _, v := range g.pots {
|
||||||
|
if v.id < min {
|
||||||
|
min = v.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Garden) getEndIndex() int {
|
||||||
|
max := MinInt
|
||||||
|
for _, v := range g.pots {
|
||||||
|
if v.id > max {
|
||||||
|
max = v.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Garden) getPot(idx int) *Pot {
|
||||||
|
for _, v := range g.pots {
|
||||||
|
if v.id == idx {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &Pot{
|
||||||
|
id: idx,
|
||||||
|
value: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Pot
|
||||||
|
*/
|
||||||
|
type Pot struct {
|
||||||
|
id int
|
||||||
|
value bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pot) string() string {
|
||||||
|
return bs(p.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transitions
|
||||||
|
*/
|
||||||
type Transition struct {
|
type Transition struct {
|
||||||
state []bool
|
state []bool
|
||||||
next bool
|
next bool
|
||||||
@ -146,9 +187,12 @@ func NewTransition(inp string) *Transition {
|
|||||||
var state []bool
|
var state []bool
|
||||||
var next bool
|
var next bool
|
||||||
pts := strings.Split(inp, " => ")
|
pts := strings.Split(inp, " => ")
|
||||||
for i := len(pts[0]) - 1; i >= 0; i-- {
|
for i := range pts[0] {
|
||||||
state = append(state, bb(pts[0][i]))
|
state = append(state, bb(pts[0][i]))
|
||||||
}
|
}
|
||||||
|
//for i := len(pts[0]) - 1; i >= 0; i-- {
|
||||||
|
// state = append(state, bb(pts[0][i]))
|
||||||
|
//}
|
||||||
next = bb(pts[1][0])
|
next = bb(pts[1][0])
|
||||||
t := &Transition{
|
t := &Transition{
|
||||||
state: state,
|
state: state,
|
||||||
@ -157,6 +201,14 @@ func NewTransition(inp string) *Transition {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Transition) string() string {
|
||||||
|
var ret string
|
||||||
|
for _, v := range t.state {
|
||||||
|
ret += bs(v)
|
||||||
|
}
|
||||||
|
return ret + " => " + bs(t.next)
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Transition) GetValue() byte {
|
func (t *Transition) GetValue() byte {
|
||||||
var ret byte
|
var ret byte
|
||||||
for _, v := range t.state {
|
for _, v := range t.state {
|
||||||
@ -168,6 +220,43 @@ func (t *Transition) GetValue() byte {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper Functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Take a byte and return a string representation of the bits
|
||||||
|
func byteToString(b byte) string {
|
||||||
|
var ret string
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
if b&1 == 1 {
|
||||||
|
ret += "#"
|
||||||
|
} else {
|
||||||
|
ret += "."
|
||||||
|
}
|
||||||
|
b = b >> 1
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take a string representation of a bits and return the byte
|
||||||
|
func stringToByte(n string) byte {
|
||||||
|
var b byte
|
||||||
|
for i := range n {
|
||||||
|
if n[i] == '#' {
|
||||||
|
b = b | 1
|
||||||
|
}
|
||||||
|
b = b << 1
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func bs(b bool) string {
|
||||||
|
if b {
|
||||||
|
return "#"
|
||||||
|
}
|
||||||
|
return "."
|
||||||
|
}
|
||||||
|
|
||||||
func rb(r rune) bool {
|
func rb(r rune) bool {
|
||||||
return bb(byte(r))
|
return bb(byte(r))
|
||||||
}
|
}
|
||||||
|
123
2018/day12/problem
Normal file
123
2018/day12/problem
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
Advent of Code
|
||||||
|
|
||||||
|
--- Day 12: Subterranean Sustainability ---
|
||||||
|
|
||||||
|
The year 518 is significantly more underground than your history books implied. Either that, or you've arrived in a vast
|
||||||
|
cavern network under the North Pole.
|
||||||
|
|
||||||
|
After exploring a little, you discover a long tunnel that contains a row of small pots as far as you can see to your left
|
||||||
|
and right. A few of them contain plants - someone is trying to grow things in these geothermally-heated caves.
|
||||||
|
|
||||||
|
The pots are numbered, with 0 in front of you. To the left, the pots are numbered -1, -2, -3, and so on; to the right, 1, 2,
|
||||||
|
3.... Your puzzle input contains a list of pots from 0 to the right and whether they do (#) or do not (.) currently contain
|
||||||
|
a plant, the initial state. (No other pots currently contain plants.) For example, an initial state of #..##.... indicates
|
||||||
|
that pots 0, 3, and 4 currently contain plants.
|
||||||
|
|
||||||
|
Your puzzle input also contains some notes you find on a nearby table: someone has been trying to figure out how these
|
||||||
|
plants spread to nearby pots. Based on the notes, for each generation of plants, a given pot has or does not have a plant
|
||||||
|
based on whether that pot (and the two pots on either side of it) had a plant in the last generation. These are written as
|
||||||
|
LLCRR => N, where L are pots to the left, C is the current pot being considered, R are the pots to the right, and N is
|
||||||
|
whether the current pot will have a plant in the next generation. For example:
|
||||||
|
|
||||||
|
• A note like ..#.. => . means that a pot that contains a plant but with no plants within two pots of it will not have a
|
||||||
|
plant in it during the next generation.
|
||||||
|
• A note like ##.## => . means that an empty pot with two plants on each side of it will remain empty in the next
|
||||||
|
generation.
|
||||||
|
• A note like .##.# => # means that a pot has a plant in a given generation if, in the previous generation, there were
|
||||||
|
plants in that pot, the one immediately to the left, and the one two pots to the right, but not in the ones immediately
|
||||||
|
to the right and two to the left.
|
||||||
|
|
||||||
|
It's not clear what these plants are for, but you're sure it's important, so you'd like to make sure the current
|
||||||
|
configuration of plants is sustainable by determining what will happen after 20 generations.
|
||||||
|
|
||||||
|
For example, given the following input:
|
||||||
|
|
||||||
|
initial state: #..#.#..##......###...###
|
||||||
|
|
||||||
|
...## => #
|
||||||
|
..#.. => #
|
||||||
|
.#... => #
|
||||||
|
.#.#. => #
|
||||||
|
.#.## => #
|
||||||
|
.##.. => #
|
||||||
|
.#### => #
|
||||||
|
#.#.# => #
|
||||||
|
#.### => #
|
||||||
|
##.#. => #
|
||||||
|
##.## => #
|
||||||
|
###.. => #
|
||||||
|
###.# => #
|
||||||
|
####. => #
|
||||||
|
|
||||||
|
For brevity, in this example, only the combinations which do produce a plant are listed. (Your input includes all possible
|
||||||
|
combinations.) Then, the next 20 generations will look like this:
|
||||||
|
|
||||||
|
1 2 3
|
||||||
|
0 0 0 0
|
||||||
|
0: ...#..#.#..##......###...###...........
|
||||||
|
1: ...#...#....#.....#..#..#..#...........
|
||||||
|
2: ...##..##...##....#..#..#..##..........
|
||||||
|
3: ..#.#...#..#.#....#..#..#...#..........
|
||||||
|
4: ...#.#..#...#.#...#..#..##..##.........
|
||||||
|
5: ....#...##...#.#..#..#...#...#.........
|
||||||
|
6: ....##.#.#....#...#..##..##..##........
|
||||||
|
7: ...#..###.#...##..#...#...#...#........
|
||||||
|
8: ...#....##.#.#.#..##..##..##..##.......
|
||||||
|
9: ...##..#..#####....#...#...#...#.......
|
||||||
|
10: ..#.#..#...#.##....##..##..##..##......
|
||||||
|
11: ...#...##...#.#...#.#...#...#...#......
|
||||||
|
12: ...##.#.#....#.#...#.#..##..##..##.....
|
||||||
|
13: ..#..###.#....#.#...#....#...#...#.....
|
||||||
|
14: ..#....##.#....#.#..##...##..##..##....
|
||||||
|
15: ..##..#..#.#....#....#..#.#...#...#....
|
||||||
|
16: .#.#..#...#.#...##...#...#.#..##..##...
|
||||||
|
17: ..#...##...#.#.#.#...##...#....#...#...
|
||||||
|
18: ..##.#.#....#####.#.#.#...##...##..##..
|
||||||
|
19: .#..###.#..#.#.#######.#.#.#..#.#...#..
|
||||||
|
20: .#....##....#####...#######....#.#..##.
|
||||||
|
|
||||||
|
The generation is shown along the left, where 0 is the initial state. The pot numbers are shown along the top, where 0
|
||||||
|
labels the center pot, negative-numbered pots extend to the left, and positive pots extend toward the right. Remember, the
|
||||||
|
initial state begins at pot 0, which is not the leftmost pot used in this example.
|
||||||
|
|
||||||
|
After one generation, only seven plants remain. The one in pot 0 matched the rule looking for ..#.., the one in pot 4
|
||||||
|
matched the rule looking for .#.#., pot 9 matched .##.., and so on.
|
||||||
|
|
||||||
|
In this example, after 20 generations, the pots shown as # contain plants, the furthest left of which is pot -2, and the
|
||||||
|
furthest right of which is pot 34. Adding up all the numbers of plant-containing pots after the 20th generation produces
|
||||||
|
325.
|
||||||
|
|
||||||
|
After 20 generations, what is the sum of the numbers of all pots which contain a plant?
|
||||||
|
|
||||||
|
Your puzzle answer was 2281.
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
You realize that 20 generations aren't enough. After all, these plants will need to last another 1500 years to even reach
|
||||||
|
your timeline, not to mention your future.
|
||||||
|
|
||||||
|
After fifty billion (50000000000) generations, what is the sum of the numbers of all pots which contain a plant?
|
||||||
|
|
||||||
|
Your puzzle answer was 2250000000120.
|
||||||
|
|
||||||
|
Both parts of this puzzle are complete! They provide two gold stars: **
|
||||||
|
|
||||||
|
References
|
||||||
|
|
||||||
|
Visible links
|
||||||
|
. https://adventofcode.com/
|
||||||
|
. https://adventofcode.com/2018/about
|
||||||
|
. https://adventofcode.com/2018/events
|
||||||
|
. https://adventofcode.com/2018/settings
|
||||||
|
. https://adventofcode.com/2018/auth/logout
|
||||||
|
. Advent of Code Supporter
|
||||||
|
https://adventofcode.com/2018/support
|
||||||
|
. https://adventofcode.com/2018
|
||||||
|
. https://adventofcode.com/2018
|
||||||
|
. https://adventofcode.com/2018/support
|
||||||
|
. https://adventofcode.com/2018/sponsors
|
||||||
|
. https://adventofcode.com/2018/leaderboard
|
||||||
|
. https://adventofcode.com/2018/stats
|
||||||
|
. https://adventofcode.com/2018/sponsors
|
||||||
|
. https://adventofcode.com/2018
|
||||||
|
. https://adventofcode.com/2018/day/12/input
|
Loading…
Reference in New Issue
Block a user