Commit c7b5e7ea authored by Jim Newton's avatar Jim Newton

initial files

parents
.idea/*
target/
src/main/scala/hwSolution
*~
name := "scalain-e-course-code"
version := "0.1"
scalaVersion := "2.12.8"
libraryDependencies += "junit" % "junit" % "4.10" % "test"
libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.5"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % "test"
libraryDependencies += "org.scala-lang.plugins" %% "scala-continuations-library" % "1.0.3"
libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.14.0" % "test"
libraryDependencies += "org.scalafx" %% "scalafx" % "8.0.144-R12"
// added the following lines as per advice from
// https://stackoverflow.com/questions/57628274/sbt-wont-compile-helloworld-scalafx-example-complains-about-javafx-missing-fro/57628433#57628433
// begin
lazy val osName = System.getProperty("os.name") match {
case n if n.startsWith("Linux") => "linux"
case n if n.startsWith("Mac") => "mac"
case n if n.startsWith("Windows") => "win"
case _ => throw new Exception("Unknown platform!")
}
// Add JavaFX dependencies
lazy val javaFXModules = Seq("base", "controls", "fxml", "graphics", "media", "swing", "web")
libraryDependencies ++= javaFXModules.map( m=>
"org.openjfx" % s"javafx-$m" % "11" classifier osName
)
// end
val circeVersion = "0.12.3"
libraryDependencies ++= Seq(
"io.circe" %% "circe-core",
"io.circe" %% "circe-generic",
"io.circe" %% "circe-parser"
).map(_ % circeVersion)
\ No newline at end of file
sbt.version = 1.2.8
\ No newline at end of file
// Copyright (c) 2020 EPITA Research and Development Laboratory
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package lecture
object Greeting {
def hello() = {
println("hello world ")
}
def main(argv:Array[String]) = {
}
}
// Copyright (c) 2020 EPITA Research and Development Laboratory
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package lecture
object Recursion {
def sumIntegersBySimpleRecursion(ints: List[Int]): Int = {
ints match {
case List() => 0
// common variable names are also h::t or head::tail or first::rest
case i :: is => i + sumIntegersBySimpleRecursion(is)
}
}
def sumIntegersByTailRecursion(ints: List[Int]): Int = {
def sumRest(acc: Int, rest: List[Int]): Int = {
rest match {
case List() => acc
case i :: is => sumRest(acc + i, is)
}
}
sumRest(0, ints)
}
def sumIntegersByFold(ints: List[Int]): Int = {
ints.fold(0)(_ + _)
}
def genLongList(len:Int, value:Double):List[Double] = {
List.tabulate(len)(_ => value)
}
def main(argv:Array[String]):Unit = {
val longList = List.tabulate(5673)(n => 0)
println(s"sum = ${sumIntegersBySimpleRecursion(longList)}")
}
}
// Copyright (c) 2020 EPITA Research and Development Laboratory
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package lecture
object Theg {
def checkEdge(n:Int, src:Int,dst:Int):Unit = {
assert(src >= 0, s"edge src=$src must be >=0")
assert(dst >= 0, s"edge dst=$dst must be >=0")
assert(src < n, s"edge src=$src must be < n=$n")
assert(dst < n, s"edge dst=$dst must be < n=$n")
}
// we begin assuming the edges are DIRECTED. this makes the code
// simpler. Later we will parameterize the function to all
// directed or undirected graphs.
// tail recursive function
// iterates on List input
// produces Array output
// uses .isEmpty, .head, and .tail to examine List and terminate recursion
// uses .updated to extend Array
// uses + to extend Set
def makeAdj_1(n:Int, edges:List[(Int,Int)]):Array[Set[Int]] = {
val adj = Array.fill(n)(Set[Int]())
@scala.annotation.tailrec
def init(edges:List[(Int,Int)], adj:Array[Set[Int]]):Array[Set[Int]] = {
if (edges.isEmpty)
adj
else {
val (src,dst) = edges.head
checkEdge(n,src,dst)
init(edges.tail,
adj.updated(src,adj(src)+dst))
}
}
init(edges,adj)
}
// tail recursive function
// iterates on List input
// produces Array output
// * uses pattern matching to examine list and terminate recursion
// uses .updated to extend Array
// uses + to extend Set
def makeAdj_2(n:Int, edges:List[(Int,Int)]):Array[Set[Int]] = {
val adj = Array.fill(n)(Set[Int]())
@scala.annotation.tailrec
def init(edges:List[(Int,Int)], adj:Array[Set[Int]]):Array[Set[Int]] = {
edges match {
case (src,dst)::tail =>
checkEdge(n,src,dst)
init(tail,
adj.updated(src,adj(src)+dst))
case List() =>
adj
}
}
init(edges,adj)
}
// tail recursive function
// * iterates on Array input
// produces Array output
// * uses .size and Array access by index to examine input Array
// uses .updated to extend Array
// uses + to extend Set
def makeAdj_3(n:Int, edges:Array[(Int,Int)]):Array[Set[Int]] = {
val adj = Array.fill(n)(Set[Int]())
@scala.annotation.tailrec
def init(i:Int, adj:Array[Set[Int]]):Array[Set[Int]] = {
if (i == edges.size)
adj
else {
val (src,dst) = edges(i)
checkEdge(n,src,dst)
init(i+1,
adj.updated(src,adj(src)+dst))
}
}
init(0,adj)
}
// tail recursive function
// * iterates on List input
// * produces Map output
// * uses pattern matching on List
// * uses + to extend Map
// uses + to extend Set
def makeAdj_4(n:Int, edges:List[(Int,Int)]):Map[Int,Set[Int]] = {
val adj= (0 to n-1).map{ i => i -> Set[Int]()}.toMap
@scala.annotation.tailrec
def loop(adj:Map[Int,Set[Int]],edges:List[(Int,Int)]):Map[Int,Set[Int]] = {
edges match {
case (src,dst)::es =>
loop(adj + (src -> (adj(src)+dst)),es)
case _ => adj
}
}
loop(adj,edges)
}
// * uses tabulate to iterate
// * iterates on Array input
// * produces Array output
// * computes Array once, not iteratively, not recursively
// * uses .filter .toSet to compute set of destination vertices
def makeAdj_5(n:Int, edges:Array[(Int,Int)]):Array[Set[Int]] = {
def connectionsTo(i:Int):Set[Int] = {
(0 until n).filter {
j => edges.exists { case (src, dst) => src == i && dst == j }
}.toSet
}
Array.tabulate(n)(connectionsTo)
}
// uses tabulate to iterate
// iterates on Array input
// produces Array output
// computes Array once, not iteratively, not recursively
// uses .filter .toSet to compute set of destination vertices
// * uses capital letters in pattern matching
def makeAdj_6(n:Int, edges:Array[(Int,Int)]):Array[Set[Int]] = {
def connectionsTo(S:Int):Set[Int] = {
(0 until n).filter {
D => edges.exists {
case (S, D) => true
case _ => false
}
}.toSet
}
Array.tabulate(n)(connectionsTo)
}
// tail recursive function
// iterates on List input
// produces Map output
// uses pattern matching on List
// uses + to extend Map
// uses + to extend Set
// * omits initialization of Map, just uses Map() and .getOrElse
def makeAdj_7(edges:List[(Int,Int)]):Map[Int,Set[Int]] = {
@scala.annotation.tailrec
def loop(adj:Map[Int,Set[Int]],edges:List[(Int,Int)]):Map[Int,Set[Int]] = {
edges match {
case (src,dst)::es =>
loop(adj + (src -> (adj.getOrElse(src,Set())+dst)),es)
case _ => adj
}
}
loop(Map(),edges)
}
// * uses .foldLeft
// iterates on List input
// produces Map output
// uses + to extend Map
// uses + to extend Set
// omits initialization of Map, just uses Map() and .getOrElse
def makeAdj_8(edges:List[(Int,Int)]):Map[Int,Set[Int]] = {
edges.foldLeft(Map[Int,Set[Int]]()){
case (adj,(src,dst)) =>
adj + (src -> (adj.getOrElse(src,Set())+dst))
}
}
// uses .foldLeft
// * iterates on Array input
// * code copied exactly from makeAdj_7
// produces Map output
// uses + to extend Map
// uses + to extend Set
// omits initialization of Map, just uses Map() and .getOrElse
def makeAdj_9(edges:Array[(Int,Int)]):Map[Int,Set[Int]] = {
edges.foldLeft(Map[Int,Set[Int]]()){
case (adj,(src,dst)) =>
adj + (src -> (adj.getOrElse(src,Set())+dst))
}
}
// uses .foldLeft
// * iterates on Seq input or List input
// * code copied exactly from makeAdj_7/makeAdj_8
// produces Map output
// uses + to extend Map
// uses + to extend Set
// omits initialization of Map, just uses Map() and .getOrElse
def makeAdj_10(edges:Seq[(Int,Int)]):Map[Int,Set[Int]] = {
edges.foldLeft(Map[Int,Set[Int]]()){
case (adj,(src,dst)) =>
adj + (src -> (adj.getOrElse(src,Set())+dst))
}
}
// uses .foldLeft
// * parameterizes the vertex type, no longer Int, now is V
// * iterates on Seq[A] input or List[A] input
// produces Map output
// uses + to extend Map
// uses + to extend Set
// omits initialization of Map, just uses Map() and .getOrElse
def makeAdj_11[V](edges:Seq[(V,V)]):Map[V,Set[V]] = {
edges.foldLeft(Map[V,Set[V]]()){
case (adj,(src,dst)) =>
adj + (src -> (adj.getOrElse(src,Set[V]())+dst))
}
}
// same as makeAdj_11, but assumes UNDIRECTED edges
def makeAdj_12[V](edges:Seq[(V,V)]):Map[V,Set[V]] = {
edges.foldLeft(Map[V,Set[V]]()){
case (adj,(src,dst)) =>
adj +
(src -> (adj.getOrElse(src,Set[V]())+dst)) +
(dst -> (adj.getOrElse(dst,Set[V]())+src))
}
}
// combine makeAdj_11 and makeAdj_12 with a Boolean indicating
// whether edges are interpreted as DIRECTED or UNDIRECTED
def makeAdj_13[V](edges:Seq[(V,V)], directed:Boolean):Map[V,Set[V]] = {
edges.foldLeft(Map[V,Set[V]]()){
case (adj,(src,dst)) =>
val m1 = adj + (src -> (adj.getOrElse(src,Set[V]())+dst))
if (directed)
m1
else
m1 + (dst -> (adj.getOrElse(dst,Set[V]())+src))
}
}
// we will cover this solution in a later lecture
def makeAdj_14[V](edges:Seq[(V,V)], directed:Boolean):Map[V,Set[V]] = {
val edges2 = if ( directed )
edges
else
edges ++ edges.map{case (src,dst) => (dst,src)}
edges2.groupBy{e => e._1}.map{
case (src,edges) => src -> edges.map{e=>e._2}.toSet
}
}
def main(args: Array[String]): Unit = {
println("1: " + makeAdj_1(3, List((0,1), (1,2))).mkString(","))
println("2: " + makeAdj_2(3, List((0,1), (1,2))).mkString(","))
println("3: " + makeAdj_3(3, Array((0,1), (1,2))).mkString(","))
println("4: " + makeAdj_4(3, List((0,1), (1,6), (0,2))))
println("5: " + makeAdj_5(3, Array((0,1), (1,2), (0,2))).mkString(","))
println("6: " + makeAdj_6(3, Array((0,1), (1,2), (0,2))).mkString(","))
println("7: " + makeAdj_7(List((0,1), (1,6), (0,2))))
println("8: " + makeAdj_8(List((0,1), (1,6), (0,2))))
println("9: " + makeAdj_9(Array((0,1), (1,6), (0,2))))
println("10: " + makeAdj_10(List((0,1), (1,6), (0,2))))
println("10: " + makeAdj_10(Array((0,1), (1,6), (0,2))))
println("11: " + makeAdj_11(Array((0,1), (1,6), (0,2))))
println("11: " + makeAdj_11(Array(("fred","jane"), ("sally","rita"), ("rita","fred"))))
println("11: " + makeAdj_11(List(("fred","jane"), ("sally","rita"), ("rita","fred"))))
println("12: " + makeAdj_12(List(("fred","jane"), ("sally","rita"), ("rita","fred"))))
println("13a: " + makeAdj_13(List(("fred","jane"), ("sally","rita"), ("rita","fred")), true))
println("13b: " + makeAdj_13(List(("fred","jane"), ("sally","rita"), ("rita","fred")), false))
println("14: " + makeAdj_14(List(("fred","jane"), ("sally","rita"), ("rita","fred")), false))
}
}
\ No newline at end of file
// Copyright (c) 2020 EPITA Research and Development Laboratory
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package homework
// Assignment name: Implement a simple function
//
// This homework assignment accompanies section "Basics".
// The test cases can be found in the file GreetingTestSuite.scala
// You should complete the function, replacing ??? with correct Scala
// code so that the tests pass.
object Greeting {
def hello(name:String) = {
println(???)
}
def main(argv:Array[String]) = {
}
}
// Copyright (c) 2020 EPITA Research and Development Laboratory
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package homework
import lecture.Recursion._
// Assignment name: Recursion excercise
//
// This homework assignment accompanies section "Recursion".
// The test cases can be found in the file RecursionTestSuite.scala
// You should complete the functions, replacing ??? with correct Scala
// code so that the tests pass.
//
// In the lecture we developed three functions for summing a list of
// integers. Three different techniques were used. In this assignment
// you should use similar techniques to create three functions to sum a
// list of Double, and also to find the product of a list of Double.
object Recursion {
// follow the examples from the lecture to create the following functions
// sumDoublesBySimpleRecursion()
// sumDoublesByTailRecursion()
// sumDoublesByFold()
//
// and also
//
// productDoublesBySimpleRecursion()
// productDoublesByTailRecursion()
// productDoublesByFold()
def sumDoublesBySimpleRecursion(doubles: List[Double]): Double = {
doubles match {
case List() => ???
case d :: ds => ??? + sumDoublesBySimpleRecursion(???)
}
}
def sumDoublesByTailRecursion(doubles: List[Double]): Double = {
def sumRest(acc: Double, rest: List[Double]): Double = {
???
}
}
sumRest(???, ???)
}
def sumDoublesByFold(doubles: List[Double]): Double = {
doubles.fold(??)(???)
}
def productDoublesBySimpleRecursion(doubles: List[Double]): Double = {
doubles match {
???
}
}
def productDoublesByTailRecursion(doubles: List[Double]): Double = {
def productRest (acc: Double, rest: List[Double] ): Double = {
???
}
???
}
def productDoublesByFold(doubles: List[Double]): Double = {
???
}
}
// Copyright (c) 2020 EPITA Research and Development Laboratory
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package homework
// In this exercise, you should take one of the makeAdj_* functions
// developed in the lecture, and change the name to makeAdj.
// You must choose one which fulfills the requirements and satisfies
// the test cases.
//
// ATTENTION: do not use any mutation in this assignment. You will not
// receive credit for the assignment if you use mutation.
//
// Your functions will manipulate a graph which may be DIRECTED or
// UNDIRECTED, and whose vertices may be any type. But any one graph
// contains only edges of the same type. E.g., no graph will have
// some vertices which are String and others which are Int.
// The graph will be specified by its edges. Each edge is a
// pair of vertices.
// There are no self loops, I.e., no edge has the same source and destination.
// And there is at most one edge between any two vertices.
// The graph has no isolated vertices.
// The graph is not guaranteed to be connected.
//
// The function makeAdj should take 2 arguments, edges and directed.
// directed is a boolean indicating whether the edges should
// be interpreted as directed or undirected.
// edges should be a parameter capable of receiving a List of any
// type or an Array of any type. I.e., edges specifies a *collection*
// of pairs of vertices. And the vertices may be String, Integer, Double,
// List, Array, any type at all, but all vertices are the same type
// on any one call to makeAdj.
// In the case that the graph is DIRECTED, there may be vertices
// which have no successors. For example there might be an edge from 1 to 2
// but no edge started at 2. In this case the Map returned from makeAdj
// should contain 1 -> Set(... 2 ...), but should not contain 2 -> Set().
//
// Implement the function reachableVertices which takes a parameter representing
// the graph edges. The function should return a Set of vertices which
// can be reached starting from the given starting vertex by tracing edges.
// Edges are traced in a directed sense if the graph is DIRECTED, and edges
// may be trace in both directions if the graph is UNDIRECTED.
// The function should implement a breadth-first search starting at