Skip to content

Commit

Permalink
feat(tricks): primitive roots
Browse files Browse the repository at this point in the history
Signed-off-by: Pouyan Heyratpour <[email protected]>
  • Loading branch information
pouyanh committed Dec 4, 2024
1 parent 0637bd8 commit 0d48803
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 23 deletions.
53 changes: 41 additions & 12 deletions tricks/mathx/arithmetic.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,26 @@ func PrimeFactors(n int) []int {
return ff[:len(ff):len(ff)]
}

// NextPrime returns next prime number greater than the given number (n)
func NextPrime(n int) int {
if n < 1 {
n = 1
}

return nextPrime(n)
}

// nextPrime returns next prime number greater than the given number (n)
func nextPrime(n int) int {
for {
n++

if IsPrime(n) {
return n
}
}
}

// CoprimesInRange returns list of all natural numbers in closed range [from, to]
// which are coprime to the given number (n)
func CoprimesInRange(n, from, to int) []int {
Expand All @@ -76,22 +96,31 @@ func MinorCoprimes(n int) []int {
return CoprimesInRange(n, 1, n-1)
}

// NextPrime returns next prime number greater than the given number (n)
func NextPrime(n int) int {
if n < 1 {
n = 1
// PrimitiveRoots returns list of all natural numbers which are less than the given number (n) and
// primitive root modulo (n)
func PrimitiveRoots(n int) map[int][]int {
cpp := CoprimesInRange(n, 2, n-1)
if len(cpp) == 0 {
return map[int][]int{1: {1}}
}

return nextPrime(n)
}
prr := make(map[int][]int)
for _, cp := range cpp {
mm := make([]int, 0, len(cpp)+1)
m := 1
for i := 1; i < n; i++ {
m = (m * cp) % n
mm = append(mm, m)

// nextPrime returns next prime number greater than the given number (n)
func nextPrime(n int) int {
for {
n++
if m == 1 {
break
}
}

if IsPrime(n) {
return n
if len(mm) == len(cpp)+1 {
prr[cp] = mm[:len(mm):len(mm)]
}
}

return prr
}
60 changes: 49 additions & 11 deletions tricks/mathx/arithmetic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func TestIsPrime(t *testing.T) {
assert.False(t, mathx.IsPrime(-7))
}

func TestPrimes(t *testing.T) {
func TestPrimeFactors(t *testing.T) {
assert.Equal(t, []int{2, 3}, mathx.PrimeFactors(6))
assert.Equal(t, []int{2, 5}, mathx.PrimeFactors(10))
assert.Equal(t, []int{2, 3, 5}, mathx.PrimeFactors(30))
Expand Down Expand Up @@ -162,16 +162,6 @@ func TestPrimes(t *testing.T) {
assert.Equal(t, []int{}, mathx.PrimeFactors(-127))
}

func TestCoprimesInRange(t *testing.T) {
assert.Equal(t, []int{3, 7}, mathx.CoprimesInRange(10, 2, 7))
assert.Equal(t, []int{7, 9, 11, 13, 17, 19}, mathx.CoprimesInRange(10, 5, 20))
}

func TestMinorCoprimes(t *testing.T) {
assert.Equal(t, []int{1, 5}, mathx.MinorCoprimes(6))
assert.Equal(t, []int{1, 3, 7, 9}, mathx.MinorCoprimes(10))
}

func TestNextPrime(t *testing.T) {
assert.Equal(t, 2, mathx.NextPrime(0))
assert.Equal(t, 2, mathx.NextPrime(1))
Expand All @@ -188,3 +178,51 @@ func TestNextPrime(t *testing.T) {
assert.Equal(t, 2, mathx.NextPrime(-5))
assert.Equal(t, 2, mathx.NextPrime(-100))
}

func TestCoprimesInRange(t *testing.T) {
assert.Equal(t, []int{3, 7}, mathx.CoprimesInRange(10, 2, 7))
assert.Equal(t, []int{7, 9, 11, 13, 17, 19}, mathx.CoprimesInRange(10, 5, 20))
}

func TestMinorCoprimes(t *testing.T) {
assert.Equal(t, []int{1, 5}, mathx.MinorCoprimes(6))
assert.Equal(t, []int{1, 3, 7, 9}, mathx.MinorCoprimes(10))
}

func TestPrimitiveRoots(t *testing.T) {
assert.Equal(t, map[int][]int{
1: {1},
}, mathx.PrimitiveRoots(2))

assert.Equal(t, map[int][]int{
2: {2, 1},
}, mathx.PrimitiveRoots(3))

assert.Equal(t, map[int][]int{
3: {3, 2, 6, 4, 5, 1},
5: {5, 4, 6, 2, 3, 1},
}, mathx.PrimitiveRoots(7))

assert.Equal(t, map[int][]int{
3: {3, 9, 7, 1},
7: {7, 9, 3, 1},
}, mathx.PrimitiveRoots(10))

assert.Equal(t, map[int][]int{
3: {3, 9, 10, 13, 5, 15, 11, 16, 14, 8, 7, 4, 12, 2, 6, 1},
5: {5, 8, 6, 13, 14, 2, 10, 16, 12, 9, 11, 4, 3, 15, 7, 1},
6: {6, 2, 12, 4, 7, 8, 14, 16, 11, 15, 5, 13, 10, 9, 3, 1},
7: {7, 15, 3, 4, 11, 9, 12, 16, 10, 2, 14, 13, 6, 8, 5, 1},
10: {10, 15, 14, 4, 6, 9, 5, 16, 7, 2, 3, 13, 11, 8, 12, 1},
11: {11, 2, 5, 4, 10, 8, 3, 16, 6, 15, 12, 13, 7, 9, 14, 1},
12: {12, 8, 11, 13, 3, 2, 7, 16, 5, 9, 6, 4, 14, 15, 10, 1},
14: {14, 9, 7, 13, 12, 15, 6, 16, 3, 8, 10, 4, 5, 2, 11, 1},
}, mathx.PrimitiveRoots(17))

prr49 := mathx.PrimitiveRoots(49)
for _, pra := range prr49 {
for _, prb := range prr49 {
assert.ElementsMatch(t, pra, prb)
}
}
}

0 comments on commit 0d48803

Please sign in to comment.