Last active
May 16, 2016 08:17
-
-
Save esehara/33bb4df90fa9c168b7949ed4fc253ab2 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 ( | |
"flag" | |
"fmt" | |
"os" | |
"runtime" | |
"sort" | |
"strconv" | |
"strings" | |
) | |
type CommandType struct { | |
Simple *bool | |
Sort *bool | |
Increment *bool | |
FilterMax *int | |
Number int | |
} | |
type CollatzResult struct { | |
Number int | |
Route []int | |
Step int | |
} | |
func (result CollatzResult) Merge(target CollatzResult) CollatzResult { | |
var new_route []int | |
if len(target.Route) == 0 && len(result.Route) == 0 { | |
new_route = make([]int, 0) | |
} else { | |
new_route = append(target.Route, result.Route...) | |
} | |
return CollatzResult{ | |
target.Number, | |
new_route, | |
result.Step + target.Step, | |
} | |
} | |
func (result CollatzResult) RouteTemplate(joinstr string) (route string) { | |
return strings.Join(IatoAa(result.Route), joinstr) | |
} | |
func (result CollatzResult) Println() { | |
fmt.Print(result.Number) | |
fmt.Print(",") | |
fmt.Println(result.Step) | |
} | |
func (result CollatzResult) PrintVerbose() { | |
fmt.Println("Number:" + strconv.Itoa(result.Number)) | |
fmt.Print("Route:") | |
fmt.Println(result.RouteTemplate(" -> ")) | |
fmt.Println("Step:" + strconv.Itoa(result.Step)) | |
} | |
// const CACHE_SIZE = 1000 | |
// var collatzcache map[int]CollatzResult = make(map[int]CollatzResult) | |
func collatz(n int, use_route bool) CollatzResult { | |
var step int | |
var route []int | |
x := n | |
for x > 1 { | |
if use_route { | |
route = append(route, x) | |
} | |
if x%2 == 1 { | |
x = x*3 + 1 | |
} else { | |
x = x / 2 | |
} | |
step++ | |
} | |
if use_route { | |
route = append(route, x) | |
} | |
return CollatzResult{n, route, step} | |
} | |
// My Library | |
func IatoAa(xs []int) (ys []string) { | |
for _, i := range xs { | |
j := strconv.Itoa(i) | |
ys = append(ys, j) | |
} | |
return ys | |
} | |
// Sort Interface | |
type CollatzResults []CollatzResult | |
func (cs CollatzResults) Len() int { | |
return len(cs) | |
} | |
func (cs CollatzResults) Less(i, j int) bool { | |
return cs[i].Step < cs[j].Step | |
} | |
func (cs CollatzResults) Swap(i, j int) { | |
cs[i], cs[j] = cs[j], cs[i] | |
} | |
// End | |
func initialize() (n CommandType) { | |
// flag | |
n.Simple = flag.Bool( | |
"s", false, "Simple Output. Number and Step only") | |
n.Increment = flag.Bool( | |
"i", false, "Increment Output") | |
n.FilterMax = flag.Int( | |
"fmax", 0, "Under Step, not show") | |
n.Sort = flag.Bool( | |
"sort", false, "Sort by Step") | |
// Get Command Line | |
flag.Parse() | |
f := flag.Args() | |
if flag.NArg() == 0 { | |
n.Number = 21 | |
} else { | |
n.Number, _ = strconv.Atoi(f[0]) | |
} | |
if n.Number < 1 { | |
fmt.Println("under zero number cannot end") | |
os.Exit(1) | |
} | |
return | |
} | |
func collatzOutput(context CommandType, n int) { | |
var c CollatzResult | |
c = collatz(n, !*context.Simple) | |
if !*context.Increment || c.Step > *context.FilterMax { | |
if *context.Simple { | |
c.Println() | |
} else { | |
c.PrintVerbose() | |
} | |
} | |
} | |
func collatzGenerate(context CommandType) { | |
const IncrementNumber = 500000 | |
var cs CollatzResults | |
var current_n int | |
var next_n int = IncrementNumber | |
var ch chan CollatzResult = make(chan CollatzResult) | |
gocollatz := func(j int) { | |
ch <- collatz(j, !*context.Simple) | |
} | |
for next_n < context.Number { | |
for i := 1 + current_n; next_n > i; i++ { | |
go gocollatz(i) | |
} | |
for i := 1 + current_n; next_n > i; i++ { | |
c := <-ch | |
if c.Step > *context.FilterMax { | |
cs = append(cs, c) | |
} | |
} | |
current_n += IncrementNumber | |
next_n += IncrementNumber | |
} | |
var reminder_ap int = current_n | |
for current_n < context.Number { | |
go gocollatz(current_n) | |
current_n++ | |
} | |
for reminder_ap < context.Number { | |
c := <-ch | |
if c.Step > *context.FilterMax { | |
cs = append(cs, c) | |
} | |
reminder_ap++ | |
} | |
sort.Sort(cs) | |
for _, elem := range cs { | |
elem.Println() | |
} | |
} | |
func main() { | |
cpus := runtime.NumCPU() | |
runtime.GOMAXPROCS(cpus) | |
var context CommandType | |
context = initialize() | |
if *context.Increment { | |
if *context.Sort { | |
collatzGenerate(context) | |
} else { | |
for i := 1; context.Number >= i; i++ { | |
collatzOutput(context, i) | |
} | |
} | |
} else { | |
collatzOutput(context, context.Number) | |
} | |
os.Exit(0) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment