This commit is contained in:
		
							parent
							
								
									c73fa4e72b
								
							
						
					
					
						commit
						99eeeedc65
					
				
							
								
								
									
										22
									
								
								.github/workflows/run_tests.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								.github/workflows/run_tests.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
name: Run Tests
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches: [ main ]
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches: [ main ]
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  test:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Check out code
 | 
			
		||||
        uses: actions/checkout@v2
 | 
			
		||||
 | 
			
		||||
      - name: Set up Go
 | 
			
		||||
        uses: actions/setup-go@v2
 | 
			
		||||
        with:
 | 
			
		||||
          go-version: '^1.22.1'
 | 
			
		||||
 | 
			
		||||
      - name: Run tests
 | 
			
		||||
        run: go test ./...
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
.idea
 | 
			
		||||
							
								
								
									
										1
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								README
									
									
									
									
									
								
							@ -1 +0,0 @@
 | 
			
		||||
Run with `go run collatz.go 1234` or download the exe and pass a number `collatz 1234`.
 | 
			
		||||
							
								
								
									
										1
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
Run with `go run collatz.go 1234` or download the executable and pass a number `collatz 1234`.
 | 
			
		||||
							
								
								
									
										10
									
								
								collatz.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								collatz.go
									
									
									
									
									
								
							@ -2,10 +2,14 @@ package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"collatz/collatz"
 | 
			
		||||
	"collatz/io"
 | 
			
		||||
	"collatz/parsing"
 | 
			
		||||
	"log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	calculator := collatz.NewCalculator(new(io.Cliargs))
 | 
			
		||||
	calculator.Collatz()
 | 
			
		||||
	calculator := collatz.NewCalculator(new(parsing.Cliargs))
 | 
			
		||||
	err := calculator.CalculateCollatz()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatalf("Error calculating Collatz: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,53 +1,59 @@
 | 
			
		||||
package collatz
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"collatz/io"
 | 
			
		||||
	"collatz/parsing"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"math/big"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Calculator struct {
 | 
			
		||||
	parser *io.Cliargs
 | 
			
		||||
	three  *big.Int
 | 
			
		||||
	two    *big.Int
 | 
			
		||||
	one    *big.Int
 | 
			
		||||
	parser     parsing.Parser
 | 
			
		||||
	three      *big.Int
 | 
			
		||||
	two        *big.Int
 | 
			
		||||
	one        *big.Int
 | 
			
		||||
	iterations 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),
 | 
			
		||||
func NewCalculator(parser parsing.Parser) *Calculator {
 | 
			
		||||
	r := &Calculator{
 | 
			
		||||
		parser:     parser,
 | 
			
		||||
		three:      big.NewInt(3),
 | 
			
		||||
		two:        big.NewInt(2),
 | 
			
		||||
		one:        big.NewInt(1),
 | 
			
		||||
		iterations: 0,
 | 
			
		||||
	}
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o Calculator) Collatz() {
 | 
			
		||||
func (o *Calculator) CalculateCollatz() error {
 | 
			
		||||
	number, err := o.parser.Parse()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Panicf("Couldn't parse input: %s\n", err)
 | 
			
		||||
		return fmt.Errorf("couldn't parse input: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Print(number.Text(10))
 | 
			
		||||
	o.nextNumber(number)
 | 
			
		||||
	err = o.nextNumber(*number)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Println()
 | 
			
		||||
	fmt.Println("Iterations:", o.iterations)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o Calculator) nextNumber(in *big.Int) {
 | 
			
		||||
func (o *Calculator) nextNumber(in big.Int) error {
 | 
			
		||||
	if in.Cmp(o.one) < 0 {
 | 
			
		||||
		log.Panicln("Must be greater than 0")
 | 
			
		||||
		return fmt.Errorf("must be greater than 0")
 | 
			
		||||
	}
 | 
			
		||||
	if in.Cmp(o.one) == 0 {
 | 
			
		||||
		return
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	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)
 | 
			
		||||
	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)
 | 
			
		||||
		newNumber = new(big.Int).Div(&in, o.two)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	o.iterations++
 | 
			
		||||
	fmt.Printf(" -> %s", newNumber.Text(10))
 | 
			
		||||
	o.nextNumber(newNumber)
 | 
			
		||||
	return o.nextNumber(*newNumber)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								collatz/calculator_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								collatz/calculator_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
package collatz
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math/big"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type MockParser struct {
 | 
			
		||||
	value *big.Int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MockParser) Parse() (*big.Int, error) {
 | 
			
		||||
	return m.value, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNewCalculator(t *testing.T) {
 | 
			
		||||
	parser := &MockParser{}
 | 
			
		||||
	calculator := NewCalculator(parser)
 | 
			
		||||
 | 
			
		||||
	if calculator.parser != parser {
 | 
			
		||||
		t.Errorf("Expected parser to be %v, got %v", parser, calculator.parser)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if calculator.one.Cmp(big.NewInt(1)) != 0 {
 | 
			
		||||
		t.Errorf("Expected one to be 1, got %v", calculator.one)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if calculator.two.Cmp(big.NewInt(2)) != 0 {
 | 
			
		||||
		t.Errorf("Expected two to be 2, got %v", calculator.two)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if calculator.three.Cmp(big.NewInt(3)) != 0 {
 | 
			
		||||
		t.Errorf("Expected three to be 3, got %v", calculator.three)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCalculateCollatz(t *testing.T) {
 | 
			
		||||
	parser := &MockParser{value: big.NewInt(6)}
 | 
			
		||||
	calculator := NewCalculator(parser)
 | 
			
		||||
 | 
			
		||||
	err := calculator.CalculateCollatz()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Expected no error, got %v", err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
package io
 | 
			
		||||
package parsing
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
							
								
								
									
										44
									
								
								parsing/cliargs_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								parsing/cliargs_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
package parsing
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math/big"
 | 
			
		||||
	"os"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestCliargs_Parse(t *testing.T) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name    string
 | 
			
		||||
		args    []string
 | 
			
		||||
		want    *big.Int
 | 
			
		||||
		wantErr bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name:    "Test with valid integer",
 | 
			
		||||
			args:    []string{"", "10"}, // the first argument is the program name
 | 
			
		||||
			want:    big.NewInt(10),
 | 
			
		||||
			wantErr: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:    "Test with non-integer",
 | 
			
		||||
			args:    []string{"", "abc"}, // the first argument is the program name
 | 
			
		||||
			want:    nil,
 | 
			
		||||
			wantErr: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			os.Args = tt.args
 | 
			
		||||
			parser := &Cliargs{}
 | 
			
		||||
			got, err := parser.Parse()
 | 
			
		||||
			if (err != nil) != tt.wantErr {
 | 
			
		||||
				t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			if !tt.wantErr && got.Cmp(tt.want) != 0 {
 | 
			
		||||
				t.Errorf("Parse() = %v, want %v", got, tt.want)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								parsing/interface.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								parsing/interface.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
package parsing
 | 
			
		||||
 | 
			
		||||
import "math/big"
 | 
			
		||||
 | 
			
		||||
type Parser interface {
 | 
			
		||||
	Parse() (*big.Int, error)
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user