Created
November 9, 2017 15:00
-
-
Save cowens/8946a4c317a28ed37c95e09b0aa0608f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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