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) }