package main
import (
"fmt"
"strings"
"github.com/davecgh/go-spew/spew"
)
type Item struct {
Prev *Item
Next *Item
Val int
}
type Circular struct {
Root *Item
Current *Item
}
func NewCircular() *Circular {
i := Item{
Val: 0,
}
i.Prev = &i
i.Next = &i
return &Circular{
Current: &i,
Root: &i,
}
}
func (c *Circular) Add(i int) {
it := Item{
Prev: c.Current,
Next: c.Current.Next,
Val: i,
}
c.Current.Next.Prev = &it
c.Current.Next = &it
c.Current = &it
}
func (c *Circular) Pop() int {
prev := c.Current.Prev
next := c.Current.Next
prev.Next = next
next.Prev = prev
val := c.Current.Val
c.Current = next
return val
}
func (c *Circular) Rotate(i int) {
for {
if i > 0 {
c.Current = c.Current.Next
i--
} else if i < 0 {
c.Current = c.Current.Prev
i++
} else {
break
}
}
}
func (c Circular) String() string {
output := strings.Builder{}
it := c.Root
for {
if it == c.Current {
output.WriteString(fmt.Sprintf("\t(%3d)", it.Val))
} else {
output.WriteString(fmt.Sprintf("\t%4d", it.Val))
}
it = it.Next
if it == c.Root {
break
}
}
return output.String()
}
type Puzzle struct {
Players int
LastMarble int
Marbles *Circular
}
func (p *Puzzle) Solution1(debug bool) int {
players := make([]int, p.Players)
if debug {
fmt.Printf("[--]%s\n", p.Marbles)
}
pnum := 0
for t := 1; t <= p.LastMarble; t++ {
if t%23 == 0 {
p.Marbles.Rotate(-7)
players[pnum] += t + p.Marbles.Pop()
} else {
p.Marbles.Rotate(1)
p.Marbles.Add(t)
}
if debug {
fmt.Printf("[%2d]%s\n", pnum+1, p.Marbles)
}
pnum++
if pnum >= p.Players {
pnum = 0
}
}
if debug {
spew.Dump(players)
}
highest := 0
for _, p := range players {
if p > highest {
highest = p
}
}
return highest
}
func (p *Puzzle) Solution2() int {
return 0
}
func main() {
p := Puzzle{
//Players: 9,
// LastMarble: 25,
Players: 439,
LastMarble: 7130700,
Marbles: NewCircular(),
}
fmt.Println(p.Solution1(false))
fmt.Println(p.Solution2())
}