2020 Day 23 Complete!
This commit is contained in:
parent
5a37a6e964
commit
3b5bae7948
1
2020/day23/input
Normal file
1
2020/day23/input
Normal file
@ -0,0 +1 @@
|
||||
614752839
|
228
2020/day23/main.go
Normal file
228
2020/day23/main.go
Normal file
@ -0,0 +1,228 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
var highest int
|
||||
var lowest int
|
||||
var AllCups map[int]*Cup
|
||||
|
||||
func init() {
|
||||
highest = h.MIN_INT
|
||||
lowest = h.MAX_INT
|
||||
AllCups = make(map[int]*Cup)
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("# Day 22")
|
||||
inp := h.StdinToString()
|
||||
|
||||
solve(inp, h.Atoi(h.OptArgNumber(1, "2")))
|
||||
}
|
||||
|
||||
var move int
|
||||
var first *Cup
|
||||
|
||||
func solve(inp string, part int) {
|
||||
moves := 100
|
||||
if part == 1 {
|
||||
BuildCircle(inp, -1)
|
||||
} else {
|
||||
BuildCircle(inp, 1000000)
|
||||
moves = 10000000
|
||||
}
|
||||
current := first
|
||||
for i := 0; i < moves; i++ {
|
||||
current = DoMove(current)
|
||||
}
|
||||
ans := FindLabel(1, first).next
|
||||
fmt.Println("## Part", part, ":\nAnswer:")
|
||||
if part == 1 {
|
||||
for ans.label != 1 {
|
||||
fmt.Print(ans.label)
|
||||
ans = ans.next
|
||||
}
|
||||
} else {
|
||||
fmt.Print(ans.label * ans.next.label)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func BuildCircle(inp string, cups int) *Cup {
|
||||
var wrk *Cup
|
||||
for k := range inp {
|
||||
next := &Cup{label: int(inp[k] - '0')}
|
||||
next.next = next
|
||||
next.prev = next
|
||||
if first == nil {
|
||||
first = next
|
||||
first.next = next
|
||||
first.prev = next
|
||||
} else {
|
||||
wrk.SetNext(next)
|
||||
}
|
||||
if next.label > highest {
|
||||
highest = next.label
|
||||
}
|
||||
if next.label < lowest {
|
||||
lowest = next.label
|
||||
}
|
||||
AllCups[next.label] = next
|
||||
wrk = next
|
||||
}
|
||||
total := Count(first)
|
||||
last := GetLast(first)
|
||||
nextLabel := highest + 1
|
||||
for cups > 0 && total < cups {
|
||||
next := &Cup{label: nextLabel}
|
||||
nextLabel++
|
||||
next.next = next
|
||||
next.prev = next
|
||||
last.SetNext(next)
|
||||
last = next
|
||||
if next.label > highest {
|
||||
highest = next.label
|
||||
}
|
||||
if next.label < lowest {
|
||||
lowest = next.label
|
||||
}
|
||||
AllCups[next.label] = next
|
||||
total++
|
||||
}
|
||||
return first
|
||||
}
|
||||
|
||||
func DoMove(curr *Cup) *Cup {
|
||||
move++
|
||||
hold := curr.RemoveNext(3)
|
||||
target := curr.label - 1
|
||||
if target < lowest {
|
||||
target = highest
|
||||
}
|
||||
// Check the removed cups
|
||||
for FindLabel(target, hold) != nil {
|
||||
target = target - 1
|
||||
if target < lowest {
|
||||
target = highest
|
||||
}
|
||||
}
|
||||
//dest := FindLabel(target, curr)
|
||||
dest := AllCups[target]
|
||||
dest.SetNext(hold)
|
||||
return curr.next
|
||||
}
|
||||
|
||||
func FindLabel(num int, first *Cup) *Cup {
|
||||
if first.label == num {
|
||||
return first
|
||||
}
|
||||
c := first.next
|
||||
for c != first {
|
||||
if c.label == num {
|
||||
return c
|
||||
}
|
||||
c = c.next
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StringifyCircle(first *Cup, current *Cup) string {
|
||||
c := first
|
||||
stringify := func(c *Cup) string {
|
||||
if c == nil {
|
||||
return "ERR"
|
||||
}
|
||||
if c == current {
|
||||
return fmt.Sprintf("(%d)", c.label)
|
||||
} else {
|
||||
return fmt.Sprintf(" %d ", c.label)
|
||||
}
|
||||
}
|
||||
ret := stringify(c)
|
||||
c = c.next
|
||||
for c != first {
|
||||
ret = ret + stringify(c)
|
||||
if c == nil {
|
||||
ret = ret + " ERR "
|
||||
break
|
||||
}
|
||||
if c.next == c {
|
||||
break
|
||||
}
|
||||
c = c.next
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetLast(cups *Cup) *Cup {
|
||||
if cups.next == cups || cups.next == nil {
|
||||
return cups
|
||||
}
|
||||
c := cups.next
|
||||
for c.next != cups {
|
||||
if c.next == nil {
|
||||
break
|
||||
}
|
||||
c = c.next
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func Count(cups *Cup) int {
|
||||
start := cups
|
||||
wrk := start.next
|
||||
ret := 1
|
||||
for wrk != start {
|
||||
wrk = wrk.next
|
||||
ret++
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
var current *Cup
|
||||
|
||||
type Cup struct {
|
||||
label int
|
||||
next *Cup
|
||||
prev *Cup
|
||||
}
|
||||
|
||||
func (c *Cup) SetNext(next *Cup) {
|
||||
if c.next == c {
|
||||
c.prev = next
|
||||
c.next = next
|
||||
next.next = c
|
||||
next.prev = c
|
||||
return
|
||||
}
|
||||
hold := c.next
|
||||
// c.p c c.n
|
||||
// c.p c next... c.n
|
||||
c.next = next
|
||||
if hold != nil {
|
||||
hold.prev = GetLast(next)
|
||||
GetLast(next).next = hold
|
||||
}
|
||||
next.prev = c
|
||||
}
|
||||
|
||||
// RemoveNext removes the next cnt cups, returning a circle of the removed cups
|
||||
func (c *Cup) RemoveNext(cnt int) *Cup {
|
||||
if cnt == 0 {
|
||||
return nil
|
||||
}
|
||||
hold := c.next
|
||||
dest := hold
|
||||
for cnt > 0 {
|
||||
dest = dest.next
|
||||
cnt--
|
||||
}
|
||||
c.next = dest
|
||||
dest.prev.next = hold
|
||||
hold.prev = dest.prev
|
||||
dest.prev = c
|
||||
return hold
|
||||
}
|
1
2020/day23/testinput
Normal file
1
2020/day23/testinput
Normal file
@ -0,0 +1 @@
|
||||
389125467
|
Loading…
Reference in New Issue
Block a user