Skip to content

Instantly share code, notes, and snippets.

@cowens
Created November 9, 2017 15:00
Show Gist options
  • Save cowens/8946a4c317a28ed37c95e09b0aa0608f to your computer and use it in GitHub Desktop.
Save cowens/8946a4c317a28ed37c95e09b0aa0608f to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"fmt"
"log"
"os"
"strconv"
)
type Output struct {
balls int
minutes int
}
func main() {
if len(os.Args) < 2 {
log.Printf("usage: %s configfile\n", os.Args[0])
os.Exit(1)
}
file, err := os.Open(os.Args[1])
defer file.Close()
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(file)
clocks := 0;
c := make(chan Output)
for scanner.Scan() {
balls, err := strconv.Atoi(scanner.Text())
if err != nil {
log.Fatal(err)
}
if balls == 0 {
break
}
if balls < 27 || balls > 127 {
log.Fatalf("bad number of balls: %d (0, 27 - 127 allowed)", balls)
}
clocks++;
go makeAndRunClock(balls, c)
}
if scanner.Err() != nil {
log.Fatal(err)
}
for i := 0; i < clocks; i++ {
output := <-c
fmt.Printf("%d balls cycle after %d days (%d minutes).\n", output.balls, output.minutes/(60*24), output.minutes)
}
}
type Ball struct {
id int
next *Ball
}
func listToSlice(head *Ball) []int {
s := make([]int, 0)
for ; head != nil ; head = head.next {
s = append(s, head.id)
}
return s
}
func makeAndRunClock(balls int, c chan Output) {
var minute, five, hour, bottom, last, cur *Ball
var ball int
minutes := 1
mCount := 1
fCount := 0
hCount := 0
bCount := balls - 1
for ball = 0; ball < balls; ball++ {
if bottom == nil {
bottom = &Ball{ball, nil}
last = bottom
continue
}
last.next = &Ball{ball, nil}
last = last.next
}
minute = bottom
bottom = bottom.next
minute.next = nil
for {
//fmt.Printf("minute %d:\n\tmin: %v\n\tfive: %v\n\thour: %v\n\tbot: %v\n",
//minutes, listToSlice(minute), listToSlice(five), listToSlice(hour), listToSlice(bottom));
if bCount == balls {
for ball, cur = 0, bottom; cur != nil && cur.id == ball; ball++ {
cur = cur.next
}
if ball == balls {
break
}
}
minutes++
cur = bottom
bottom = bottom.next
cur.next = nil
bCount--
if mCount != 4 {
cur.next = minute
minute = cur
mCount++
continue
}
last.next = minute
last = minute.next.next.next
minute = nil
mCount = 0
bCount += 4
if fCount != 11 {
cur.next = five
five = cur
fCount++
continue
}
last.next = five
last = five.next.next.next.next.next.next.next.next.next.next
five = nil
fCount = 0
bCount += 11
if hCount != 11 {
cur.next = hour
hour = cur
hCount++
continue
}
last.next = hour
last = hour.next.next.next.next.next.next.next.next.next.next
last.next = cur
last = cur
hour = nil
hCount = 0
bCount += 12
}
c <- Output{balls, minutes}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment