gocollatz/collatz/calculator.go
Lars M. Rogne 713f70041b
All checks were successful
Run Tests / test (push) Successful in 9s
Clean code improvements.
2024-04-25 04:41:39 +02:00

62 lines
1.4 KiB
Go

package collatz
import (
"collatz/parsing"
"fmt"
"math/big"
)
type Calculator struct {
parser parsing.Parser
three *big.Int
two *big.Int
one *big.Int
sequence Sequence
}
type Sequence struct {
Iterations int
Sequence []*big.Int
}
func NewCalculator(parser parsing.Parser) *Calculator {
r := &Calculator{
parser: parser,
three: big.NewInt(3),
two: big.NewInt(2),
one: big.NewInt(1),
}
return r
}
func (calc *Calculator) CalculateCollatz() (Sequence, error) {
number, err := calc.parser.Parse()
if err != nil {
return Sequence{}, fmt.Errorf("couldn't parse input: %w", err)
}
calc.sequence = Sequence{Iterations: 0}
calc.sequence.Sequence = append(calc.sequence.Sequence, new(big.Int).Set(number))
err = calc.calculateNextCollatzNumber(*number)
if err != nil {
return Sequence{}, err
}
return calc.sequence, nil
}
func (calc *Calculator) calculateNextCollatzNumber(in big.Int) error {
if in.Cmp(calc.one) < 0 {
return fmt.Errorf("must be greater than 0")
}
if in.Cmp(calc.one) == 0 {
return nil
}
var newNumber *big.Int
if new(big.Int).And(&in, calc.one).Cmp(calc.one) == 0 {
newNumber = new(big.Int).Add(new(big.Int).Mul(&in, calc.three), calc.one)
} else {
newNumber = new(big.Int).Div(&in, calc.two)
}
calc.sequence.Iterations++
calc.sequence.Sequence = append(calc.sequence.Sequence, newNumber)
return calc.calculateNextCollatzNumber(*newNumber)
}