-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Abhijit Sarkar
committed
Jan 5, 2024
1 parent
de0e1f3
commit be445d0
Showing
20 changed files
with
322 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package arithmetic | ||
|
||
// P31 (**) Determine whether a given integer number is prime. | ||
// scala> 7.isPrime | ||
// res0: Boolean = true | ||
|
||
object P31: | ||
def isPrime(n: Int): Boolean = | ||
if n == 2 || n == 3 | ||
then true | ||
else if n <= 1 || (n % 2) == 0 || (n % 3) == 0 | ||
then false | ||
else | ||
val i = Math.sqrt(n.toDouble).toInt | ||
val prime = (j: Int) => (n % j) != 0 && (n % (j + 2)) != 0 | ||
(5 to i).forall(prime) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package arithmetic | ||
|
||
// P32 (**) Determine the greatest common divisor of two positive integer | ||
// numbers. | ||
// Use Euclid's algorithm. | ||
// | ||
// scala> gcd(36, 63) | ||
// res0: Int = 9 | ||
|
||
object P32: | ||
def gcd(x: Int, y: Int): Int = | ||
if y == 0 | ||
then x | ||
else if x < y | ||
then gcd(y, x) | ||
else gcd(y, x % y) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package arithmetic | ||
|
||
// P33 (*) Determine whether two positive integer numbers are coprime. | ||
// Two numbers are coprime if their greatest common divisor equals 1. | ||
// | ||
// scala> 35.isCoprimeTo(64) | ||
// res0: Boolean = true | ||
|
||
object P33: | ||
def isCoprime(x: Int, y: Int): Boolean = | ||
P32.gcd(x, y) == 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package arithmetic | ||
|
||
// P34 (**) Calculate Euler's totient function phi(m). | ||
// Euler's so-called totient function phi(m) is defined as the number of | ||
// positive integers r (1 <= r < m) that are coprime to m. As a special | ||
// case, phi(1) is defined to be 1. | ||
// | ||
// scala> 10.totient | ||
// res0: Int = 4 | ||
|
||
object P34: | ||
private val f = (x: Int) => 1 - 1 / x.toDouble | ||
|
||
def totient(x: Int): Int = | ||
val y = P35 | ||
.primeFactors(x) | ||
.map(f) | ||
.foldLeft(1.0d)(_ * _) | ||
|
||
(x * y).toInt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package arithmetic | ||
|
||
// P35 (**) Determine the prime factors of a given positive integer. | ||
// Construct a flat list containing the prime factors in ascending order. | ||
// | ||
// scala> 315.primeFactors | ||
// res0: List[Int] = List(3, 3, 5, 7) | ||
|
||
object P35: | ||
private val primes = LazyList.iterate(2) { n => | ||
Iterator | ||
.from(n + 1) | ||
.dropWhile(!P31.isPrime(_)) | ||
.next() | ||
} | ||
|
||
private def primeFactors(ll: LazyList[Int], x: Int): List[Int] = | ||
if x <= 1 | ||
then Nil | ||
else | ||
val k = ll.head | ||
if x > 1 && x % k == 0 | ||
then k :: primeFactors(ll, x / k) | ||
else primeFactors(ll.tail, x) | ||
|
||
def primeFactors(x: Int): List[Int] = primeFactors(primes, x) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package arithmetic | ||
|
||
// P36 (**) Determine the prime factors of a given positive integer (2). | ||
// Construct a list containing the prime factors and their multiplicity. | ||
// | ||
// scala> 315.primeFactorMultiplicity | ||
// res0: List[(Int, Int)] = List((3,2), (5,1), (7,1)) | ||
// | ||
// Alternately, use a Map for the result. | ||
// scala> 315.primeFactorMultiplicity | ||
// res0: Map[Int,Int] = Map(3 -> 2, 5 -> 1, 7 -> 1) | ||
|
||
object P36: | ||
def primeFactorMultiplicity(x: Int): Map[Int, Int] = | ||
P35 | ||
.primeFactors(x) | ||
.groupBy(identity) | ||
.map((k, v) => (k, v.length)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package arithmetic | ||
|
||
import math.Integral.Implicits.infixIntegralOps | ||
|
||
// P39 (*) A list of prime numbers. | ||
// Given a range of integers by its lower and upper limit, construct a list | ||
// of all prime numbers in that range. | ||
// | ||
// scala> listPrimesinRange(7 to 31) | ||
// res0: List[Int] = List(7, 11, 13, 17, 19, 23, 29, 31) | ||
|
||
object P39: | ||
def primesInRng(a: Int, b: Int): List[Int] = | ||
val o = 3.max(a + (if a % 2 == 0 then 1 else 0)) | ||
val r = Math.sqrt(b.toDouble + 1).toInt | ||
val composites = | ||
(for | ||
p <- (3 to r by 2) | ||
q = p * p | ||
s = 2 * p | ||
(n, x) = (o - q) /% s | ||
q2 = | ||
if o <= q | ||
then q | ||
else q + (n + x.sign) * s | ||
i <- q2 to b by s | ||
yield i).toSet | ||
|
||
val xs = (o to b by 2).filterNot(composites.contains).toList | ||
if a < 3 | ||
then 2 :: xs | ||
else xs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package arithmetic | ||
|
||
// P40 (**) Goldbach's conjecture. | ||
// Goldbach's conjecture says that every positive even number greater than 2 | ||
// is the sum of two prime numbers. E.g. 28 = 5 + 23. It is one of the | ||
// most famous facts in number theory that has not been proved to be correct | ||
// in the general case. It has been numerically confirmed up to very large | ||
// numbers (much larger than Scala's Int can represent). Write a function | ||
// to find the two prime numbers that sum up to a given even integer. | ||
// | ||
// scala> 28.goldbach | ||
// res0: (Int, Int) = (5,23) | ||
|
||
object P40: | ||
// This implementation isn't very efficient because the primes are generated | ||
// eagerly. It works much better in Haskell where list is lazy. | ||
def goldbach(n: Int): (Int, Int) = | ||
P39 | ||
.primesInRng(2, n - 2) | ||
.collect: | ||
case x if P31.isPrime(n - x) => (x, n - x) | ||
.head |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package arithmetic | ||
|
||
// P41 (**) A list of Goldbach compositions. | ||
// Given a range of integers by its lower and upper limit, print a list of | ||
// all even numbers and their Goldbach composition. | ||
// | ||
// scala> printGoldbachList(9 to 20) | ||
// 10 = 3 + 7 | ||
// 12 = 5 + 7 | ||
// 14 = 3 + 11 | ||
// 16 = 3 + 13 | ||
// 18 = 5 + 13 | ||
// 20 = 3 + 17 | ||
// | ||
// In most cases, if an even number is written as the sum of two prime | ||
// numbers, one of them is very small. Very rarely, the primes are both | ||
// bigger than, say, 50. Try to find out how many such cases there are in | ||
// the range 2..3000. | ||
// | ||
// Example (minimum value of 50 for the primes): | ||
// scala> printGoldbachListLimited(1 to 2000, 50) | ||
// 992 = 73 + 919 | ||
// 1382 = 61 + 1321 | ||
// 1856 = 67 + 1789 | ||
// 1928 = 61 + 1867 | ||
|
||
object P41: | ||
// This implementation isn't very efficient because the primes are generated | ||
// eagerly. It works much better in Haskell where list is lazy. | ||
def goldbachList(a: Int, b: Int): Map[Int, (Int, Int)] = | ||
(a to b) | ||
.collect: | ||
case x if x % 2 == 0 => (x, P40.goldbach(x)) | ||
.toMap |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package arithmetic | ||
|
||
import munit.FunSuite | ||
|
||
class P31Suite extends FunSuite: | ||
|
||
test("determine whether a given integer is prime"): | ||
val data = List( | ||
(1, false), | ||
(2, true), | ||
(3, true), | ||
(4, false), | ||
(5, true), | ||
(6, false), | ||
(7, true), | ||
(11, true) | ||
) | ||
data.foreach { (n, prime) => | ||
assertEquals(P31.isPrime(n), prime, s"n=${n}") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package arithmetic | ||
|
||
import munit.FunSuite | ||
|
||
class P32Suite extends FunSuite: | ||
|
||
test("determine the greatest common divisor of two positive integers"): | ||
assertEquals(P32.gcd(36, 63), 9) | ||
assertEquals(P32.gcd(63, 36), 9) | ||
assertEquals(P32.gcd(125, 81), 1) | ||
assertEquals(P32.gcd(221, 559), 13) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package arithmetic | ||
|
||
import munit.FunSuite | ||
|
||
class P33Suite extends FunSuite: | ||
|
||
test("determine whether two positive integer numbers are coprime"): | ||
assertEquals(P33.isCoprime(35, 64), true) | ||
assertEquals(P33.isCoprime(1173, 1547), false) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package arithmetic | ||
|
||
import munit.FunSuite | ||
|
||
class P34Suite extends FunSuite: | ||
|
||
test("calculate Euler's totient function phi"): | ||
assertEquals(P34.totient(10), 4) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package arithmetic | ||
|
||
import munit.FunSuite | ||
|
||
class P35Suite extends FunSuite: | ||
|
||
test("determine the prime factors of a given positive integer"): | ||
val data = List( | ||
(1, Nil), | ||
(2, List(2)), | ||
(9, List(3, 3)), | ||
(8, List(2, 2, 2)), | ||
(12, List(2, 2, 3)), | ||
(315, List(3, 3, 5, 7)), | ||
(901255, List(5, 17, 23, 461)) | ||
) | ||
data.foreach { (n, pf) => | ||
assertEquals(P35.primeFactors(n), pf) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package arithmetic | ||
|
||
import munit.FunSuite | ||
|
||
class P36Suite extends FunSuite: | ||
|
||
test("construct a list containing the prime factors and their multiplicity for a given integer"): | ||
assertEquals(P36.primeFactorMultiplicity(315), Map(3 -> 2, 5 -> 1, 7 -> 1)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package arithmetic | ||
|
||
import munit.FunSuite | ||
|
||
class P39Suite extends FunSuite: | ||
|
||
test("construct a list of all prime numbers within a given range"): | ||
val obtained = P39.primesInRng(7, 31) | ||
val expected = List(7, 11, 13, 17, 19, 23, 29, 31) | ||
assertEquals(obtained, expected) | ||
|
||
val obtained1 = P39.primesInRng(10, 20) | ||
val expected1 = List(11, 13, 17, 19) | ||
assertEquals(obtained1, expected1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package arithmetic | ||
|
||
import munit.FunSuite | ||
|
||
class P40Suite extends FunSuite: | ||
|
||
test("find the two prime numbers that sum up to a given even integer"): | ||
val obtained = P40.goldbach(28) | ||
val expected = (5, 23) | ||
assertEquals(obtained, expected) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package arithmetic | ||
|
||
import munit.FunSuite | ||
|
||
class P41Suite extends FunSuite: | ||
|
||
test("find the Goldbach compositions of all even numbers within a given range"): | ||
val obtained = P41.goldbachList(9, 20) | ||
val expected = Map( | ||
10 -> (3, 7), | ||
12 -> (5, 7), | ||
14 -> (3, 11), | ||
16 -> (3, 13), | ||
18 -> (5, 13), | ||
20 -> (3, 17) | ||
) | ||
assertEquals(obtained, expected) |