gocollatz/collatz/calculator.go

62 lines
1.4 KiB
Go
Raw Permalink Normal View History

2024-04-24 17:49:03 +00:00
package collatz
import (
2024-04-24 20:04:34 +00:00
"collatz/parsing"
2024-04-24 17:49:03 +00:00
"fmt"
"math/big"
)
type Calculator struct {
2024-04-25 02:41:39 +00:00
parser parsing.Parser
three *big.Int
two *big.Int
one *big.Int
sequence Sequence
}
type Sequence struct {
Iterations int
Sequence []*big.Int
2024-04-24 17:49:03 +00:00
}
2024-04-24 20:04:34 +00:00
func NewCalculator(parser parsing.Parser) *Calculator {
r := &Calculator{
2024-04-25 02:41:39 +00:00
parser: parser,
three: big.NewInt(3),
two: big.NewInt(2),
one: big.NewInt(1),
2024-04-24 17:49:03 +00:00
}
return r
}
2024-04-25 02:41:39 +00:00
func (calc *Calculator) CalculateCollatz() (Sequence, error) {
number, err := calc.parser.Parse()
2024-04-24 17:49:03 +00:00
if err != nil {
2024-04-25 02:41:39 +00:00
return Sequence{}, fmt.Errorf("couldn't parse input: %w", err)
2024-04-24 17:49:03 +00:00
}
2024-04-25 02:41:39 +00:00
calc.sequence = Sequence{Iterations: 0}
calc.sequence.Sequence = append(calc.sequence.Sequence, new(big.Int).Set(number))
err = calc.calculateNextCollatzNumber(*number)
2024-04-24 20:04:34 +00:00
if err != nil {
2024-04-25 02:41:39 +00:00
return Sequence{}, err
2024-04-24 20:04:34 +00:00
}
2024-04-25 02:41:39 +00:00
return calc.sequence, nil
2024-04-24 17:49:03 +00:00
}
2024-04-25 02:41:39 +00:00
func (calc *Calculator) calculateNextCollatzNumber(in big.Int) error {
if in.Cmp(calc.one) < 0 {
2024-04-24 20:04:34 +00:00
return fmt.Errorf("must be greater than 0")
2024-04-24 17:49:03 +00:00
}
2024-04-25 02:41:39 +00:00
if in.Cmp(calc.one) == 0 {
2024-04-24 20:04:34 +00:00
return nil
2024-04-24 17:49:03 +00:00
}
var newNumber *big.Int
2024-04-25 02:41:39 +00:00
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)
2024-04-24 17:49:03 +00:00
} else {
2024-04-25 02:41:39 +00:00
newNumber = new(big.Int).Div(&in, calc.two)
2024-04-24 17:49:03 +00:00
}
2024-04-25 02:41:39 +00:00
calc.sequence.Iterations++
calc.sequence.Sequence = append(calc.sequence.Sequence, newNumber)
return calc.calculateNextCollatzNumber(*newNumber)
2024-04-24 17:49:03 +00:00
}