commit a9420a1a07acb9ec64093621aeae81cb4bde2655 Author: Lars Mikal Rogne Date: Wed Apr 24 19:35:43 2024 +0200 Initial commit diff --git a/collatz.go b/collatz.go new file mode 100644 index 0000000..cab9120 --- /dev/null +++ b/collatz.go @@ -0,0 +1,11 @@ +package main + +import ( + "collatz/collatz" + "collatz/io" +) + +func main() { + calculator := collatz.NewCalculator(new(io.Cliargs)) + calculator.Collatz() +} diff --git a/collatz/calculator.go b/collatz/calculator.go new file mode 100644 index 0000000..7be8fb4 --- /dev/null +++ b/collatz/calculator.go @@ -0,0 +1,54 @@ +package collatz + +import ( + "collatz/io" + "fmt" + "log" + "math/big" +) + +type Calculator struct { + parser *io.Cliargs + three *big.Int + two *big.Int + one *big.Int +} + +func NewCalculator(parser *io.Cliargs) Calculator { + r := Calculator{ + parser: parser, + three: new(big.Int).SetInt64(3), + two: new(big.Int).SetInt64(2), + one: new(big.Int).SetInt64(1), + } + return r +} + +func (o Calculator) Collatz() { + err := o.parser.Parse() + if err != nil { + log.Panicf("Couldn't parse input: %s\n", err) + } + number := o.parser.GetNumber() + fmt.Print(number.Text(10)) + o.nextNumber(number) + fmt.Println() +} + +func (o Calculator) nextNumber(in *big.Int) { + if in.Cmp(o.one) < 0 { + log.Panicln("Must be greater than 0") + } + if in.Cmp(o.one) == 0 { + return + } + var newNumber *big.Int + if new(big.Int).And(in, o.one).Cmp(o.one) == 0 { + newNumber = new(big.Int).Add(new(big.Int).Mul(in, o.three), o.one) + } else { + newNumber = new(big.Int).Div(in, o.two) + } + + fmt.Printf(" -> %s", newNumber.Text(10)) + o.nextNumber(newNumber) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..48dad79 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module collatz + +go 1.22 diff --git a/io/cliargs.go b/io/cliargs.go new file mode 100644 index 0000000..f396516 --- /dev/null +++ b/io/cliargs.go @@ -0,0 +1,28 @@ +package io + +import ( + "errors" + "math/big" + "os" +) + +type Cliargs struct { + value *big.Int +} + +func (arg *Cliargs) Parse() error { + args := os.Args[1:] + if len(args) != 1 { + return errors.New("only expected 1 arg") + } + num, success := new(big.Int).SetString(args[0], 10) + if !success { + return errors.New("argument is not an integer") + } + arg.value = num + return nil +} + +func (arg *Cliargs) GetNumber() *big.Int { + return arg.value +}