diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 21f3d2f..3049d9d 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -2,14 +2,15 @@
+
+
-
@@ -17,7 +18,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..f4c7f29
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..c5310cd
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/scala_settings.xml b/.idea/scala_settings.xml
new file mode 100644
index 0000000..348d2d7
--- /dev/null
+++ b/.idea/scala_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index cf8ed1c..e517d3e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,11 +9,15 @@
pom
1.0
+
+ UTF-8
+
+
scala
modern-java
- functional-programming-java
-
+ functional-programming-java
+
diff --git a/scala/pom.xml b/scala/pom.xml
index 812e02d..40416e2 100644
--- a/scala/pom.xml
+++ b/scala/pom.xml
@@ -7,6 +7,8 @@
1.0
+ 8
+ 8
2.13.0
diff --git a/scala/src/main/scala/org/gym/fp/Device.scala b/scala/src/main/scala/org/gym/fp/Device.scala
new file mode 100644
index 0000000..c436796
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/Device.scala
@@ -0,0 +1,32 @@
+package org.gym.fp
+
+abstract class Device
+
+case class Phone(model: String) extends Device {
+ def screenOff = "Turning screen off"
+}
+
+case class Computer(model: String) extends Device {
+ def screenSaverOn = "Turning screen saver on..."
+}
+
+object DeviceTest {
+
+ private def newLine = println()
+
+ def main(args: Array[String]): Unit = {
+ println("TEST 1")
+ val p = Phone("Samsung Galaxy S8 Edge")
+ val c = Computer("Alienware")
+ println(goIdle(p))
+ println(goIdle(c))
+ newLine
+ }
+
+ def goIdle(device: Device) = {
+ device match {
+ case p: Phone => p.screenOff
+ case c: Computer => c.screenSaverOn
+ }
+ }
+}
diff --git a/scala/src/main/scala/org/gym/fp/Exercise.scala b/scala/src/main/scala/org/gym/fp/Exercise.scala
new file mode 100644
index 0000000..6043938
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/Exercise.scala
@@ -0,0 +1,358 @@
+package org.gym.fp
+
+import org.gym.fp.model.Rational
+
+import scala.annotation.tailrec
+
+class Exercise {
+
+ private def newLine = println()
+
+ //es. 1
+ def mcd(x: Int, y: Int): Int = if (y == 0) x else mcd(y, x % y)
+
+ //es. 2
+ def sommeQuad(x: Int, y: Int): Int = if (x > y) 0 else x * x + sommeQuad(x + 1, y)
+
+ //es. 3
+ def sqrt(x: Double) = {
+ val epsilon = 0.000000000001
+
+ def abs(x: Double) = if (x < 0) -x else x
+
+ def firstPrev(y: Double, x: Double) = abs(y * y - x) < epsilon
+
+ def secondPrev(y: Double, x: Double) = (y + x / y) / 2.0
+
+ def bestSqrt(y: Double, x: Double): Double =
+ if (firstPrev(y, x)) y else bestSqrt(secondPrev(y, x), x)
+
+ bestSqrt(1.0, x)
+ }
+
+ // f(g(x)) es. 4
+ def componi(f: Int => Int, g: Int => Int) = g.andThen(f)
+
+ //es. 5
+ def somma(f: Int => Int): (Int, Int) => Int = {
+ def g(a: Int, b: Int): Int = if (a - b > 0) 0 else f(a) + g(a + 1, b)
+
+ g
+ }
+
+ // es. 6
+ def applicaDueVolte(f: Int => Int, x: Int) = componi(f, f)(x)
+
+ // es. 9
+ def primo(n: Int): Boolean = {
+ val sqrt = Operation.sqrt(n.doubleValue()).intValue();
+ var result = true
+
+ if (n == 2) {
+ result = false
+ }
+
+ for (i <- 2 to sqrt) {
+ if (n % i == 0) {
+ result = false
+ }
+ }
+ result
+ }
+
+ //es. 10
+ def fib(n: Int): Int =
+ if (n == 0) 0 else if (n == 1) 1 else fib(n - 1) + fib(n - 2)
+
+ //es. 11
+ def sommaQuadRic(a: Int, b: Int): Int = {
+ @tailrec
+ def somma(a: Int, b: Int, acc: Int): Int =
+ if (a - b > 0) acc else somma(a + 1, b, (a * a) + acc)
+
+ somma(a, b, 0)
+ }
+
+ def sommaQuadList(a: Int, b: Int) = List.range(a, b + 1).map(x => x * x).reduce(_ + _)
+
+ //es. 12
+ def funcEqual(f1: Int => Int, f2: Int => Int, n: Int): Boolean =
+ if (n >= 0) f1(n) == f2(n) else f1(n) == f2(n) && funcEqual(f1, f2, n - 1)
+
+ //es. 13 TODO NON SI CAPISCE IL RISULTATO DEL ESERCIZIO
+ def concatena(f1: Double => Double, f2: Double => Double, f3: Double => Double, a: Double, b: Double) = ???
+
+ //es. 14
+ def maxLength(strings: List[String]) =
+ strings.map(s => s.length()).reduce((s1, s2) => if (s1 > s2) s1 else s2)
+
+ //es. 15
+ def equal(l1: List[Int], l2: List[Int]): Boolean =
+ if (l1.isEmpty && !l2.isEmpty || !l1.isEmpty && l2.isEmpty)
+ false
+ else if (l1.isEmpty && l2.isEmpty)
+ true
+ else
+ l1.head == l2.head && equal(l1.tail, l2.tail)
+
+ //es. 16
+ def filter(l: List[Int], predicate: Int => Boolean): List[Int] = {
+ @tailrec
+ def innerFilter(l: List[Int], predicate: Int => Boolean, acc: List[Int]): List[Int] =
+ if (l.isEmpty) acc else innerFilter(l.tail, predicate, if (predicate(l.head)) l.head :: acc else acc)
+
+ innerFilter(l, predicate, List()).sorted
+ }
+
+ //es. 17
+ def minMaxRic(l: List[Int]): (Int, Int) = {
+ @tailrec
+ def min(l: List[Int], m: Int): Int = if (l.isEmpty) m else min(l.tail, if (l.head < m) l.head else m)
+
+ @tailrec
+ def max(l: List[Int], m: Int): Int = if (l.isEmpty) m else max(l.tail, if (l.head > m) l.head else m)
+
+ (min(l, Int.MaxValue), max(l, Int.MinValue))
+ }
+
+ def minMaxList(l: List[Int]): (Int, Int) = {
+ val min = l.reduce((a, b) => if (a < b) a else b)
+ val max = l.reduce((a, b) => if (a > b) a else b)
+ (min, max)
+ }
+
+ def minMaxList2(l: List[Int]): (Int, Int) = (l.min, l.max)
+
+ //es. 18
+ def mediaVeicoli(l: List[Int]): Double =
+ l.span(v => v > 0)._1.foldLeft(0)(_ + _).toDouble / l.span(v => v > 0)._1.foldLeft(0.0)((r, c) => r + 1)
+
+ //es. 19
+ def allDistinct[T <% Ordered[T]](l: List[T]): Boolean = l.size == l.distinct.size
+
+ //es. 20 TODO NON SI CAPISCE IL RISULTATO DEL ESERCIZIO
+ def inferiori(l: List[Int]): List[(Int, Int)] = ???
+
+ //es. 21
+ def find[T](x: T, l: List[T]): Boolean = l.find(x == _).getOrElse(None) != None
+
+ //es. 22
+ def removeDuplicates[T](l: List[T]): List[T] = l.distinct
+
+ //es. 23
+ def union[T](l1: List[T], l2: List[T]): List[T] = l1.union(l2).distinct
+
+ //es. 24
+ def intersection[T](l1: List[T], l2: List[T]): List[T] = l1.intersect(l2).distinct
+
+ //es. 31
+ def forComprehension() = {
+ case class Studente(val nome: String, val eta: Int, val esami: List[String])
+
+ val q = List(
+ Studente("Marco", 23, List("PFP", "SC")),
+ Studente("Laura", 19, List("SC", "FI1", "PFP")),
+ Studente("Stefano", 23, List("SC", "FI1")),
+ Studente("Marco", 25, List("SC", "FI1", "FI2")),
+ Studente("Paola", 22, List("SC", "PFP"))
+ )
+
+ // estrarre tutti gli studenti con eta compresa tra 20 e 24 anni (inclusi) che hanno sostenuto l'esame di "PFP"
+ val query1 = for {
+ s <- q
+ if (s.eta >= 20 && s.eta <= 24 && s.esami.contains("PFP"))
+ } yield s;
+ // stampare i dati degli studenti in query1
+ println("Studenti dai 20 ai 24 anni con esame PFP: ")
+ query1 foreach println
+ newLine
+
+ // estrarre tutti gli studenti con eta strettamente inferiore a 24 anni che hanno sostenuto almeno due esami
+ val query2 = for {
+ s <- q
+ if (s.eta < 24 && s.esami.size >= 2)
+ } yield s;
+ // stampare i dati degli studenti in query2
+ println("Studenti minori di 24 anni con almeno 2 esami: ")
+ query2 foreach println
+ }
+
+ //es. 33
+ def repeat(times: Int)(statement: => Unit) = for (i <- 1 to times) statement
+
+ //es. 34
+
+ // Versione imperativa di prova
+ // def vecprod(v1: Array[Double], v2: Array[Double]) = {
+ // require(v1.size == v2.size)
+ // var sp = 0.0
+ // var i = 0
+ // while (i < v1.size) {
+ // sp += v1(i) * v2(i)
+ // i += 1
+ // }
+ // sp
+ // }
+
+ def vecprod(v1: Array[Double], v2: Array[Double]) = {
+ require(v1.size == v2.size)
+ v1.zip(v2).map(t => t._1 * t._2).reduce(_ + _)
+ }
+
+ def executeAllTests() = {
+
+ //es. 1
+ println("Esercizio 1")
+ println("Minimo comune denominatore tra 5 e 15 = " + mcd(5, 15))
+ newLine
+
+ //es. 2
+ println("Esercizio 2")
+ println("sommatoria dei quadrati da 1 a 3 = " + sommeQuad(1, 3)) // stampa 14 (somma dei quadrati di 1, 2 e 3)
+ newLine
+
+ //es. 3
+ println("Esercizio 3")
+ println("Radice quadrata di 2 ~ " + sqrt(2))
+ newLine
+
+ // f(g(x)) es.4
+ println("Esercizio 4")
+ val f = componi(x => x * x, x => x + 1)
+ println("f(g(x) / f(x) = x * x e g(x) = x + 1 := " + f(9)) // stampa 100
+ newLine
+
+ //es.5
+ println("Esercizio 5")
+ val sommaQuadrati = somma(x => x * x)
+ println("sommatoria dei quadrati da 1 a 3 = " + sommaQuadrati(1, 3)) // stampa 14 (somma dei quadrati di 1, 2 e 3)
+ newLine
+
+ //es.6
+ println("Esercizio 6")
+ println("10 + 1 + 1 = " + applicaDueVolte(x => x + 1, 10)) // stampa 12
+ newLine
+
+ //es.9
+ println("Esercizio 9")
+ println("primo(3) = " + primo(3)) // true
+ println("primo(2) = " + primo(2)) // false
+ newLine
+
+ //es.10
+ println("Esercizio 10")
+ println("fib(20) = " + fib(20))
+ newLine
+
+ //es.11
+ println("Esercizio 11")
+ println("sommatoria dei quadrati da 1 a 3 = " + sommaQuadRic(1, 3)) //14
+ println("sommatoria dei quadrati da 1 a 3 = " + sommaQuadList(1, 3)) //14
+ newLine
+
+ //es.12
+ println("Esercizio 12")
+ println(funcEqual(x => x * x, x => x * x, 4)) // true
+ println(funcEqual(x => x * x, x => x + 1, 4)) // false
+ newLine
+
+ //es. 14
+ println("Esercizio 14")
+ println(maxLength(List("ciao", "famiglia", "supercalifragilistichespiralidoso"))) // 33
+ newLine
+
+ //es. 15
+ println("Esercizio 15")
+ println(equal(List(1, 2, 3), List(1, 2, 3))) // true
+ println(equal(List(1, 2, 3), List(1, 2, 3, 4))) // false
+ println(equal(List(1, 2, 3, 4), List(1, 2, 3))) // false
+ newLine
+
+ //es. 16
+ println("Esercizio 16")
+ val l = List(3, 1, 2, 4, 5)
+ println(filter(l, _ > 2)) // stampa 3,4,5
+ newLine
+
+ //es. 17
+ println("Esercizio 17")
+ println("Versione ricorsiva: " + minMaxRic(List(10, 2, 3, 6)))
+ println("Versione con metodi standard: " + minMaxList(List(10, 2, 3, 6)))
+ newLine
+
+ //es. 18
+ println("Esercizio 18")
+ println("La media e' = " + mediaVeicoli(List(4, 8, 4, 8, 4, 4, 4, 4, -1, 77, 88, 99))) // 5
+ newLine
+
+ //es. 19
+ println("Esercizio 19")
+ println(allDistinct(List(1, 2, 3, 4, 5))) // true
+ println(allDistinct(List(4, 8, 4, 8, 4, 4, 4, 4, -1, 77, 88, 99))) // false
+ newLine
+
+ //es. 20
+ println("Esercizio 20")
+ //println(inferiori(List(1,3,1,2,2,1))) // deve restituire List((1,0), (2,3), (3,5))
+ newLine
+
+ //es. 21
+ println("Esercizio 21")
+ println(find(2, List(3, 1, 2, 4, 5))) // true
+ println(find(20, List(3, 1, 2, 4, 5))) // false
+ newLine
+
+ //es. 22
+ println("Esercizio 22")
+ println(removeDuplicates(List(1, 2, 3, 4, 4, 5))) // List(1, 2, 3, 4, 5)
+ println(removeDuplicates(List(4, 8, 4, 8, 4, 4, 4, 4, -1, 77, 88, 99))) // List(4, 8, -1, 77, 88, 99)
+ newLine
+
+ //es. 23
+ println("Esercizio 23")
+ println(union(List(1, 2, 3, 4, 4, 5), List(4, 8, 4, 8, 4, 4, 4, 4, -1, 77, 88, 99))) // List(1, 2, 3, 4, 5, 8, -1, 77, 88, 99)
+ newLine
+
+ //es. 24
+ println("Esercizio 24")
+ println(intersection(List(1, 2, 3, 4, 4, 5), List(4, 8, 4, 8, 4, 4, 4, 4, 5, -1, 77, 88, 99))) // List(4, 5)
+ newLine
+
+ //es. 25
+ println("Esercizio 25")
+ val r1 = new Rational(2, 7)
+ val r2 = new Rational(8, 6)
+ val r3 = new Rational(4, 14)
+ val r4: Rational = 1.0 / 2.0
+ val r5: Rational = 5
+ println(r1 + r2) // stampa 34/21
+ println(r1 - r2) // stampa -22/21
+ println(r1 * r2) // stampa 8/21
+ println(r1 / r2) // stampa 3/14
+ println(r1 == r3) // stampa true
+ println(r1 != r2) // stampa true
+ println(r1 < r2) // stampa true
+ println(r2 < r1) // stampa false
+ println(r4)
+ println(r5)
+ newLine
+
+ //es. 31
+ println("Esercizio 31")
+ forComprehension()
+ newLine
+
+ //es. 33
+ println("Esercizio 33")
+ repeat(3) {
+ println("ciao")
+ }
+ newLine
+
+ //es. 34
+ println("Esercizio 34")
+ println(vecprod(Array(1.0, 2.0, 3.0, 4.0, 5.0), Array(6.0, 7.0, 8.0, 9.0, 10.0))) // 130.0
+ newLine
+ }
+
+}
diff --git a/scala/src/main/scala/org/gym/fp/Furniture.scala b/scala/src/main/scala/org/gym/fp/Furniture.scala
new file mode 100644
index 0000000..5145e43
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/Furniture.scala
@@ -0,0 +1,21 @@
+package org.gym.fp
+
+sealed abstract class Furniture
+
+case class Couch() extends Furniture
+
+case class Chair() extends Furniture
+
+object FurnitureTest {
+ def main(args: Array[String]): Unit = {
+ val a = Couch
+ val b = Chair
+ }
+
+ def findPlaceToSit(piece: Furniture) = {
+ piece match {
+ case a: Couch => "Lie on the couch"
+ case b: Chair => "Sit on the chair"
+ }
+ }
+}
\ No newline at end of file
diff --git a/scala/src/main/scala/org/gym/fp/Main.scala b/scala/src/main/scala/org/gym/fp/Main.scala
new file mode 100644
index 0000000..88f208f
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/Main.scala
@@ -0,0 +1,22 @@
+package org.gym.fp
+
+object Main {
+
+ def main(args: Array[String]): Unit = {
+ // val t = new Test
+ // println("TEST 1")
+ // t.test1()
+ // println("TEST 2")
+ // t.test2()
+ // println("TEST 3")
+ // t.test3()
+ // println("TEST 4")
+ // t.test4()
+ // println("TEST 5")
+ // t.test5()
+ println("ESERCIZI")
+ val e: Exercise = new Exercise
+ e.executeAllTests()
+ }
+
+}
diff --git a/scala/src/main/scala/org/gym/fp/Model2D.scala b/scala/src/main/scala/org/gym/fp/Model2D.scala
new file mode 100644
index 0000000..c5fcdf4
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/Model2D.scala
@@ -0,0 +1,18 @@
+package org.gym.fp
+
+import org.gym.fp.model.{Frame2D, Line}
+
+object Model2D {
+
+ def getGrid(n: Int) = {
+
+ // completare costruzione di un modello 2D di una griglia con n linee verticali ed n linee orizzontali
+ List(new Line(0.0, 0.0, 1.0, 1.0)) // esempio di linea
+ }
+
+ def main(args: Array[String]) {
+ println("Displaying 20x20 grid...")
+ Frame2D.display(Model2D.getGrid(20), 500, 500)
+ }
+
+}
diff --git a/scala/src/main/scala/org/gym/fp/Notification.scala b/scala/src/main/scala/org/gym/fp/Notification.scala
new file mode 100644
index 0000000..93c5e27
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/Notification.scala
@@ -0,0 +1,73 @@
+package org.gym.fp
+
+abstract class Notification
+
+case class Email(sender: String, title: String, body: String) extends Notification
+
+case class SMS(caller: String, message: String) extends Notification
+
+case class VoiceRecording(contactName: String, link: String) extends Notification
+
+class NotificationTest() {
+ def showNotification(notification: Notification): String = {
+ notification match {
+ case Email(email, title, _) =>
+ s"You got an email from $email with title: $title"
+ case SMS(number, message) =>
+ s"You got an SMS from $number! Message: $message"
+ case VoiceRecording(name, link) =>
+ s"You received a Voice Recording from $name! Click the link to hear it: $link"
+ }
+ }
+
+ def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
+ notification match {
+ case Email(email, _, _) if importantPeopleInfo.contains(email) =>
+ "You got an email from special someone!"
+ case SMS(number, _) if importantPeopleInfo.contains(number) =>
+ "You got an SMS from special someone!"
+ case other =>
+ showNotification(other) // nothing special, delegate to our original showNotification function
+ }
+ }
+}
+
+object NotificationTest {
+
+ private def newLine = println()
+
+ def main(args: Array[String]): Unit = {
+ val t = new NotificationTest
+
+ println("TEST 1")
+ test1(t)
+ newLine
+
+ println("TEST 2")
+ test2(t)
+ newLine
+ }
+
+ def test1(t: NotificationTest) = {
+ val someSms = SMS("12345", "Are you there?")
+ val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
+
+ println(t.showNotification(someSms)) // prints You got an SMS from 12345! Message: Are you there?
+ println(t.showNotification(someVoiceRecording)) // you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123
+ }
+
+ def test2(t: NotificationTest) = {
+ val importantPeopleInfo = Seq("867-5309", "jenny@gmail.com")
+
+ val someSms = SMS("867-5309", "Are you there?")
+ val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
+ val importantEmail = Email("jenny@gmail.com", "Drinks tonight?", "I'm free after 5!")
+ val importantSms = SMS("867-5309", "I'm here! Where are you?")
+
+ println(t.showImportantNotification(someSms, importantPeopleInfo))
+ println(t.showImportantNotification(someVoiceRecording, importantPeopleInfo))
+ println(t.showImportantNotification(importantEmail, importantPeopleInfo))
+ println(t.showImportantNotification(importantSms, importantPeopleInfo))
+ }
+
+}
diff --git a/scala/src/main/scala/org/gym/fp/Operation.scala b/scala/src/main/scala/org/gym/fp/Operation.scala
new file mode 100644
index 0000000..678a8fb
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/Operation.scala
@@ -0,0 +1,50 @@
+package org.gym.fp
+
+import scala.annotation.tailrec
+
+object Operation {
+
+ def abs(x: Double) = if (x < 0) -x else x
+
+ def add(a: Double)(b: Double) = a + b
+
+ def sub(a: Double)(b: Double) = a - b
+
+ def prod(a: Double)(b: Double) = a * b
+
+ def div(a: Double)(b: Double) = if (b != 0) a / b else 0
+
+ def inc(x: Double) = add(x)(1)
+
+ def dec(x: Double) = sub(x)(1)
+
+ def mcd(x: Int, y: Int): Int = if (y == 0) x else mcd(y, x % y)
+
+ def sqrt(x: Double) = {
+ val epsilon = 0.000000000001
+
+ def firstPrev(y: Double, x: Double) = abs(y * y - x) < epsilon
+
+ def secondPrev(y: Double, x: Double) = (y + x / y) / 2.0
+
+ def bestSqrt(y: Double, x: Double): Double =
+ if (firstPrev(y, x)) y else bestSqrt(secondPrev(y, x), x)
+
+ bestSqrt(1.0, x)
+ }
+
+ def pow(n: Double)(x: Double) = {
+ @tailrec
+ def p(n: Double, x: Double, a: Double): Double =
+ if (x == 0) a else p(n, x - 1, n * a)
+
+ p(n, x, 1)
+ }
+
+ def square(n: Double) = pow(n)(2)
+
+ def cube(n: Double) = pow(n)(3)
+
+ def percent(n: Double, p: Double) = if (p > 0 && n > 0) div(prod(n)(p))(100.0) else 0
+
+}
\ No newline at end of file
diff --git a/scala/src/main/scala/org/gym/fp/TestThread.scala b/scala/src/main/scala/org/gym/fp/TestThread.scala
new file mode 100644
index 0000000..81271b8
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/TestThread.scala
@@ -0,0 +1,14 @@
+package org.gym.fp
+
+object TestThread extends App {
+ val r = new Runnable {
+ def run() {
+ for (i <- 1 to 1000)
+ println(i)
+ }
+ }
+ val t = new Thread(r)
+ t.start()
+ for (i <- 5000 to 6000) println(i)
+ t.join()
+}
diff --git a/scala/src/main/scala/org/gym/fp/TestThread2.scala b/scala/src/main/scala/org/gym/fp/TestThread2.scala
new file mode 100644
index 0000000..603eb86
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/TestThread2.scala
@@ -0,0 +1,11 @@
+package org.gym.fp
+
+import org.gym.fp.model.Par.par
+
+object TestThread2 extends App {
+ par {
+ for (i <- 0 to 1000) println(i)
+ } {
+ for (i <- 5000 to 6000) println(i)
+ }
+}
diff --git a/scala/src/main/scala/org/gym/fp/db/Database.scala b/scala/src/main/scala/org/gym/fp/db/Database.scala
new file mode 100644
index 0000000..513922e
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/db/Database.scala
@@ -0,0 +1,19 @@
+package org.gym.fp.db
+
+import org.gym.fp.model.Customer
+
+/**
+ * @author HP
+ */
+object Database {
+ var values = List(
+ new Customer("Luigi", 35),
+ new Customer("Marco", 14),
+ new Customer("Martina", 22),
+ new Customer("Fabrizio", 30),
+ new Customer("Flavia", 25),
+ new Customer("Kevin", 45),
+ new Customer("Antonio", 56),
+ new Customer("Giuseppe", 61),
+ new Customer("Cinzia", 55))
+}
diff --git a/scala/src/main/scala/org/gym/fp/model/Customer.scala b/scala/src/main/scala/org/gym/fp/model/Customer.scala
new file mode 100644
index 0000000..1d23094
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/model/Customer.scala
@@ -0,0 +1,3 @@
+package org.gym.fp.model
+
+case class Customer(val name: String, val age: Int)
\ No newline at end of file
diff --git a/scala/src/main/scala/org/gym/fp/model/Frame2D.scala b/scala/src/main/scala/org/gym/fp/model/Frame2D.scala
new file mode 100644
index 0000000..b43e0a8
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/model/Frame2D.scala
@@ -0,0 +1,60 @@
+package org.gym.fp.model
+
+import java.awt.{Dimension, EventQueue, Graphics, Graphics2D}
+
+import javax.swing.{JFrame, JPanel}
+
+object Frame2D {
+ def display(l: List[Shape], width: Int, height: Int) {
+ EventQueue.invokeLater(() => {
+ val ex = new Frame2D(l, width, height)
+ ex.setVisible(true)
+ })
+ }
+}
+
+class Frame2D(l: List[Shape], width: Int, height: Int) extends JFrame {
+
+ class Surface2D extends JPanel {
+
+ def doDrawCircle(c: Circle, g2d: Graphics2D) {
+ val xc = (width * (c.x - c.r)).toInt
+ val yc = height / 2 - (height * (c.y - c.r)).toInt
+ val wc = (2 * width * c.r).toInt
+ val hc = (2 * height * c.r).toInt
+ g2d.drawOval(xc, yc, wc, hc)
+ }
+
+ def doDrawLine(l: Line, g2d: Graphics2D) {
+ val x1 = (width * l.x1).toInt
+ val y1 = height - (height * l.y1).toInt
+ val x2 = (width * l.x2).toInt
+ val y2 = height - (height * l.y2).toInt
+ g2d.drawLine(x1, y1, x2, y2)
+ }
+
+ def doDrawing(g: Graphics) {
+ g match {
+ case g2d: Graphics2D =>
+ l foreach (_ match {
+ case c: Circle => doDrawCircle(c, g2d)
+ case l: Line => doDrawLine(l, g2d)
+ })
+ }
+ }
+
+ override def paintComponent(g: Graphics) {
+ super.paintComponent(g);
+ doDrawing(g);
+ }
+ }
+
+ val panel = new Surface2D()
+ panel.setPreferredSize(new Dimension(width, height))
+ add(panel);
+ setTitle("Shapes");
+ setResizable(false)
+ pack();
+ setLocationRelativeTo(null);
+ //setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+}
\ No newline at end of file
diff --git a/scala/src/main/scala/org/gym/fp/model/Par.scala b/scala/src/main/scala/org/gym/fp/model/Par.scala
new file mode 100644
index 0000000..59f07eb
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/model/Par.scala
@@ -0,0 +1,13 @@
+package org.gym.fp.model
+
+object Par {
+ def par(statement1: => Unit)(statement2: => Unit) = {
+ val r = new Runnable {
+ override def run(): Unit = statement1
+ }
+ val t = new Thread(r)
+ t.start()
+ statement2
+ t.join()
+ }
+}
diff --git a/scala/src/main/scala/org/gym/fp/model/Pila.scala b/scala/src/main/scala/org/gym/fp/model/Pila.scala
new file mode 100644
index 0000000..458eaaf
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/model/Pila.scala
@@ -0,0 +1,29 @@
+package org.gym.fp.model
+
+import scala.collection.mutable.ArrayBuffer
+
+class Pila[T] {
+ private var l: ArrayBuffer[T] = ArrayBuffer[T]()
+
+ def isEmpty(): Boolean = l.isEmpty
+
+ def push(elem: T): Unit = l.append(elem)
+
+ def pop(): T = {
+ if (isEmpty()) throw new IllegalArgumentException()
+ l.remove(0)
+ }
+
+ def top(): T = {
+ if (isEmpty()) throw new IllegalArgumentException()
+ l.last
+ }
+}
+
+object TestPila {
+ def main(args: Array[String]): Unit = {
+ var p: Pila[Int] = new Pila[Int]
+ for (i <- 1 to 10) p.push(i)
+ while (!p.isEmpty()) println(p.pop())
+ }
+}
diff --git a/scala/src/main/scala/org/gym/fp/model/Rational.scala b/scala/src/main/scala/org/gym/fp/model/Rational.scala
new file mode 100644
index 0000000..0d4fece
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/model/Rational.scala
@@ -0,0 +1,52 @@
+package org.gym.fp.model
+
+import org.gym.fp.Operation.{mcd, pow}
+
+
+case class Rational(num: Int, den: Int) {
+
+ def +(other: Rational) =
+ Rational.minimize(Rational((this.num * other.den) + (this.den * other.num), this.den * other.den))
+
+ def -(other: Rational) =
+ Rational.minimize(Rational((this.num * other.den) - (this.den * other.num), this.den * other.den))
+
+ def *(other: Rational) =
+ Rational.minimize(Rational(this.num * other.num, this.den * other.den))
+
+ def /(other: Rational) =
+ Rational.minimize(Rational(this.num * other.den, this.den * other.num))
+
+ def >(other: Rational) = (this.num / this.den) > (other.num / other.den)
+
+ def <(other: Rational) = (this.num / this.den) < (other.num / other.den)
+
+ def >=(other: Rational) = (this.num / this.den) >= (other.num / other.den)
+
+ def <=(other: Rational) = (this.num / this.den) <= (other.num / other.den)
+
+ def ==(other: Rational) = (this.num / this.den) == (other.num / other.den)
+
+ def !=(other: Rational) = (this.num / this.den) != (other.num / other.den)
+
+ override def toString() = s"$num/$den"
+
+}
+
+object Rational {
+
+ private def minimize(r: Rational) =
+ if (r.num == 0) Rational(r.num, 1) else Rational(r.num / mcd(r.num, r.den), r.den / mcd(r.num, r.den))
+
+ implicit def doubleToRational(d: Double) = {
+ val len = String.valueOf(d).split("\\.")(1).length
+ val den = pow(10)(len).toInt
+ val num = (d * den).toInt
+ minimize(new Rational(num, den))
+ }
+
+ implicit def intToRational(i: Int) = {
+ minimize(new Rational(i, 1))
+ }
+
+}
\ No newline at end of file
diff --git a/scala/src/main/scala/org/gym/fp/model/Shape.scala b/scala/src/main/scala/org/gym/fp/model/Shape.scala
new file mode 100644
index 0000000..ff5b887
--- /dev/null
+++ b/scala/src/main/scala/org/gym/fp/model/Shape.scala
@@ -0,0 +1,7 @@
+package org.gym.fp.model
+
+abstract class Shape
+
+class Circle(val x: Double, val y: Double, val r: Double) extends Shape
+
+class Line(val x1: Double, val y1: Double, val x2: Double, val y2: Double) extends Shape
\ No newline at end of file