Skip to content

Commit

Permalink
feat: added perfect numnber serach implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
aholbreich committed May 22, 2024
1 parent cb41ace commit c704a9d
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 0 deletions.
20 changes: 20 additions & 0 deletions numbers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package go_kata

import "math/big"

// shifts the integer n to the left by i bits.
func ShiftLeft(n int, i uint) int {
return n << i
}

// shifts the big integer n to the left by i bits.
func ShiftLeftBig(n uint, i uint) big.Int {
var res = big.NewInt(1)
return *res.Lsh(big.NewInt(int64(n)), uint(i))
}

// shifts the big integer n to the left by 1 bit.
func ShiftLeftMultBy2(n uint) big.Int {
var res = big.NewInt(1)
return *res.Lsh(big.NewInt(int64(n)), uint(1))
}
77 changes: 77 additions & 0 deletions numbers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// FILEPATH: /home/aho/git/go_katas/numbers_test.go

package go_kata

import (
"testing"
)

func TestShiftLeft(t *testing.T) {
testCases := []struct {
n int
i uint
expected int
}{
{2, 1, 4},
{3, 1, 6},
{2, 2, 8},
{5, 2, 20},
{10, 3, 80},
{0, 25, 0},
{1024, 1, 2048},
{-5, 1, -10},
}

for _, testCases := range testCases {
result := ShiftLeft(testCases.n, testCases.i)
if result != testCases.expected {
t.Errorf("shiftLeft(%d, %d) = %d, expected %d", testCases.n, testCases.i, result, testCases.expected)
}
}
}

func TestShiftLeftBig(t *testing.T) {
testCases := []struct {
n uint
i uint
expected int
}{
{2, 1, 4},
{3, 1, 6},
{2, 2, 8},
{5, 2, 20},
{10, 3, 80},
{0, 25, 0},
{1024, 1, 2048},
{1, 10, 1024},
}

for _, testCases := range testCases {
result := ShiftLeftBig(testCases.n, testCases.i)
if result.Int64() != int64(testCases.expected) {
t.Errorf("shiftLeftBig(%d, %d) = %d, expected %d", testCases.n, testCases.i, result.Uint64(), testCases.expected)
}
}
}

func TestShiftLeftPow2(t *testing.T) {

testCases := []struct {
n uint
expected int
}{
{2, 4},
{3, 6},
{5, 10},
{10, 20},
{0, 0},
{1024, 2048},
}

for _, testCases := range testCases {
result := ShiftLeftMultBy2(testCases.n)
if result.Int64() != int64(testCases.expected) {
t.Errorf("shiftLeftBig(%d) = %d, expected %d", testCases.n, result.Uint64(), testCases.expected)
}
}
}
58 changes: 58 additions & 0 deletions perfectnumber.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package go_kata

import (
"math/big"
)

func isPerfectNumber(num int) bool {
sum := 0
for i := 1; i < num; i++ {
if num%i == 0 {
sum += i
}
}
return sum == num
}

func FindPerfectNumbers(n int) []int {
perfectNumbers := []int{}
num := 1
for len(perfectNumbers) < n {
if isPerfectNumber(num) {
perfectNumbers = append(perfectNumbers, num)
}
num++
}
return perfectNumbers
}

func FindPerfectNumbersEfficient(n int) []*big.Int {

var perfectNumbers = make([]*big.Int, n)
count := 0

var bigInt = new(big.Int)
var base = big.NewInt(2)

for i := 2; count < n; i++ {

if !big.NewInt(int64(i)).ProbablyPrime(20) {
continue
}

var e = big.NewInt(int64(i))
var mersennePrime = bigInt.Exp(base, e, nil)
mersennePrime = bigInt.Sub(mersennePrime, big.NewInt(1))

if mersennePrime.ProbablyPrime(20) {

e = big.NewInt(int64(i - 1))
mersennePrime2 := new(big.Int).Exp(base, e, nil)

perfectNumbers[count] = new(big.Int).Mul(mersennePrime, mersennePrime2)
count++
}
}

return perfectNumbers
}
34 changes: 34 additions & 0 deletions perfectnumber_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// FILEPATH: /home/aho/git/go_katas/perfectnumber_test.go

package go_kata

import (
"math/big"
"reflect"
"testing"
)

func TestFindPerfectNumbers(t *testing.T) {

result := FindPerfectNumbers(4)
expected := []int{6, 28, 496, 8128}
if !reflect.DeepEqual(result, expected) {
t.Errorf("findPerfectNumbers(%d) = %v, expected %v", 1, result, expected)
}

}

func TestFindPerfectNumbersEfficient(t *testing.T) {

result := FindPerfectNumbersEfficient(5)
expected := []*big.Int{
big.NewInt(6),
big.NewInt(28),
big.NewInt(496),
big.NewInt(8128),
big.NewInt(33550336),
}
if !reflect.DeepEqual(result, expected) {
t.Errorf("findPerfectNumbers(%d) = %v, expected %v", 1, result, expected)
}
}
9 changes: 9 additions & 0 deletions prime.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,12 @@ func IsPrimeWithMathLib(n int) bool {
bigN := big.NewInt(int64(n))
return bigN.ProbablyPrime(0)
}

// Returns the next prime number that is greater than n.
func GetPrimeThatIsGreaterThan(n int) int {
for i := n + 1; ; i++ {
if IsPrime(i) {
return i
}
}
}
27 changes: 27 additions & 0 deletions prime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,30 @@ func TestIsPrime(t *testing.T) {
func TestIsPrimeUsingMathLib(t *testing.T) {
runIsPrimeTests(t, IsPrimeWithMathLib)
}

func TestGetPrimeThatIsGreaterThan(t *testing.T) {
tests := []struct {
input int
expected int
}{
{0, 2},
{1, 2},
{2, 3},
{3, 5},
{4, 5},
{5, 7},
{7, 11},
{8, 11},
{71, 73},
{941, 947},
{1000, 1009},
{7919, 7927},
{1000000000000000000, 1000000000000000003},
}
for _, test := range tests {
result := GetPrimeThatIsGreaterThan(test.input)
if result != test.expected {
t.Errorf("GetPrimeThatIsGreaterThan(%d) = %d; want %d", test.input, result, test.expected)
}
}
}

0 comments on commit c704a9d

Please sign in to comment.