Skip to content

Commit

Permalink
Complete graph problems
Browse files Browse the repository at this point in the history
  • Loading branch information
Abhijit Sarkar committed Jan 15, 2025
1 parent 9225dcb commit 8d6d635
Show file tree
Hide file tree
Showing 84 changed files with 1,281 additions and 398 deletions.
2 changes: 2 additions & 0 deletions .github/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ fi

if (( no_lint == 0 )); then
if [[ -z "${CI}" ]]; then
./mill modules[_].__.fix
./mill mill.scalalib.scalafmt.ScalafmtModule/reformatAll modules[_].__.sources
else
./mill modules[_].__.fix --check
./mill mill.scalalib.scalafmt.ScalafmtModule/checkFormatAll modules[_].__.sources
fi
fi
16 changes: 16 additions & 0 deletions .scalafix.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
rules = [
# semantic
ExplicitResultTypes
NoAutoTupling
OrganizeImports
RemoveUnused
# syntactic
DisableSyntax
LeakingImplicitClassVal
NoValInForComprehension
ProcedureSyntax
RedundantSyntax
]

ExplicitResultTypes.fetchScala3CompilerArtifactsOnVersionMismatch = true
OrganizeImports.targetDialect = Scala3
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,23 +152,23 @@ P73 (**) Lisp-like tree representation.

P80 (***) Conversions.

P81 (**) Path from one node to another one.
[P81](graph/src/P81.scala) (**) Path from one node to another one.

P82 (*) Cycle from a given node.
[P82](graph/src/P82.scala) (*) Cycle from a given node.

P83 (**) Construct all spanning trees.
[P83](graph/src/P83.scala) (**) Construct all spanning trees.

P84 (**) Construct the minimal spanning tree.
[P84](graph/src/P84.scala) (**) Construct the minimal spanning tree.

P85 (**) Graph isomorphism.
[P85](graph/src/P85.scala) (**) Graph isomorphism.

P86 (**) Node degree and graph coloration.
[P86](graph/src/P86.scala) (**) Node degree and graph coloration.

P87 (**) Depth-first order graph traversal.
[P87](graph/src/P87.scala) (**) Depth-first order graph traversal.

P88 (**) Connected components.
[P88](graph/src/P88.scala) (**) Connected components.

P89 (**) Bipartite graphs.
[P89](graph/src/P89.scala) (**) Bipartite graphs.

## Miscellaneous Problems

Expand Down
5 changes: 3 additions & 2 deletions arithmetic/src/P31.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package arithmetic

// P31 (**) Determine whether a given integer number is prime.
// scala> 7.isPrime
// res0: Boolean = true
//
// scala> 7.isPrime
// res0: Boolean = true

object P31:
def isPrime(n: Int): Boolean =
Expand Down
8 changes: 4 additions & 4 deletions arithmetic/src/P32.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package arithmetic

// P32 (**) Determine the greatest common divisor of two positive integer
// numbers.
// Use Euclid's algorithm.
// numbers.
// Use Euclid's algorithm.
//
// scala> gcd(36, 63)
// res0: Int = 9
// scala> gcd(36, 63)
// res0: Int = 9

object P32:
def gcd(x: Int, y: Int): Int =
Expand Down
6 changes: 3 additions & 3 deletions arithmetic/src/P33.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package arithmetic

// P33 (*) Determine whether two positive integer numbers are coprime.
// Two numbers are coprime if their greatest common divisor equals 1.
// Two numbers are coprime if their greatest common divisor equals 1.
//
// scala> 35.isCoprimeTo(64)
// res0: Boolean = true
// scala> 35.isCoprimeTo(64)
// res0: Boolean = true

object P33:
def isCoprime(x: Int, y: Int): Boolean =
Expand Down
10 changes: 5 additions & 5 deletions arithmetic/src/P34.scala
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
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.
// 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
// scala> 10.totient
// res0: Int = 4

object P34:
private val f = (x: Int) => 1 - 1 / x.toDouble
Expand Down
6 changes: 3 additions & 3 deletions arithmetic/src/P35.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package arithmetic

// P35 (**) Determine the prime factors of a given positive integer.
// Construct a flat list containing the prime factors in ascending order.
// Construct a flat list containing the prime factors in ascending order.
//
// scala> 315.primeFactors
// res0: List[Int] = List(3, 3, 5, 7)
// scala> 315.primeFactors
// res0: List[Int] = List(3, 3, 5, 7)

object P35:
private val primes = LazyList.iterate(2) { n =>
Expand Down
12 changes: 6 additions & 6 deletions arithmetic/src/P36.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package arithmetic

// P36 (**) Determine the prime factors of a given positive integer (2).
// Construct a list containing the prime factors and their multiplicity.
// Construct a list containing the prime factors and their multiplicity.
//
// scala> 315.primeFactorMultiplicity
// res0: List[(Int, Int)] = List((3,2), (5,1), (7,1))
// 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)
// 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] =
Expand Down
8 changes: 4 additions & 4 deletions arithmetic/src/P39.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ 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.
// 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)
// 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] =
Expand Down
16 changes: 8 additions & 8 deletions arithmetic/src/P40.scala
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
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.
// 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)
// scala> 28.goldbach
// res0: (Int, Int) = (5,23)

object P40:
// This implementation isn't very efficient because the primes are generated
Expand Down
38 changes: 19 additions & 19 deletions arithmetic/src/P41.scala
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
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.
// 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
// 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.
// 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
// 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
Expand Down
20 changes: 10 additions & 10 deletions bintree/src/P55.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ package bintree
import Tree.*

// P55 (**) Construct completely balanced binary trees.
// In a completely balanced binary tree, the following property holds for
// every node: The number of nodes in its left subtree and the number of
// nodes in its right subtree are almost equal, which means their difference
// is not greater than one.
// In a completely balanced binary tree, the following property holds for
// every node: The number of nodes in its left subtree and the number of
// nodes in its right subtree are almost equal, which means their difference
// is not greater than one.
//
// Define an object named Tree. Write a function Tree.cBalanced to
// construct completely balanced binary trees for a given number of nodes.
// The function should generate all solutions. The function should take as
// parameters the number of nodes and a single value to put in all of them.
// Define an object named Tree. Write a function Tree.cBalanced to
// construct completely balanced binary trees for a given number of nodes.
// The function should generate all solutions. The function should take as
// parameters the number of nodes and a single value to put in all of them.
//
// scala> Tree.cBalanced(4, "x")
// res0: List(Node[String]) = List(T(x T(x . .) T(x . T(x . .))), T(x T(x . .) T(x T(x . .) .)), ...
// scala> Tree.cBalanced(4, "x")
// res0: List(Node[String]) = List(T(x T(x . .) T(x . T(x . .))), T(x T(x . .) T(x T(x . .) .)), ...

object P55:
private def build[A](n: Int, x: A): List[(Tree[A], Int)] =
Expand Down
20 changes: 10 additions & 10 deletions bintree/src/P56.scala
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package bintree

import Tree.*
import Tree.{Empty, Node}

// P56 (**) Symmetric binary trees.
// Let us call a binary tree symmetric if you can draw a vertical line
// through the root node and then the right subtree is the mirror image of
// the left subtree. Add an isSymmetric method to the Tree class to check
// whether a given binary tree is symmetric. Hint: Write an isMirrorOf
// method first to check whether one tree is the mirror image of another.
// We are only interested in the structure, not in the contents of the
// nodes.
// Let us call a binary tree symmetric if you can draw a vertical line
// through the root node and then the right subtree is the mirror image of
// the left subtree. Add an isSymmetric method to the Tree class to check
// whether a given binary tree is symmetric. Hint: Write an isMirrorOf
// method first to check whether one tree is the mirror image of another.
// We are only interested in the structure, not in the contents of the
// nodes.
//
// scala> Node('a', Node('b'), Node('c')).isSymmetric
// res0: Boolean = true
// scala> Node('a', Node('b'), Node('c')).isSymmetric
// res0: Boolean = true

object P56:
private def isMirror[A](t1: Tree[A], t2: Tree[A]): Boolean =
Expand Down
44 changes: 22 additions & 22 deletions bintree/src/P57.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,37 @@ import Tree.*
import math.Ordered.orderingToOrdered

// P57 (**) Binary search trees (dictionaries).
// Write a function to add an element to a binary search tree.
// Write a function to add an element to a binary search tree.
//
// scala> End.addValue(2)
// res0: Node[Int] = T(2 . .)
// scala> End.addValue(2)
// res0: Node[Int] = T(2 . .)
//
// scala> res0.addValue(3)
// res1: Node[Int] = T(2 . T(3 . .))
// scala> res0.addValue(3)
// res1: Node[Int] = T(2 . T(3 . .))
//
// scala> res1.addValue(0)
// res2: Node[Int] = T(2 T(0 . .) T(3 . .))
// scala> res1.addValue(0)
// res2: Node[Int] = T(2 T(0 . .) T(3 . .))
//
// Hint: The abstract definition of addValue in Tree should be
// `def addValue[U >: T <% Ordered[U]](x: U): Tree[U]`. The `>: T` is
// because addValue's parameters need to be _contravariant_ in T.
// (Conceptually, we're adding nodes above existing nodes. In order for the
// subnodes to be of type T or any subtype, the upper nodes must be of type
// T or any supertype.) The `<% Ordered[U]` allows us to use the < operator
// on the values in the tree.
// Hint: The abstract definition of addValue in Tree should be
// `def addValue[U >: T <% Ordered[U]](x: U): Tree[U]`. The `>: T` is
// because addValue's parameters need to be _contravariant_ in T.
// (Conceptually, we're adding nodes above existing nodes. In order for the
// subnodes to be of type T or any subtype, the upper nodes must be of type
// T or any supertype.) The `<% Ordered[U]` allows us to use the < operator
// on the values in the tree.
//
// Use that function to construct a binary tree from a list of integers.
// Use that function to construct a binary tree from a list of integers.
//
// scala> Tree.fromList(List(3, 2, 5, 7, 1))
// res3: Node[Int] = T(3 T(2 T(1 . .) .) T(5 . T(7 . .)))
// scala> Tree.fromList(List(3, 2, 5, 7, 1))
// res3: Node[Int] = T(3 T(2 T(1 . .) .) T(5 . T(7 . .)))
//
// Finally, use that function to test your solution to P56.
// Finally, use that function to test your solution to P56.
//
// scala> Tree.fromList(List(5, 3, 18, 1, 4, 12, 21)).isSymmetric
// res4: Boolean = true
// scala> Tree.fromList(List(5, 3, 18, 1, 4, 12, 21)).isSymmetric
// res4: Boolean = true
//
// scala> Tree.fromList(List(3, 2, 5, 7, 4)).isSymmetric
// res5: Boolean = false
// scala> Tree.fromList(List(3, 2, 5, 7, 4)).isSymmetric
// res5: Boolean = false

object P57:
extension [A](t: Tree[A])
Expand Down
10 changes: 5 additions & 5 deletions bintree/src/P58.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package bintree

import P56.*
import P56.isSymmetric

// P58 (**) Generate-and-test paradigm.
// Apply the generate-and-test paradigm to construct all symmetric,
// completely balanced binary trees with a given number of nodes.
// Apply the generate-and-test paradigm to construct all symmetric,
// completely balanced binary trees with a given number of nodes.
//
// scala> Tree.symmetricBalancedTrees(5, "x")
// res0: List[Node[String]] = List(T(x T(x . T(x . .)) T(x T(x . .) .)), T(x T(x T(x . .) .) T(x . T(x . .))))
// scala> Tree.symmetricBalancedTrees(5, "x")
// res0: List[Node[String]] = List(T(x T(x . T(x . .)) T(x T(x . .) .)), T(x T(x T(x . .) .) T(x . T(x . .))))

object P58:
def symmetricBalancedTrees[A](n: Int, x: A): List[Tree[A]] =
Expand Down
Loading

0 comments on commit 8d6d635

Please sign in to comment.