Skip to content

Commit 3ca31c5

Browse files
Chapter 1
1 parent 8dfd125 commit 3ca31c5

File tree

7 files changed

+246
-0
lines changed

7 files changed

+246
-0
lines changed

build.sbt

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name := "Chapter 1 Exercises"
2+
3+
organization := "fpoo"
4+
5+
version := "1.0"
6+
7+
scalaVersion := "2.10.3"
8+
9+
scalacOptions ++= Seq("-unchecked", "-deprecation")
10+
11+
libraryDependencies ++= Seq(
12+
"org.scalatest" % "scalatest_2.10" % "2.0" % "test",
13+
"org.scalautils" % "scalautils_2.10" % "2.0"
14+
)

project/build.properties

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sbt.version=0.12.0

project/build.scala

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// import sbt._
2+
// import Keys._
3+
4+
// object H2TaskManager {
5+
// var process: Option[Process] = None
6+
// lazy val H2 = config("h2") extend(Compile)
7+
8+
// val startH2 = TaskKey[Unit]("start", "Starts H2 database")
9+
// val startH2Task = startH2 in H2 <<= (fullClasspath in Compile) map {
10+
// cp =>
11+
// startDatabase {
12+
// cp.map(_.data)
13+
// .map(_.getAbsolutePath())
14+
// .filter(_.contains("h2database"))
15+
// }
16+
// }
17+
18+
// def startDatabase(paths: Seq[String]) = {
19+
// process match {
20+
// case None =>
21+
// val cp = paths.mkString(System.getProperty("path.separator"))
22+
// val command = "java -cp " + cp + " org.h2.tools.Server"
23+
// println("Starting Database with command: " + command)
24+
// process = Some(Process(command).run())
25+
// println("Database started ! ")
26+
// case Some(_) => println("H2 Database already started")
27+
// }
28+
// }
29+
30+
// val stopH2 = TaskKey[Unit]("stop", "Stops H2 database")
31+
// val stopH2Task = stopH2 in H2 :={
32+
// process match {
33+
// case None => println("Database already stopped")
34+
// case Some(_) =>
35+
// println("Stopping database...")
36+
// process.foreach{_.destroy()}
37+
// process = None
38+
// println("Database stopped...")
39+
// }
40+
// }
41+
// }
42+
43+
// object MainBuild extends Build {
44+
// import H2TaskManager._
45+
46+
// lazy val scalazVersion = "6.0.3"
47+
// lazy val jettyVersion = "7.3.0.v20110203"
48+
49+
// lazy val wekanban = Project("wekanban", file("."))
50+
// .settings(startH2Task, stopH2Task)
51+
// }

project/plugins.sbt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

src/main/scala/fpoo/Chapter01.scala

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package fpoo
2+
3+
object Chapter01 {
4+
// import
5+
def second[A](list: List[A]): A = list(1)
6+
def third[A](list: List[A]): A = list(2)
7+
def third2[A](list: List[A]): A = list.tail.tail.head
8+
def addSquares[T](list: List[T])(implicit n: Numeric[T]): T = list.map( x => n.times(x, x) ).sum
9+
def bizarreFactorial(n: Int): Int = n match {
10+
case x if x < 0 => throw new IllegalArgumentException("Factorial only works for positive integers")
11+
case 0 => 1
12+
case _ => 1 to n product
13+
}
14+
def prefixOf[A](prefix: Seq[A], seq: Seq[A]) = seq.startsWith(prefix)
15+
16+
implicit class Ops[A](val seq: Seq[A]) extends AnyVal {
17+
def interleave(that: Seq[A]): Seq[A] = {
18+
seq zip that flatMap { t => Seq(t._1, t._2) }
19+
}
20+
def tails2: Seq[Seq[A]] = {
21+
def tailn(s: Seq[A]): Seq[Seq[A]] = s match {
22+
case Seq() => Seq(s)
23+
case _ => s +: tailn(s.tail)
24+
}
25+
tailn(seq)
26+
}
27+
def tails3: Seq[Seq[A]] = {
28+
val seqs = Seq.fill(seq.length + 1)(seq)
29+
val nToDrop = 0 to seq.length
30+
(seqs, nToDrop).zipped map (_ drop _)
31+
}
32+
}
33+
}
+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package fpoo
2+
3+
import org.scalatest._
4+
import org.scalatest.prop.TableDrivenPropertyChecks
5+
import fpoo.Chapter01._
6+
7+
class SecondSpec extends UnitSpec {
8+
"Exercise 1: second" should "return the second item in a given list" in {
9+
val list = List("Lorem", "ipsum", "dolor", "sit", "amet")
10+
second(list) should be ("ipsum")
11+
}
12+
it should "throw IndexOutOfBoundsException if called on a list with fewer than 2 elements" in {
13+
val listOf1 = List("sole")
14+
a [IndexOutOfBoundsException] should be thrownBy {
15+
second(listOf1)
16+
}
17+
}
18+
}
19+
20+
class ThirdSpec extends UnitSpec {
21+
"Exercise 2a: third" should "return the third item in a given list" in {
22+
val list = List("Lorem", "ipsum", "dolor", "sit", "amet")
23+
third(list) should be ("dolor")
24+
}
25+
it should "throw IndexOutOfBoundsException if called on a list with fewer than 3 elements" in {
26+
val listOf2 = List("penulitimate", "ultimate")
27+
a [IndexOutOfBoundsException] should be thrownBy {
28+
third(listOf2)
29+
}
30+
}
31+
}
32+
33+
class Third2Spec extends UnitSpec {
34+
"Exercise 2b: third2" should "return the third item in a given list" in {
35+
val list = List("Lorem", "ipsum", "dolor", "sit", "amet")
36+
third2(list) should be ("dolor")
37+
}
38+
it should "throw NoSuchElementException if called on a list with fewer than 3 elements" in {
39+
val listOf2 = List("penulitimate", "ultimate")
40+
a [NoSuchElementException] should be thrownBy {
41+
third2(listOf2)
42+
}
43+
}
44+
}
45+
46+
class AddSquaresSpec extends UnitSpec {
47+
"Exercise 3: addSquares" should "square each item in a list and sum them" in {
48+
val list = List(1, 2, 5)
49+
addSquares(list) should be (30)
50+
}
51+
it should "return 0 if called on an empty list" in {
52+
val emptyList = List[Int]()
53+
addSquares(emptyList) should be (0)
54+
}
55+
}
56+
57+
class BizareFactorialSpec extends UnitSpec with TableDrivenPropertyChecks {
58+
"Exercise 4: bizarreFactorial" should "compute the factorial, i.e., n!, of a given integer n >= 0" in {
59+
val factorials = Table(
60+
("n", "factorial"),
61+
(0, 1),
62+
(1, 1),
63+
(2, 2),
64+
(3, 6),
65+
(4, 24),
66+
(5, 120)
67+
)
68+
69+
forAll (factorials) { (n: Int, factorial: Int) =>
70+
whenever (n >= 0) {
71+
bizarreFactorial(n) should be (factorial)
72+
}
73+
}
74+
}
75+
}
76+
77+
class OtherFunctionsSpec extends UnitSpec {
78+
"Exercise 5a: take" should "create a new sequence of the first n elements of an existing sequence" in {
79+
1 to 10 take 3 should be (List(1, 2, 3))
80+
}
81+
82+
"Exercise 5b: distinct" should "remove duplicates from an existing sequence" in {
83+
val dupes = Seq(1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6)
84+
dupes.distinct should be (1 to 6)
85+
}
86+
87+
"Exercise 5c: ++" should "concatenate two sequences together" in {
88+
val a = 1 to 3
89+
val b = 4 to 6
90+
a ++ b should be (1 to 6)
91+
}
92+
93+
"Exercise 5d: fill" should "create a sequence containing n copies of the same value" in {
94+
Seq.fill(5)(2) should be (Seq(2, 2, 2, 2, 2))
95+
}
96+
97+
"Exercise 5e: interleave" should "interleave the elements of two sequences together" in {
98+
val evens = Seq(0, 2, 4, 6, 8)
99+
val odds = Seq(1, 3, 5, 7, 9)
100+
evens interleave odds should be (0 to 9)
101+
}
102+
103+
"Exercise 5f.i: drop" should "remove the first n items from the sequence" in {
104+
1 to 10 drop 3 should be (4 to 10)
105+
}
106+
"Exercise 5f.ii: dropRight" should "remove the last n items from the sequence" in {
107+
1 to 10 dropRight 3 should be (1 to 7)
108+
}
109+
110+
"Exercise 5g: flatten" should "turn a sequence of sequences into a sequence containing all of the values of each subsequence" in {
111+
Seq(1 to 3, 4 to 6, 7 to 9).flatten should be (1 to 9)
112+
}
113+
114+
"Exercise 5h: grouped" should "yield an iterator that turns the given sequence into a sequence of subsequences, each n items long" in {
115+
(1 to 9 grouped 3).toSeq should be (Seq(1 to 3, 4 to 6, 7 to 9))
116+
}
117+
118+
"Exercise 5i: forall" should "test whether all items in a sequence meet a certain condition" in {
119+
1 to 9 forall { _ < 10 } should be (true)
120+
}
121+
122+
"Exercise 5j: filterNot" should "remove items meeting a certain criterion from a given sequence" in {
123+
1 to 10 filterNot { _ % 3 == 0 } should be (Seq(1, 2, 4, 5, 7, 8, 10))
124+
}
125+
}
126+
127+
class StartsWithSpec extends UnitSpec {
128+
"Exercise 6: startsWith" should "test whether a sequence begins with the same element of another sequence" in {
129+
(1 to 10) startsWith (1 to 3) should be (true)
130+
}
131+
}
132+
133+
class Tails2Spec extends UnitSpec {
134+
"Exercise 7: tails2" should "return a sequence of successively smaller subsequences of the argument" in {
135+
(1 to 4).tails2 should be (Seq(1 to 4, 2 to 4, 3 to 4, 4 to 4, 4 until 4))
136+
}
137+
"Exercise 7a: tails3" should "return a sequence of successively smaller subsequences of the argument" in {
138+
(1 to 4).tails3 should be (Seq(1 to 4, 2 to 4, 3 to 4, 4 to 4, 4 until 4))
139+
}
140+
}
141+

src/test/scala/fpoo/UnitSpec.scala

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package fpoo
2+
3+
import org.scalatest._
4+
5+
class UnitSpec extends FlatSpec with Matchers with OptionValues with Inside

0 commit comments

Comments
 (0)