Compare commits
	
		
			46 Commits
		
	
	
		
			f66fdac8b4
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b7ca6610fc | |||
| ec0e1e8ae4 | |||
| 5365eabadd | |||
| 43e0694d9d | |||
| c13f9851e3 | |||
| bed771a04e | |||
| 6954695a0d | |||
| a16b70970f | |||
| 34b1ff39ce | |||
| e58c399bad | |||
| 95fdbf7abf | |||
| 17c1e4170d | |||
| d4878015e3 | |||
| f693d69366 | |||
| d8b22157c5 | |||
| 9ad00e6182 | |||
| b53e0677cc | |||
| 056305fd72 | |||
| f4e417571a | |||
| 4eba7f3587 | |||
| 76a4f50075 | |||
| 41c0b80d8b | |||
| 3f648b7fc9 | |||
| 84315955f8 | |||
| bbfcb31026 | |||
| 03c383fb35 | |||
| eebfe377c7 | |||
| 8c01471dda | |||
| 56f41ecc22 | |||
| 2f72fbb599 | |||
| 9eeb59f1e0 | |||
| b18b92fb0b | |||
| e9b68c0913 | |||
| bba0ee90d4 | |||
| 34f88cdf28 | |||
| 1dc768ae51 | |||
| a608a602ad | |||
| 966767f58c | |||
| 7a6168dd50 | |||
| f4d0c9adfa | |||
| 529e6967c4 | |||
| 3d87c132b9 | |||
| 1a567b6b4e | |||
| 53c4036f85 | |||
| 444c83afb2 | |||
| 3c2e6a7175 | 
							
								
								
									
										161
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,161 @@ | |||||||
|  | <h1>205.1 Functional Programming</h1> | ||||||
|  |  | ||||||
|  | <p align="center"> | ||||||
|  |     <img src="icon.svg" width="80" alt="Lambda in the colors of the Scala logo (red)"> | ||||||
|  | </p> | ||||||
|  |  | ||||||
|  | --- | ||||||
|  | <h2>Table of Contents</h2> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | <!-- TOC --> | ||||||
|  |   * [Lessons](#lessons) | ||||||
|  |     * [Lesson 1 - Evaluation](#lesson-1---evaluation) | ||||||
|  |     * [Lesson 2 - Higher order functions](#lesson-2---higher-order-functions) | ||||||
|  |     * [Lesson 3 - Data structures](#lesson-3---data-structures) | ||||||
|  |     * [Lesson 4 - Lists and pattern matching](#lesson-4---lists-and-pattern-matching) | ||||||
|  |     * [Lesson 5 - Advanced lists and High order functions](#lesson-5---advanced-lists-and-high-order-functions) | ||||||
|  |     * [Midterm preparation](#midterm-preparation) | ||||||
|  |     * [Midterm](#midterm) | ||||||
|  |     * [Lesson 6 - Tuples and comprehensions](#lesson-6---tuples-and-comprehensions) | ||||||
|  |     * [Lesson 7 - Advanced typing and infinite lists](#lesson-7---advanced-typing-and-infinite-lists) | ||||||
|  |     * [Lesson 8 - Futures and parallel collections](#lesson-8---futures-and-parallel-collections) | ||||||
|  |     * [Lesson 9 - DSLs](#lesson-9---dsls) | ||||||
|  |     * [Final preparation](#final-exam-preparation) | ||||||
|  |     * [Final](#final-exam) | ||||||
|  |   * [Assignments](#assignments) | ||||||
|  |     * [Assignment 1 - Square root](#assignment-1---square-root) | ||||||
|  |     * [Assignment 2 - Map-reduce](#assignment-2---map-reduce) | ||||||
|  |     * [Assignment 3 - Binary tree](#assignment-3---binary-tree) | ||||||
|  |     * [Assignment 4 - Lists and pattern matching](#assignment-4---lists-and-pattern-matching) | ||||||
|  |     * [Assignment 5 - High-order functions on lists](#assignment-5---high-order-functions-on-lists) | ||||||
|  |     * [Assignment 6 - Sequence comprehension and tuples](#assignment-6---sequence-comprehension-and-tuples) | ||||||
|  |     * [Assignment 7 - Advanced typing and infinite lists](#assignment-7---advanced-typing-and-infinite-lists) | ||||||
|  |     * [Assignment 8 - Advanced typing and infinite lists](#assignment-8---advanced-typing-and-infinite-lists) | ||||||
|  |     * [Assignment 9 - DSLs](#assignment-9---dsls) | ||||||
|  | <!-- TOC --> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ## Lessons | ||||||
|  |  | ||||||
|  | ### Lesson 1 - Evaluation | ||||||
|  | [Files](src/Lesson1) | ||||||
|  | - Call by name / Call by value | ||||||
|  | - State-less functions | ||||||
|  |  | ||||||
|  | ### Lesson 2 - Higher order functions | ||||||
|  | [Files](src/Lesson2) | ||||||
|  | - Curryfication | ||||||
|  | - Recursion | ||||||
|  | - Tail recursion | ||||||
|  |  | ||||||
|  | ### Lesson 3 - Data structures | ||||||
|  | [Files](src/Lesson3) | ||||||
|  | - Functional data structures | ||||||
|  | - Binary tree | ||||||
|  | - Operation precedence | ||||||
|  |  | ||||||
|  | ### Lesson 4 - Lists and pattern matching | ||||||
|  | [Files](src/Lesson4) | ||||||
|  | - List | ||||||
|  | - Pattern matching | ||||||
|  | - Genericity | ||||||
|  |  | ||||||
|  | ### Lesson 5 - Advanced lists and High order functions | ||||||
|  | [Files](src/Lesson5) | ||||||
|  | - Lists | ||||||
|  | - High order functions | ||||||
|  |  | ||||||
|  | ### Midterm preparation | ||||||
|  | [Files](src/MidTermPrep1) | ||||||
|  |  | ||||||
|  | ### Midterm | ||||||
|  | [Files](src/MidTerm1) | ||||||
|  |  | ||||||
|  | ### Lesson 6 - Tuples and comprehensions | ||||||
|  | [Files](src/Lesson6) | ||||||
|  | - Tuples | ||||||
|  | - For-comprehension | ||||||
|  | - Yield | ||||||
|  | - Flatmap | ||||||
|  |  | ||||||
|  | ### Lesson 7 - Advanced typing and infinite lists | ||||||
|  | [Files](src/Lesson7) | ||||||
|  | - Types | ||||||
|  | - Bounds | ||||||
|  | - Traits | ||||||
|  | - Variance, covariance and contra-variance | ||||||
|  | - Infinite sequences | ||||||
|  |  | ||||||
|  | ### Lesson 8 - Futures and parallel collections | ||||||
|  | [Files](src/Lesson8) | ||||||
|  | - Futures | ||||||
|  | - Actors | ||||||
|  | - Parallel collections | ||||||
|  |  | ||||||
|  | ### Lesson 9 - DSLs | ||||||
|  | [Files](src/Lesson9) | ||||||
|  | - DSL | ||||||
|  |  | ||||||
|  | ### Final exam preparation | ||||||
|  | [Files](src/FinalPrep1) | ||||||
|  |  | ||||||
|  | ### Final exam | ||||||
|  | [Files](src/Final1) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Assignments | ||||||
|  |  | ||||||
|  | ### Assignment 1 - Square root | ||||||
|  | [Files](src/Assignment1) | ||||||
|  | - Recursion | ||||||
|  | - Newton | ||||||
|  | - Tail recursion | ||||||
|  |  | ||||||
|  | ### Assignment 2 - Map-reduce | ||||||
|  | [Files](src/Assignment2) | ||||||
|  | - Fibonacci | ||||||
|  | - Sum | ||||||
|  | - Map-reduce | ||||||
|  |  | ||||||
|  | ### Assignment 3 - Binary tree | ||||||
|  | [Files](src/Assignment3) | ||||||
|  | - Int set | ||||||
|  | - Binary tree | ||||||
|  | - Union / intersection / foreach | ||||||
|  |  | ||||||
|  | ### Assignment 4 - Lists and pattern matching | ||||||
|  | [Files](src/Assignment4) | ||||||
|  | - Expression interpreter | ||||||
|  | - Binary tree | ||||||
|  | - List functions | ||||||
|  | - Predicates (any / every) | ||||||
|  |  | ||||||
|  | ### Assignment 5 - High-order functions on lists | ||||||
|  | [Files](src/Assignment5) | ||||||
|  | - High-order functions | ||||||
|  | - Lists | ||||||
|  | - Map | ||||||
|  | - Fold | ||||||
|  | - Zip | ||||||
|  |  | ||||||
|  | ### Assignment 6 - Sequence comprehension and tuples | ||||||
|  | [Files](src/Assignment6) | ||||||
|  | - Tuples | ||||||
|  | - `for` comprehension | ||||||
|  |  | ||||||
|  | ### Assignment 7 - Advanced typing and infinite lists | ||||||
|  | [Files](src/Assignment7) | ||||||
|  | - Genericity | ||||||
|  | - Infinite lazy lists | ||||||
|  |  | ||||||
|  | ### Assignment 8 - Advanced typing and infinite lists | ||||||
|  | [Files](src/Assignment8) | ||||||
|  | - Parallel collections | ||||||
|  | - Futures | ||||||
|  |  | ||||||
|  | ### Assignment 9 - DSLs | ||||||
|  | [Files](src/Assignment9) | ||||||
|  | - DSL | ||||||
							
								
								
									
										126
									
								
								icon.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								icon.svg
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||||
|  |  | ||||||
|  | <svg | ||||||
|  |    width="128" | ||||||
|  |    height="128" | ||||||
|  |    viewBox="0 0 128 128" | ||||||
|  |    version="1.1" | ||||||
|  |    id="svg1" | ||||||
|  |    sodipodi:docname="icon.svg" | ||||||
|  |    inkscape:version="1.4 (e7c3feb100, 2024-10-09)" | ||||||
|  |    inkscape:export-filename="icon.png" | ||||||
|  |    inkscape:export-xdpi="96" | ||||||
|  |    inkscape:export-ydpi="96" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns:xlink="http://www.w3.org/1999/xlink" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg"> | ||||||
|  |   <sodipodi:namedview | ||||||
|  |      id="namedview1" | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#000000" | ||||||
|  |      borderopacity="0.25" | ||||||
|  |      inkscape:showpageshadow="2" | ||||||
|  |      inkscape:pageopacity="0.0" | ||||||
|  |      inkscape:pagecheckerboard="0" | ||||||
|  |      inkscape:deskcolor="#d1d1d1" | ||||||
|  |      inkscape:document-units="mm" | ||||||
|  |      showgrid="true" | ||||||
|  |      inkscape:zoom="5.7798541" | ||||||
|  |      inkscape:cx="63.928949" | ||||||
|  |      inkscape:cy="68.773362" | ||||||
|  |      inkscape:window-width="1920" | ||||||
|  |      inkscape:window-height="1016" | ||||||
|  |      inkscape:window-x="0" | ||||||
|  |      inkscape:window-y="27" | ||||||
|  |      inkscape:window-maximized="1" | ||||||
|  |      inkscape:current-layer="layer1"> | ||||||
|  |     <inkscape:grid | ||||||
|  |        id="grid3" | ||||||
|  |        units="px" | ||||||
|  |        originx="0" | ||||||
|  |        originy="0" | ||||||
|  |        spacingx="1" | ||||||
|  |        spacingy="1" | ||||||
|  |        empcolor="#0099e5" | ||||||
|  |        empopacity="0.30196078" | ||||||
|  |        color="#0099e5" | ||||||
|  |        opacity="0.14901961" | ||||||
|  |        empspacing="16" | ||||||
|  |        enabled="true" | ||||||
|  |        visible="true" /> | ||||||
|  |   </sodipodi:namedview> | ||||||
|  |   <defs | ||||||
|  |      id="defs1"> | ||||||
|  |     <linearGradient | ||||||
|  |        id="linearGradient10" | ||||||
|  |        inkscape:collect="always"> | ||||||
|  |       <stop | ||||||
|  |          style="stop-color:#4e4e4e;stop-opacity:1;" | ||||||
|  |          offset="0" | ||||||
|  |          id="stop10" /> | ||||||
|  |       <stop | ||||||
|  |          style="stop-color:#000000;stop-opacity:1;" | ||||||
|  |          offset="1" | ||||||
|  |          id="stop11" /> | ||||||
|  |     </linearGradient> | ||||||
|  |     <linearGradient | ||||||
|  |        id="linearGradient8" | ||||||
|  |        inkscape:collect="always"> | ||||||
|  |       <stop | ||||||
|  |          style="stop-color:#c40000;stop-opacity:1;" | ||||||
|  |          offset="0" | ||||||
|  |          id="stop8" /> | ||||||
|  |       <stop | ||||||
|  |          style="stop-color:#ff0000;stop-opacity:1;" | ||||||
|  |          offset="1" | ||||||
|  |          id="stop9" /> | ||||||
|  |     </linearGradient> | ||||||
|  |     <rect | ||||||
|  |        x="37.92537" | ||||||
|  |        y="44.042365" | ||||||
|  |        width="295.5732" | ||||||
|  |        height="25.93606" | ||||||
|  |        id="rect1" /> | ||||||
|  |     <linearGradient | ||||||
|  |        inkscape:collect="always" | ||||||
|  |        xlink:href="#linearGradient8" | ||||||
|  |        id="linearGradient9" | ||||||
|  |        x1="18.422545" | ||||||
|  |        y1="64" | ||||||
|  |        x2="109.57747" | ||||||
|  |        y2="64" | ||||||
|  |        gradientUnits="userSpaceOnUse" | ||||||
|  |        gradientTransform="translate(-1.999545,-1)" /> | ||||||
|  |     <linearGradient | ||||||
|  |        inkscape:collect="always" | ||||||
|  |        xlink:href="#linearGradient10" | ||||||
|  |        id="linearGradient11" | ||||||
|  |        x1="18.422545" | ||||||
|  |        y1="64" | ||||||
|  |        x2="109.57746" | ||||||
|  |        y2="64" | ||||||
|  |        gradientUnits="userSpaceOnUse" /> | ||||||
|  |   </defs> | ||||||
|  |   <g | ||||||
|  |      inkscape:label="Layer 1" | ||||||
|  |      inkscape:groupmode="layer" | ||||||
|  |      id="layer1"> | ||||||
|  |     <g | ||||||
|  |        id="g11" | ||||||
|  |        transform="matrix(1.2023042,0,0,1.2023042,-11.745442,-12.346318)"> | ||||||
|  |       <path | ||||||
|  |          style="fill:url(#linearGradient11);fill-opacity:1;stroke:none;stroke-width:1.99937;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 60.310857,20 H 34.422545 v 16 h 16 l 8,16 -40,48 H 37.503412 L 65.57787,66.310651 86.422545,108 109.57746,96.422544 l -7.15534,-14.310651 -8.844251,4.42213 z" | ||||||
|  |          id="path3" | ||||||
|  |          sodipodi:nodetypes="ccccccccccccc" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:url(#linearGradient9);stroke:none;stroke-width:1.99937;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 58.311312,19 H 32.423 v 16 h 16 l 8,16 -40,48 H 35.503867 L 63.578325,65.310651 84.423,107 l 23.15493,-11.577456 -7.15534,-14.310651 -8.84427,4.42213 z" | ||||||
|  |          id="path3-7" | ||||||
|  |          sodipodi:nodetypes="ccccccccccccc" /> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 3.8 KiB | 
							
								
								
									
										90
									
								
								src/Assignment3/IntSet.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/Assignment3/IntSet.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | |||||||
|  | abstract class IntSet() { | ||||||
|  |   def add(x: Int): IntSet | ||||||
|  |   def contains(x: Int): Boolean | ||||||
|  |   def foreach(f: Int => Unit): Unit | ||||||
|  |   def union(other: IntSet): IntSet | ||||||
|  |   def intersect(other: IntSet): IntSet | ||||||
|  |   def excl(x: Int): IntSet | ||||||
|  |   def +(x: Int): IntSet = this.add(x) | ||||||
|  |   def -(x: Int): IntSet = this.excl(x) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class NonEmpty(elem: Int, left: IntSet, right: IntSet) extends IntSet() { | ||||||
|  |   def add(x: Int): IntSet = { | ||||||
|  |     if (x < elem) new NonEmpty(elem, left add x, right) | ||||||
|  |     else if (x > elem) new NonEmpty(elem, left, right add x) | ||||||
|  |     else this | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def contains(x: Int): Boolean = | ||||||
|  |     if (x < elem) left contains x | ||||||
|  |     else if (x > elem) right contains x | ||||||
|  |     else true | ||||||
|  |  | ||||||
|  |   override def toString = "(" + left + "|" + elem + "|" + right + ")" | ||||||
|  |  | ||||||
|  |   def foreach(f: Int => Unit): Unit = { | ||||||
|  |     left.foreach(f) | ||||||
|  |     f(elem) | ||||||
|  |     right.foreach(f) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def union(other: IntSet): IntSet = | ||||||
|  |     this.left.union(right) | ||||||
|  |              .union(other) | ||||||
|  |              .add(this.elem) | ||||||
|  |  | ||||||
|  |   def intersect(other: IntSet): IntSet = { | ||||||
|  |     val base = if (other.contains(this.elem)) Empty.add(this.elem) | ||||||
|  |                else Empty | ||||||
|  |     base.union(this.left.intersect(other)) | ||||||
|  |         .union(this.right.intersect(other)) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def excl(x: Int): IntSet = { | ||||||
|  |     if (x < elem) new NonEmpty(elem, this.left.excl(x), this.right) | ||||||
|  |     else if (x > elem) new NonEmpty(elem, this.left, this.right.excl(x)) | ||||||
|  |     else this.left.union(this.right) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | object Empty extends IntSet() { | ||||||
|  |   def add(x: Int): IntSet = new NonEmpty(x, Empty, Empty) | ||||||
|  |   def contains(x: Int): Boolean = false | ||||||
|  |   override def toString = "-" | ||||||
|  |  | ||||||
|  |   def foreach(f: Int => Unit): Unit = {} | ||||||
|  |   def union(other: IntSet): IntSet = other | ||||||
|  |   def intersect(other: IntSet): IntSet = Empty | ||||||
|  |   def excl(x: Int): IntSet = this | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val t1 = Empty | ||||||
|  | val t2 = t1 add 3 | ||||||
|  | val t3 = t1 add 4 add 5 add 2 add 6 | ||||||
|  | t3 contains 4 | ||||||
|  |  | ||||||
|  | println(Empty)                  // prints - | ||||||
|  | println(Empty.add(3))           // prints (-|3|-) | ||||||
|  | println(Empty.add(3).add(2))    // prints ((-|2|-)|3|-) | ||||||
|  |  | ||||||
|  | val s = Empty.add(3).add(2).add(7).add(1) | ||||||
|  | s.foreach(println) | ||||||
|  |  | ||||||
|  | (Empty.add(3).add(2).add(6).add(1)) foreach (x => print(x+1 + ", ")) | ||||||
|  | // 2, 3, 4, 7, | ||||||
|  | // Because a BST is always sorted | ||||||
|  |  | ||||||
|  | val s2 = Empty.add(3).add(4).add(6).add(2) | ||||||
|  |  | ||||||
|  | s.union(s2) | ||||||
|  | s.intersect(s2) | ||||||
|  |  | ||||||
|  | s2.excl(0) | ||||||
|  | s2.excl(6) | ||||||
|  | s2.excl(2) | ||||||
|  | s2.excl(4) | ||||||
|  |  | ||||||
|  | val o1 = Empty + 3 + 4 + 12 + 5 | ||||||
|  | val o2 = (o1 - 3 - 4) | ||||||
|  | o2  // ((-|5|-)|12|-) | ||||||
							
								
								
									
										60
									
								
								src/Assignment4/Ex1_Expressions.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/Assignment4/Ex1_Expressions.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | |||||||
|  | sealed abstract class Expr | ||||||
|  | case class Number(n: Int) extends Expr | ||||||
|  | case class Sum(e1: Expr, e2: Expr) extends Expr | ||||||
|  | case class Product(e1: Expr, e2: Expr) extends Expr | ||||||
|  |  | ||||||
|  | def eval(e: Expr): Int = e match { | ||||||
|  |   case Number(n) => n | ||||||
|  |   case Sum(e1, e2) => eval(e1) + eval(e2) | ||||||
|  |   case Product(e1, e2) => eval(e1) * eval(e2) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def show(e: Expr): String = e match { | ||||||
|  |   case Number(n) => n.toString | ||||||
|  |   case Sum(e1, e2) => show(e1) + " + " + show(e2) | ||||||
|  |   case Product(e1, e2) => { | ||||||
|  |     val left: String = e1 match { | ||||||
|  |       case Sum(e1a, e1b) => "(" + show(e1) + ")" | ||||||
|  |       case _ => show(e1) | ||||||
|  |     } | ||||||
|  |     val right: String = e2 match { | ||||||
|  |       case Sum(e2a, e2b) => "(" + show(e2) + ")" | ||||||
|  |       case _ => show(e2) | ||||||
|  |     } | ||||||
|  |     left + " * " + right | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val e1: Expr = Sum(Number(1), Sum(Number(2), Number(3))) | ||||||
|  | eval(e1) | ||||||
|  | show(e1) | ||||||
|  |  | ||||||
|  | val e2: Expr = Sum( | ||||||
|  |   Number(2), | ||||||
|  |   Product( | ||||||
|  |     Number(3), | ||||||
|  |     Sum( | ||||||
|  |       Number(4), | ||||||
|  |       Number(5) | ||||||
|  |     ) | ||||||
|  |   ) | ||||||
|  | ) | ||||||
|  | eval(e2) | ||||||
|  | show(e2) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | val expr0 = Sum(Product(Number(2), Number(3)), Number(4)) | ||||||
|  | println("Expr0: " + show(expr0))  // Expr0: 2*3+4 | ||||||
|  | assert(eval(expr0) == 10) | ||||||
|  |  | ||||||
|  | val expr1 = Product(Number(4), Number(12)) | ||||||
|  | println("Expr1: " + show(expr1))  // Expr1: 4*12 | ||||||
|  | assert(eval(expr1) == 48) | ||||||
|  |  | ||||||
|  | val expr2 = Product(Sum(Number(2), Number(3)), Number(4)) | ||||||
|  | println("Expr2: " + show(expr2))  // Expr2: (2+3)*4 | ||||||
|  | assert(eval(expr2) == 20) | ||||||
|  |  | ||||||
|  | val expr3 = Product(Number(2), Sum(Number(3), Number(4))) | ||||||
|  | println("Expr3: " + show(expr3))  // Expr3: 2*(3+4) | ||||||
|  | assert(eval(expr3) == 14) | ||||||
							
								
								
									
										22
									
								
								src/Assignment4/Ex2_Trees.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/Assignment4/Ex2_Trees.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | sealed abstract class BinaryTree | ||||||
|  | case class Leaf(value: Int) extends BinaryTree | ||||||
|  | case class Node(left: BinaryTree, right: BinaryTree) extends BinaryTree | ||||||
|  |  | ||||||
|  | def leafSum(tree: BinaryTree): Int = { | ||||||
|  |   tree match { | ||||||
|  |     case Leaf(value) => value | ||||||
|  |     case Node(left, right) => leafSum(left) + leafSum(right) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def min(a: Int, b: Int): Int = if (a < b) a else b | ||||||
|  | def smallest(tree: BinaryTree): Int = { | ||||||
|  |   tree match { | ||||||
|  |     case Leaf(value) => value | ||||||
|  |     case Node(left, right) => min(smallest(left), smallest(right)) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | assert(leafSum(Node(Node(Leaf(3), Leaf(8)), Leaf(5))) == 16) | ||||||
|  |  | ||||||
|  | assert(smallest(Node(Node(Leaf(3), Leaf(5)), Leaf(-5))) == -5) | ||||||
							
								
								
									
										64
									
								
								src/Assignment4/Ex3_Lists.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/Assignment4/Ex3_Lists.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | import scala.annotation.tailrec | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Complexity: O(n) | ||||||
|  | @tailrec | ||||||
|  | def last[T](list: List[T]): T = { | ||||||
|  |   if (list.isEmpty) throw new NoSuchElementException() | ||||||
|  |   if (list.tail.isEmpty) list.head | ||||||
|  |   else last(list.tail) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def init[T](list: List[T]): List[T] = { | ||||||
|  |   if (list.isEmpty) list | ||||||
|  |   else if (list.tail.isEmpty) Nil | ||||||
|  |   else list.head::init(list.tail) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Complexity: O(n) | ||||||
|  | def concat[T](l1: List[T], l2: List[T]): List[T] = { | ||||||
|  |   if (l1.isEmpty) l2 | ||||||
|  |   else l1.head::concat(l1.tail, l2) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Complexity: O(n²) | ||||||
|  | def reverse[T](list: List[T]): List[T] = { | ||||||
|  |   if (list.isEmpty) Nil | ||||||
|  |   else last(list)::reverse(init(list)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Better -> O(n) | ||||||
|  | /* | ||||||
|  | def reverse[T](list: List[T], res: List[T] = Nil): List[T] = { | ||||||
|  |   if (list.isEmpty) res | ||||||
|  |   else reverse(list.tail, list.head::res) | ||||||
|  | } | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | def take[T](list: List[T], n: Int): List[T] = { | ||||||
|  |   if (list.isEmpty || n <= 0) Nil | ||||||
|  |   else list.head::take(list.tail, n - 1) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @tailrec | ||||||
|  | def drop[T](list: List[T], n: Int): List[T] = { | ||||||
|  |   if (list.isEmpty || n <= 0) list | ||||||
|  |   else drop(list.tail, n - 1) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @tailrec | ||||||
|  | def apply[T](list: List[T], n: Int): T = { | ||||||
|  |   if (list.isEmpty) throw new NoSuchElementException() | ||||||
|  |   else if (n == 0) list.head | ||||||
|  |   else apply(list.tail, n - 1) | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | assert(last(List(1,2,3)) == 3) | ||||||
|  | assert(init(List(1,2,3)) == List(1,2)) | ||||||
|  | assert(concat(List(1,2,3), List(4,5,6)) == List(1,2,3,4,5,6)) | ||||||
|  | assert(reverse(List(1,2,3)) == List(3,2,1)) | ||||||
|  | assert(take(List(1,2,3), 2) == List(1,2)) | ||||||
|  | assert(drop(List(1,2,3), 2) == List(3)) | ||||||
|  | assert(drop(List(1,2,3), 4) == Nil) | ||||||
|  | assert(apply(List(1,2,3), 2) == 3) | ||||||
							
								
								
									
										79
									
								
								src/Assignment4/Ex3_ListsMatch.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/Assignment4/Ex3_ListsMatch.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | |||||||
|  | import scala.annotation.tailrec | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Complexity: O(n) | ||||||
|  | @tailrec | ||||||
|  | def last[T](list: List[T]): T = { | ||||||
|  |   list.tail match { | ||||||
|  |     case Nil => list.head | ||||||
|  |     case _ => last(list.tail) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def init[T](list: List[T]): List[T] = { | ||||||
|  |   list.tail match { | ||||||
|  |     case Nil => Nil | ||||||
|  |     case _ => list.head::init(list.tail) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Complexity: O(n) | ||||||
|  | def concat[T](l1: List[T], l2: List[T]): List[T] = { | ||||||
|  |   l1 match { | ||||||
|  |     case Nil => l2 | ||||||
|  |     case _ => l1.head::concat(l1.tail, l2) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Complexity: O(n²) | ||||||
|  | def reverse[T](list: List[T]): List[T] = { | ||||||
|  |   list match { | ||||||
|  |     case Nil => Nil | ||||||
|  |     case _ => last(list)::reverse(init(list)) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Better -> O(n) | ||||||
|  | /* | ||||||
|  | def reverse[T](list: List[T], res: List[T] = Nil): List[T] = { | ||||||
|  |   list match { | ||||||
|  |     case Nil => res | ||||||
|  |     case _ => reverse(list.tail, list.head::res) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | def take[T](list: List[T], n: Int): List[T] = { | ||||||
|  |   if (n <= 0) Nil | ||||||
|  |   else list match { | ||||||
|  |     case Nil => Nil | ||||||
|  |     case _ => list.head::take(list.tail, n - 1) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @tailrec | ||||||
|  | def drop[T](list: List[T], n: Int): List[T] = { | ||||||
|  |   if (n <= 0) list | ||||||
|  |   else list match { | ||||||
|  |     case Nil => list | ||||||
|  |     case _ => drop(list.tail, n - 1) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @tailrec | ||||||
|  | def apply[T](list: List[T], n: Int): T = { | ||||||
|  |   n match { | ||||||
|  |     case 0 => list.head | ||||||
|  |     case _ => apply(list.tail, n - 1) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | assert(last(List(1,2,3)) == 3) | ||||||
|  | assert(init(List(1,2,3)) == List(1,2)) | ||||||
|  | assert(concat(List(1,2,3), List(4,5,6)) == List(1,2,3,4,5,6)) | ||||||
|  | assert(reverse(List(1,2,3)) == List(3,2,1)) | ||||||
|  | assert(take(List(1,2,3), 2) == List(1,2)) | ||||||
|  | assert(drop(List(1,2,3), 2) == List(3)) | ||||||
|  | assert(drop(List(1,2,3), 4) == Nil) | ||||||
|  | assert(apply(List(1,2,3), 2) == 3) | ||||||
							
								
								
									
										24
									
								
								src/Assignment4/Ex4_Predicates.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/Assignment4/Ex4_Predicates.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | import scala.annotation.tailrec | ||||||
|  |  | ||||||
|  | @tailrec | ||||||
|  | def any[T](p: T => Boolean)(l: List[T]): Boolean = { | ||||||
|  |   if (l.isEmpty) false | ||||||
|  |   else if (p(l.head)) true | ||||||
|  |   else any(p)(l.tail) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @tailrec | ||||||
|  | def every[T](p: T => Boolean)(l: List[T]): Boolean = { | ||||||
|  |   if (l.isEmpty) true | ||||||
|  |   else if (!p(l.head)) false | ||||||
|  |   else every(p)(l.tail) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val a = List(1, 2, 3, 4, 5) | ||||||
|  | assert(!any((x: Int) => x == 12)(a)) | ||||||
|  | assert(any((x: Int) => x > 4)(a)) | ||||||
|  |  | ||||||
|  | val a = List(1, 2, 3, 4, 5) | ||||||
|  | val b = List(2, 4, 6, 8, 10) | ||||||
|  | assert(!every((x: Int) => (x % 2) == 0)(a)) | ||||||
|  | assert(every((x: Int) => (x % 2) == 0)(b)) | ||||||
							
								
								
									
										36
									
								
								src/Assignment5/Folds.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/Assignment5/Folds.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | def areTrue(booleans: List[Boolean]): Boolean = { | ||||||
|  |   booleans.foldLeft(true)((acc, value) => acc && value) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def lString(strings: List[String]): Int = { | ||||||
|  |   strings.foldLeft(0)((len, str) => len + str.length) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def longest(strings: List[String]): Int = { | ||||||
|  |   strings.foldLeft(0)((maxLen, str) => if (str.length > maxLen) str.length else maxLen) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def isPresent[T](list: List[T], target: T): Boolean = { | ||||||
|  |   list.foldLeft(false)((res, value) => res || value == target) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def flattenList(list: List[Any]): List[Any] = { | ||||||
|  |   list.foldRight(List.empty[Any])((elem, acc) => { | ||||||
|  |     elem match { | ||||||
|  |       case l: List[Any] => flattenList(l).foldRight(acc)((e, l) => e::l) | ||||||
|  |       case _ => elem::acc | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | assert(!areTrue(List(true, true, false))) | ||||||
|  | assert(areTrue(List(true, true, true))) | ||||||
|  |  | ||||||
|  | assert(lString(List("Folding", "is", "fun")) == 12) | ||||||
|  |  | ||||||
|  | assert(longest(List("What", "is", "the", "longest?")) == 8) | ||||||
|  |  | ||||||
|  | assert(!isPresent(List(1, 2, 3, 4), 5)) | ||||||
|  | assert(isPresent(List(1, 2, 3, 4), 3)) | ||||||
|  |  | ||||||
|  | assert(flattenList(List(List(1, 1), 2, List(3, List(5, 8)))) == List(1, 1, 2, 3, 5, 8)) | ||||||
							
								
								
									
										18
									
								
								src/Assignment5/HOFOnLists.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/Assignment5/HOFOnLists.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | def lengthStrings(strings: List[String]): List[Int] = { | ||||||
|  |   strings map (s => s.length) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def dup[T](elem: T, n: Int): List[T] = { | ||||||
|  |   (1 to n).toList map (_ => elem) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def dot(list1: List[Int], list2: List[Int]): List[Int] = { | ||||||
|  |   list1 zip list2 map (p => p._1 * p._2) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | assert(lengthStrings(List("How","long","are","we?")) == List(3, 4, 3, 3)) | ||||||
|  |  | ||||||
|  | assert(dup("foo", 5) == List("foo", "foo", "foo", "foo", "foo")) | ||||||
|  | assert(dup(List(1,2,3), 2) == List(List(1,2,3), List(1,2,3))) | ||||||
|  |  | ||||||
|  | assert(dot(List(1,2,3), List(2,4,3)) == List(2,8,9)) | ||||||
							
								
								
									
										17
									
								
								src/Assignment6/Ex1.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/Assignment6/Ex1.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | def flattenList(list: List[Any]): List[Any] = { | ||||||
|  |   list.foldRight(List.empty[Any])( | ||||||
|  |     (e, acc) => { | ||||||
|  |       e match { | ||||||
|  |         case l: List[Any] => flattenList(l) concat acc | ||||||
|  |         case _ => e::acc | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   ) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | assert( | ||||||
|  |   flattenList( | ||||||
|  |     List(List(1,1), 2, List(3, List(5, 8))) | ||||||
|  |   ) == List(1,1,2,3,5,8) | ||||||
|  | ) | ||||||
|  |  | ||||||
							
								
								
									
										38
									
								
								src/Assignment6/Ex2.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/Assignment6/Ex2.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  |  | ||||||
|  | def isPrime(i: Int): Boolean = | ||||||
|  |     i match { | ||||||
|  |         case i if i <= 1 => false | ||||||
|  |         case 2 => true | ||||||
|  |         case _ => !(2 to (i - 1)).exists(x => i % x == 0) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | def primeSum(max: Int): List[(Int, Int)] = | ||||||
|  |     for { | ||||||
|  |         i <- (1 to max).toList | ||||||
|  |         j <- (1 to max).toList | ||||||
|  |         if (isPrime(i + j)) | ||||||
|  |     } yield (i, j) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def uniquePermutations(permutations: List[(Int, Int)]): List[(Int, Int)] = { | ||||||
|  |   permutations match { | ||||||
|  |     case Nil => Nil | ||||||
|  |     case (a, b)::rest if rest contains(b, a) => uniquePermutations(rest) | ||||||
|  |     case head::rest => head::uniquePermutations(rest) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def uniquePermutations2(permutations: List[(Int, Int)]): List[(Int, Int)] = { | ||||||
|  |   permutations.foldRight(List.empty[(Int, Int)])( | ||||||
|  |     (e, acc) => { | ||||||
|  |       e match { | ||||||
|  |         case (a, b) if acc contains (b, a) => acc | ||||||
|  |         case _ => e::acc | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   ) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val perms = primeSum(10) | ||||||
|  | uniquePermutations(perms) | ||||||
|  | uniquePermutations2(perms) | ||||||
							
								
								
									
										22
									
								
								src/Assignment6/Ex3.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/Assignment6/Ex3.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | val cities = List("Paris", "London", "Berlin", "Lausanne") | ||||||
|  | val relatives = List("Grandma", "Grandpa", "Aunt Lottie", "Dad") | ||||||
|  | val travellers = List("Pierre-Andre", "Rachel") | ||||||
|  |  | ||||||
|  | def generatePostcards(cities: List[String], relatives: List[String], travellers: List[String]): List[String] = { | ||||||
|  |   for (t <- travellers; | ||||||
|  |        r <- relatives; | ||||||
|  |        c <- cities) yield s"Dear $r, Wish you were here in $c! Love, $t" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def generatePostcards2(cities: List[String], relatives: List[String], travellers: List[String]): List[String] = { | ||||||
|  |   for (t <- travellers; | ||||||
|  |        r <- relatives; | ||||||
|  |        c <- cities; | ||||||
|  |        if r.startsWith("G")) yield s"Dear $r, Wish you were here in $c! Love, $t" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val cards: List[String] = generatePostcards(cities, relatives, travellers) | ||||||
|  | println(cards.mkString("\n")) | ||||||
|  |  | ||||||
|  | val cards2: List[String] = generatePostcards2(cities, relatives, travellers) | ||||||
|  | println(cards2.mkString("\n")) | ||||||
							
								
								
									
										39
									
								
								src/Assignment6/Ex4.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/Assignment6/Ex4.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | def inCheck(q1: (Int, Int), q2: (Int, Int)) = | ||||||
|  |     q1._1 == q2._1 || // same row | ||||||
|  |     q1._2 == q2._2 || // same column | ||||||
|  |     (q1._1 - q2._1).abs == (q1._2 - q2._2).abs // on diagonal | ||||||
|  |  | ||||||
|  | def isSafe(queen: (Int, Int), queens: List[(Int, Int)]) = | ||||||
|  |     queens forall (q => !inCheck(queen, q)) | ||||||
|  |  | ||||||
|  | def queens(n: Int): List[List[(Int, Int)]] = { | ||||||
|  |     def placeQueens(k: Int): List[List[(Int, Int)]] = | ||||||
|  |         if (k == 0) | ||||||
|  |             List(List()) | ||||||
|  |         else | ||||||
|  |             for { | ||||||
|  |                 queens <- placeQueens(k - 1) | ||||||
|  |                 column <- 1 to n | ||||||
|  |                 queen = (k, column) | ||||||
|  |                 if isSafe(queen, queens) | ||||||
|  |             } yield queen :: queens | ||||||
|  |  | ||||||
|  |     placeQueens(n) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def printChessBoard(solutions: List[List[(Int, Int)]]): String = { | ||||||
|  |   val sols: List[String] = for ((sol, i) <- solutions.zipWithIndex) yield { | ||||||
|  |     val lines: IndexedSeq[String] = for (y <- 1 to sol.length) yield { | ||||||
|  |       val line: IndexedSeq[String] = { | ||||||
|  |         for (x <- 1 to sol.length) yield { | ||||||
|  |           if (sol contains (y, x)) "♕" else "_" | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       line.mkString("|", "|", "|") | ||||||
|  |     } | ||||||
|  |     s"Solution $i:\n" + lines.mkString("\n") | ||||||
|  |   } | ||||||
|  |   sols.mkString("\n\n") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | println(printChessBoard(queens(4))) | ||||||
							
								
								
									
										35
									
								
								src/Assignment7/Ex1.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/Assignment7/Ex1.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | trait Stack[+A] { | ||||||
|  |     def push[B >: A](elem: B) : Stack[B] = ElemStack(elem, this) | ||||||
|  |     def top: A | ||||||
|  |     def pop: Stack[A] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | case class EmptyStack[+A]() extends Stack[A] { | ||||||
|  |   override def top: A = throw new IndexOutOfBoundsException("Stack is empty") | ||||||
|  |   override def pop: Stack[A] = this | ||||||
|  | } | ||||||
|  |  | ||||||
|  | case class ElemStack[+A](elmt: A, base: Stack[A]) extends Stack[A] { | ||||||
|  |   override def top: A = elmt | ||||||
|  |   override def pop: Stack[A] = base | ||||||
|  |   override def toString: String = elmt.toString + "," + base.toString | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Construction, pop and toString | ||||||
|  | val a = EmptyStack().push("hello").push("world").push("it's fun").pop | ||||||
|  | assert(a.toString() == "world,hello,EmptyStack()") | ||||||
|  |  | ||||||
|  | // Getting top | ||||||
|  | val b = EmptyStack().push(1).push(3) | ||||||
|  | assert(b.top == 3) | ||||||
|  |  | ||||||
|  | // Variance checks | ||||||
|  | class Foo | ||||||
|  | class Bar extends Foo | ||||||
|  | val c: Stack[Bar] = EmptyStack().push(new Bar()).push(new Bar()) | ||||||
|  | assert(c.top.isInstanceOf[Bar] == true) | ||||||
|  | assert(c.top.isInstanceOf[Foo] == true) | ||||||
|  |  | ||||||
|  | // Variance check 2 | ||||||
|  | val d: Stack[Foo] = EmptyStack().push(new Bar()).push(new Bar()) | ||||||
|  | assert(d.top.isInstanceOf[Foo]) | ||||||
							
								
								
									
										9
									
								
								src/Assignment7/Ex2.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/Assignment7/Ex2.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | def intsFrom(n: Int): LazyList[Int] = { | ||||||
|  |   n #:: intsFrom(n + 1) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def primeNumbers(list: LazyList[Int]): LazyList[Int] = { | ||||||
|  |   list.head #:: primeNumbers(list.tail.filter(n => n % list.head != 0)) | ||||||
|  | } | ||||||
|  | val ints: LazyList[Int] = intsFrom(2) | ||||||
|  | primeNumbers(ints).take(10).toList | ||||||
							
								
								
									
										12
									
								
								src/Assignment7/Ex3.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/Assignment7/Ex3.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | def addStream(s1: LazyList[Int], s2: LazyList[Int]): LazyList[Int] = { | ||||||
|  |   s1 zip s2 map (p => p._1 + p._2) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def fibonacci(): LazyList[Int] = { | ||||||
|  |   0 #:: 1 #:: addStream( | ||||||
|  |     fibonacci(), | ||||||
|  |     fibonacci().tail | ||||||
|  |   ) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fibonacci().take(10).toList | ||||||
							
								
								
									
										19
									
								
								src/Assignment7/Ex4.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/Assignment7/Ex4.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  |  | ||||||
|  | def THRESHOLD: Double = 0.0001 | ||||||
|  |  | ||||||
|  | def sqr(x: Double): Double = x * x | ||||||
|  |  | ||||||
|  | def sqrt_stream(value: Double): LazyList[Double] = { | ||||||
|  |   def helper(target: Double, approx: Double): LazyList[Double] = { | ||||||
|  |     approx #:: helper(target, approx - (sqr(approx) - target) / (2 * approx)) | ||||||
|  |   } | ||||||
|  |   helper(value, value) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | sqrt_stream(2).take(10).toList | ||||||
|  |  | ||||||
|  | def threshold(list: LazyList[Double], thresh: Double) = { | ||||||
|  |   list.zip(list.drop(1)).filter(p => math.abs(p._2 - p._1) < thresh).head._2 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | threshold(sqrt_stream(2), 1e-15) | ||||||
							
								
								
									
										26
									
								
								src/Assignment7/Ex5.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/Assignment7/Ex5.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | /* | ||||||
|  | 1 | ||||||
|  | 1 1 | ||||||
|  | 2 1 | ||||||
|  | 1 2 1 1 | ||||||
|  | 1 1 1 2 2 1 | ||||||
|  | 3 1 2 2 1 1 | ||||||
|  | Next : | ||||||
|  | 1 3 1 1 2 2 2 1 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | def nextLine(current: List[Int]) : List[Int] = { | ||||||
|  |   current.foldRight(List.empty[(Int, Int)])((x, acc) => { | ||||||
|  |     (x, acc) match { | ||||||
|  |       case (a, p :: rest) if a == p._2 => (p._1 + 1, p._2) :: rest | ||||||
|  |       case _ => (1, x) :: acc | ||||||
|  |     } | ||||||
|  |   }).flatten(p => List(p._1, p._2)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def makeSequence(start: List[Int]): LazyList[List[Int]] = { | ||||||
|  |   start #:: makeSequence(nextLine(start)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | lazy val sequence: LazyList[List[Int]] = makeSequence(List(1)) | ||||||
|  | sequence.take(7).toList | ||||||
							
								
								
									
										24
									
								
								src/Assignment8/Ex1.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/Assignment8/Ex1.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | package Assignment8 | ||||||
|  |  | ||||||
|  | import utils.timeVerbose | ||||||
|  |  | ||||||
|  | import scala.collection.parallel.CollectionConverters._ | ||||||
|  |  | ||||||
|  | object Ex1 extends App { | ||||||
|  |   def integrate(a: Double, b: Double, nIntervals: Int, f: (Double => Double)): Double = { | ||||||
|  |     val dx: Double = (b - a) / nIntervals | ||||||
|  |     //val y: Double = (1 until nIntervals).map(i => f(i * dx + a)).sum | ||||||
|  |     //val y: Double = (1 until nIntervals).view.map(i => f(i * dx + a)).sum | ||||||
|  |     val y: Double = (1 until nIntervals).par.map(i => f(i * dx + a)).sum | ||||||
|  |     return (2 * y + f(a) + f(b)) * dx / 2 | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   println(integrate(1, 2, 500, math.sin)) | ||||||
|  |  | ||||||
|  |   println(integrate(0, 1, 500, math.sin _ compose math.cos)) | ||||||
|  |  | ||||||
|  |   timeVerbose { | ||||||
|  |     val i = integrate(0, 1, math.pow(20, 6).toInt, math.sin) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										62
									
								
								src/Assignment8/Ex2.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/Assignment8/Ex2.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | package Assignment8 | ||||||
|  |  | ||||||
|  | import net.liftweb.json | ||||||
|  | import net.liftweb.json.DefaultFormats | ||||||
|  |  | ||||||
|  | import java.net.URI | ||||||
|  | import scala.concurrent.duration.Duration | ||||||
|  | import scala.concurrent.{Await, Future} | ||||||
|  | import scala.sys.process._ | ||||||
|  | import scala.util.{Failure, Success} | ||||||
|  |  | ||||||
|  | object Ex2 extends App { | ||||||
|  |   implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global | ||||||
|  |   implicit val formats: DefaultFormats.type = DefaultFormats | ||||||
|  |  | ||||||
|  |   case class Coin(id: String, icon: String, name: String, symbol: String, rank: Int, price: Double, priceBtc: Double, volume: Double, marketCap: Double, availableSupply: Double, totalSupply: Double, fullyDilutedValuation: Double, priceChange1h: Double, priceChange1d: Double, priceChange1w: Double, redditUrl: String, websiteUrl: String, twitterUrl: String, explorers: List[String]) | ||||||
|  |   case class Currency(name: String, rate: Double, symbol: String, imageUrl: String) | ||||||
|  |  | ||||||
|  |   val BITCOIN_TO_USD: String = "https://openapiv1.coinstats.app/coins/bitcoin" | ||||||
|  |   val USD_TO_CHF: String = "https://openapiv1.coinstats.app/fiats" | ||||||
|  |   private val API_KEY: String = sys.env.getOrElse("OPENAPI_KEY", "") | ||||||
|  |  | ||||||
|  |   def getUrl(url: String): Future[String] = { | ||||||
|  |     Future { | ||||||
|  |       val uri: URI = new URI(url) | ||||||
|  |       val cmd: String = "curl -s -H 'X-API-KEY: " + API_KEY + "' " + uri.toString | ||||||
|  |       cmd.!! | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def extractBitcoinToUSDRate(jsonStr: String): Double = { | ||||||
|  |     val data: Coin = json.parse(jsonStr).extract[Coin] | ||||||
|  |     return data.price | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def extractUSDToCHFRate(jsonStr: String): Double = { | ||||||
|  |     val data: List[Currency] = json.parse(jsonStr).extract[List[Currency]] | ||||||
|  |     return data.find(currency => currency.name == "CHF") | ||||||
|  |                .map(currency => currency.rate) | ||||||
|  |                .get | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def getBitcoinToUSD: Future[Double] = { | ||||||
|  |     getUrl(BITCOIN_TO_USD) map extractBitcoinToUSDRate | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def getUSDToCHF: Future[Double] = { | ||||||
|  |     getUrl(USD_TO_CHF) map extractUSDToCHFRate | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   val f: Future[Double] = for { | ||||||
|  |     btc2usd <- getBitcoinToUSD | ||||||
|  |     usd2chf <- getUSDToCHF | ||||||
|  |   } yield btc2usd * usd2chf | ||||||
|  |  | ||||||
|  |   f onComplete { | ||||||
|  |     case Success(value) => println(s"1 BTC == $value CHF") | ||||||
|  |     case Failure(e) => println(s"An error occurred: $e") | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Await.ready(f, Duration.Inf) | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								src/Assignment9/Assignment9.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/Assignment9/Assignment9.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | import Assignment9.Kelvin.kel2cel | ||||||
|  |  | ||||||
|  | import scala.language.implicitConversions | ||||||
|  |  | ||||||
|  |  | ||||||
|  | package object Assignment9 { | ||||||
|  |   sealed trait Temperature { | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   object Temperature { | ||||||
|  |     implicit def cel2kel(celsius: Celsius): Kelvin = new Kelvin(celsius.value + 273.15) | ||||||
|  |     implicit def kel2cel(kelvin: Kelvin): Celsius = new Celsius(kelvin.value - 273.15) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   case class Celsius(value: Double) extends Temperature { | ||||||
|  |     override def toString: String = s"$value°C" | ||||||
|  |   } | ||||||
|  |   object Celsius { | ||||||
|  |     implicit def val2cel(value: Double): Celsius = new Celsius(value) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   case class Kelvin(value: Double) extends Temperature { | ||||||
|  |     override def toString: String = s"$value K" | ||||||
|  |   } | ||||||
|  |   object Kelvin { | ||||||
|  |     implicit def kel2cel(value: Double): Kelvin = new Kelvin(value) | ||||||
|  |  | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								src/Assignment9/Ex1.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/Assignment9/Ex1.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | package Assignment9 | ||||||
|  |  | ||||||
|  | import scala.language.implicitConversions | ||||||
|  |  | ||||||
|  | object Ex1 extends App { | ||||||
|  |   val a: Celsius = 30 | ||||||
|  |   val b: Kelvin = 30 | ||||||
|  |   val c: Kelvin = Celsius(10) | ||||||
|  |   val d: Celsius = c | ||||||
|  |   val e: Temperature = d | ||||||
|  |  | ||||||
|  |   println(a) // Should print "30°C" | ||||||
|  |   println(b) // Should print "30 K" | ||||||
|  |  | ||||||
|  |   println() | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								src/Final1/Exercise1.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/Final1/Exercise1.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | package exercises | ||||||
|  |  | ||||||
|  | object Exercise1 extends App { | ||||||
|  |   def dup[A](r: List[Int], l: List[A]): List[A] = { | ||||||
|  |     r.zip(l).flatMap(p => { | ||||||
|  |       List.fill(p._1)(p._2) | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def removeDup[A](l: List[A]): List[A] = { | ||||||
|  |     l match { | ||||||
|  |       case head::tail => { | ||||||
|  |         head::removeDup(tail.filterNot(e => e == head)) | ||||||
|  |       } | ||||||
|  |       case _ => l | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def zip[A, B](first: List[A], second: List[B]): List[(A, B)] = { | ||||||
|  |     first match { | ||||||
|  |       case head1::tail1 => { | ||||||
|  |         second match { | ||||||
|  |           case head2::tail2 => { | ||||||
|  |             (head1, head2)::zip(tail1, tail2) | ||||||
|  |           } | ||||||
|  |           case _ => Nil | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       case _ => Nil | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def zipWith[A, B, C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = { | ||||||
|  |     zip(xs, ys).map((p: (A, B)) => f(p._1, p._2)) | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								src/Final1/Exercise2.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/Final1/Exercise2.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | package exercises | ||||||
|  |  | ||||||
|  | object Exercise2 extends App { | ||||||
|  |   def gen(charSet: String, length: Int): List[String] = { | ||||||
|  |     if (length <= 0) List("") | ||||||
|  |     else charSet.toList.flatMap(c => { | ||||||
|  |       gen(charSet, length - 1).map(pwd => c.toString + pwd) | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										55
									
								
								src/Final1/Exercise3.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/Final1/Exercise3.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | package exercises | ||||||
|  |  | ||||||
|  | object Exercise3 extends App { | ||||||
|  |   sealed abstract class Tree { | ||||||
|  |     def isMirrorOf(other: Tree): Boolean | ||||||
|  |     def isSymmetric(): Boolean | ||||||
|  |     def computeDepth(): Int = { | ||||||
|  |       this match { | ||||||
|  |         case Empty => 1 | ||||||
|  |         case Node(left, _, right) => 1 + Math.max(left.computeDepth(), right.computeDepth()) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     def traverseBreadthFirst(): List[Int] = { | ||||||
|  |       val depth: Int = computeDepth() | ||||||
|  |       // Construct list of levels | ||||||
|  |       def helper(tree: Tree, curDepth: Int = 0): List[List[Int]] = { | ||||||
|  |         tree match { | ||||||
|  |           // Add empty levels for consistent indices | ||||||
|  |           case Empty => List.fill(depth - curDepth)(List.empty[Int]) | ||||||
|  |           case Node(left, elem, right) => { | ||||||
|  |             val leftList: List[List[Int]] = helper(left, curDepth + 1) | ||||||
|  |             val rightList: List[List[Int]] = helper(right, curDepth + 1) | ||||||
|  |             val res: List[List[Int]] = (0 until depth - curDepth - 1).map(i => { | ||||||
|  |               leftList(i) ::: rightList(i) | ||||||
|  |             }).toList | ||||||
|  |  | ||||||
|  |             // Add this level | ||||||
|  |             List(elem)::res | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       helper(this).flatten | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   case class Node(left: Tree, elem: Int, right: Tree) extends Tree { | ||||||
|  |     def isMirrorOf(other: Tree): Boolean = { | ||||||
|  |       other match { | ||||||
|  |         case Node(left2, _, right2) => (left isMirrorOf right2) && (right isMirrorOf left2) | ||||||
|  |         case _ => false | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     def isSymmetric: Boolean = left isMirrorOf right | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   case object Empty extends Tree { | ||||||
|  |     def isMirrorOf(other: Tree): Boolean = { | ||||||
|  |       other match { | ||||||
|  |         case Empty => true | ||||||
|  |         case _ => false | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     def isSymmetric: Boolean = true | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								src/FinalPrep1/Ex1.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/FinalPrep1/Ex1.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | def insertion[T](x: T, xs: List[T]): List[List[T]] = { | ||||||
|  |   return (0 to xs.length).map((i: Int) => { | ||||||
|  |     val p = xs.splitAt(i) | ||||||
|  |     p._1 ::: (x :: p._2) | ||||||
|  |   }).toList | ||||||
|  |  | ||||||
|  |   def buildInsertions(x: T, xs: List[T], before: List[T]): List[List[T]] = { | ||||||
|  |     xs match { | ||||||
|  |       case Nil => (before :+ x) :: Nil | ||||||
|  |       case head::tail => (before ::: (x :: xs)) :: buildInsertions(x, tail, before :+ head) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   buildInsertions(x, xs, Nil) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | insertion(1, List(2,3,4)) | ||||||
|  |  | ||||||
|  | def permutation[T](xs: List[T]): List[List[T]] = { | ||||||
|  |   xs match { | ||||||
|  |     case head::tail => permutation(tail) flatMap (perm => insertion(head, perm)) | ||||||
|  |     case _ => List(xs) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | permutation(List(1,2,3)) | ||||||
							
								
								
									
										18
									
								
								src/FinalPrep1/Ex2.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/FinalPrep1/Ex2.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | import scala.math.{ceil, min, sqrt} | ||||||
|  |  | ||||||
|  | def fourSquares(n: Int): List[Tuple4[Int, Int, Int, Int]] = { | ||||||
|  |   val tups = for ( | ||||||
|  |     d: Int <- ceil(sqrt(n)).toInt to 0 by -1; | ||||||
|  |     c: Int <- min(d, ceil(sqrt(n - d*d))).toInt to 0 by -1; | ||||||
|  |     b: Int <- min(c, ceil(sqrt(n - d*d - c*c))).toInt to 0 by -1; | ||||||
|  |     a: Int <- min(b, ceil(sqrt(n - d*d - c*c - b*b))).toInt to 0 by -1 | ||||||
|  |     if (a*a + b*b + c*c + d*d == n) | ||||||
|  |   ) yield Tuple4(a, b, c, d) | ||||||
|  |  | ||||||
|  |   tups.toList | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fourSquares(0)  // List(Tuple4(0, 0, 0, 0)) | ||||||
|  | fourSquares(3)  // List(Tuple4(0, 1, 1, 1)) | ||||||
|  | fourSquares(15)  // List(Tuple(1, 1, 2, 3)) | ||||||
|  | fourSquares(88)  // List(Tuple4(0, 4, 6, 6), Tuple4(2, 2, 4, 8)) | ||||||
							
								
								
									
										165
									
								
								src/FinalPrep1/Ex3.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/FinalPrep1/Ex3.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | |||||||
|  | sealed abstract class Tree { | ||||||
|  |   // Additional | ||||||
|  |   def toTree(indent: String = ""): String = indent | ||||||
|  |   // End | ||||||
|  |   def eval(): Double = { | ||||||
|  |     this match { | ||||||
|  |       case Sum(l, r) => l.eval() + r.eval() | ||||||
|  |       case Var(n) => throw new RuntimeException("Cannot evaluate " + this) | ||||||
|  |       case Const(v) => v | ||||||
|  |       case Power(x, y) => Math.pow(x.eval(), y.eval()) | ||||||
|  |       case Product(x, y) => x.eval() * y.eval() | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   def simplify(): Tree = { | ||||||
|  |     this match { | ||||||
|  |       case Sum(Const(v1), Const(v2)) => Const(v1 + v2) | ||||||
|  |       case Sum(l, r) if l == r => Product(Const(2), l) | ||||||
|  |       case Product(_, Const(0)) | Product(Const(0), _) => Const(0) | ||||||
|  |       case Product(v, Const(1)) => v | ||||||
|  |       case Product(Const(1), v) => v | ||||||
|  |       case Product(Const(v1), Const(v2)) => Const(v1 * v2) | ||||||
|  |  | ||||||
|  |       // Additional | ||||||
|  |       case Sum(l, Const(0)) => l | ||||||
|  |       case Sum(Const(0), r) => r | ||||||
|  |       case Product(l, c: Const) => Product(c, l) | ||||||
|  |       case Product(Const(v1), Product(Const(v2), r)) => Product(Const(v1 * v2), r) | ||||||
|  |       case Product(Product(Const(v1), l), Const(v2)) => Product(Const(v1 * v2), l) | ||||||
|  |       case Product(Product(Const(v1), l), Product(Const(v2), r)) => Product(Const(v1 * v2), Product(l, r)) | ||||||
|  |       // End | ||||||
|  |  | ||||||
|  |       case Power(_, Const(0)) => Const(1) | ||||||
|  |       case Power(v, Const(1)) => v | ||||||
|  |       case _ => this | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   def fullSimplify(): Tree = { | ||||||
|  |     (this match { | ||||||
|  |       case Sum(l, r) => Sum(l.fullSimplify(), r.fullSimplify()) | ||||||
|  |       case Power(x, y) => Power(x.fullSimplify(), y.fullSimplify()) | ||||||
|  |       case Product(x, y) => Product(x.fullSimplify(), y.fullSimplify()) | ||||||
|  |       case _ => this | ||||||
|  |     }).simplify() | ||||||
|  |   } | ||||||
|  |   def derive(s: String): Tree = { | ||||||
|  |     val simplified = this.fullSimplify() | ||||||
|  |     (simplified match { | ||||||
|  |       case Const(_) => Const(0) | ||||||
|  |       case Product(c: Const, other) => Product(c, other.derive(s)) | ||||||
|  |       case Product(other, c: Const) => Product(other.derive(s), c) | ||||||
|  |       case Sum(l, r) => Sum(l.derive(s), r.derive(s)) | ||||||
|  |  | ||||||
|  |       // Additional | ||||||
|  |       case Product(l, r) => Sum( | ||||||
|  |         Product(l.derive(s), r), | ||||||
|  |         Product(l, r.derive(s)) | ||||||
|  |       ) | ||||||
|  |       case Power(b, Const(e)) => Product(Const(e), Power(b, Const(e - 1))) | ||||||
|  |       case Power(b, e) => Product(Product(e, Power(b, Sum(e, Const(-1)))), e.derive(s)) | ||||||
|  |       case Var(n) if n == s => Const(1) | ||||||
|  |       // End | ||||||
|  |  | ||||||
|  |       case _ => simplified | ||||||
|  |     }).fullSimplify() | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | case class Sum(l: Tree, r: Tree) extends Tree { | ||||||
|  |   override def toString(): String = | ||||||
|  |     l.toString() + "+" + r.toString() | ||||||
|  |  | ||||||
|  |   // Additional | ||||||
|  |   override def toTree(indent: String = ""): String = { | ||||||
|  |     (indent + "Sum(\n" | ||||||
|  |       + l.toTree(indent + "  ") + ",\n" | ||||||
|  |       + r.toTree(indent + "  ") + "\n" | ||||||
|  |       + indent + ")") | ||||||
|  |   } | ||||||
|  |   // End | ||||||
|  | } | ||||||
|  | case class Var(n: String) extends Tree { | ||||||
|  |   override def toString() = n | ||||||
|  |  | ||||||
|  |   // Additional | ||||||
|  |   override def toTree(indent: String = ""): String = { | ||||||
|  |     indent + "Var(" + n + ")" | ||||||
|  |   } | ||||||
|  |   // End | ||||||
|  | } | ||||||
|  | case class Const(v: Double) extends Tree { | ||||||
|  |   override def toString() = v.toString | ||||||
|  |   // Additional | ||||||
|  |   override def toTree(indent: String = ""): String = { | ||||||
|  |     indent + "Const(" + v + ")" | ||||||
|  |   } | ||||||
|  |   // End | ||||||
|  | } | ||||||
|  | case class Power(x: Tree, y: Tree) extends Tree { | ||||||
|  |   override def toString() = x + "^" + y | ||||||
|  |   // Additional | ||||||
|  |   override def toTree(indent: String = ""): String = { | ||||||
|  |     (indent + "Power(\n" | ||||||
|  |       + x.toTree(indent + "  ") + ",\n" | ||||||
|  |       + y.toTree(indent + "  ") + "\n" | ||||||
|  |       + indent + ")") | ||||||
|  |   } | ||||||
|  |   // End | ||||||
|  | } | ||||||
|  | case class Product(x: Tree, y: Tree) extends Tree { | ||||||
|  |   override def toString() = x + "*" + y | ||||||
|  |   // Additional | ||||||
|  |   override def toTree(indent: String = ""): String = { | ||||||
|  |     (indent + "Sum(\n" | ||||||
|  |       + x.toTree(indent + "  ") + ",\n" | ||||||
|  |       + y.toTree(indent + "  ") + "\n" | ||||||
|  |       + indent + ")") | ||||||
|  |   } | ||||||
|  |   // End | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val p = Product( | ||||||
|  |   Sum( | ||||||
|  |     Const(3), | ||||||
|  |     Const(-3) | ||||||
|  |   ), | ||||||
|  |   Const(10) | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | p.eval() | ||||||
|  | p.fullSimplify() | ||||||
|  |  | ||||||
|  | // 23x^3 + 6x^2 -268x + pi | ||||||
|  | val p = Sum( | ||||||
|  |   Sum( | ||||||
|  |     Sum( | ||||||
|  |       Product( | ||||||
|  |         Power( | ||||||
|  |           Var("x"), | ||||||
|  |           Const(3) | ||||||
|  |         ), | ||||||
|  |         Const(23), | ||||||
|  |       ), | ||||||
|  |       Product( | ||||||
|  |         Const(6), | ||||||
|  |         Power( | ||||||
|  |           Var("x"), | ||||||
|  |           Const(2) | ||||||
|  |         ) | ||||||
|  |       ) | ||||||
|  |     ), | ||||||
|  |     Product( | ||||||
|  |       Const(-268), | ||||||
|  |       Var("x") | ||||||
|  |     ) | ||||||
|  |   ), | ||||||
|  |   Const(Math.PI) | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | p.toTree() | ||||||
|  |  | ||||||
|  | p.derive("x").toTree() | ||||||
|  |  | ||||||
|  | p.derive("x") | ||||||
|  |  | ||||||
|  | // (23x^3 + 6x^2 -268x + pi)' = 69x^2 + 12x - 268 | ||||||
							
								
								
									
										21
									
								
								src/Lesson3/Rational.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/Lesson3/Rational.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | class Rational(n: Int, d: Int) { | ||||||
|  |   def num = n | ||||||
|  |   def denom = d | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def add(x: Rational, y: Rational): Rational = | ||||||
|  |   new Rational( | ||||||
|  |     x.num * y.denom + x.denom * y.num, | ||||||
|  |     x.denom * y.denom | ||||||
|  |   ) | ||||||
|  |  | ||||||
|  | def stringVersion(x: Rational) = x.num + "/" + x.denom | ||||||
|  |  | ||||||
|  | val r1 = new Rational(1, 2) | ||||||
|  | r1.num | ||||||
|  | r1.denom | ||||||
|  |  | ||||||
|  | val r2 = new Rational(3, 4) | ||||||
|  |  | ||||||
|  | val r3 = add(r1, r2) | ||||||
|  | stringVersion(r3) | ||||||
							
								
								
									
										41
									
								
								src/Lesson3/Rational2.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/Lesson3/Rational2.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | import scala.annotation.tailrec | ||||||
|  |  | ||||||
|  | class Rational(n: Int, d: Int) { | ||||||
|  |   require(d != 0) | ||||||
|  |  | ||||||
|  |   @tailrec | ||||||
|  |   private def gcd(x: Int, y: Int): Int = | ||||||
|  |     if (y == 0) x else gcd(y, x % y) | ||||||
|  |  | ||||||
|  |   private val g: Int = gcd(n, d) | ||||||
|  |   def num: Int = n / g | ||||||
|  |   def denom: Int = d / g | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   def +(that: Rational): Rational = new Rational( | ||||||
|  |     this.num * that.denom + this.denom * that.num, | ||||||
|  |     this.denom * that.denom | ||||||
|  |   ) | ||||||
|  |  | ||||||
|  |   def unary_- : Rational = new Rational(-num, denom) | ||||||
|  |  | ||||||
|  |   def <(that: Rational): Boolean = this.num * that.denom < that.num * this.denom | ||||||
|  |  | ||||||
|  |   def max(that: Rational): Rational = if (this < that) that else this | ||||||
|  |  | ||||||
|  |   override def toString = if (math.abs(denom) == 1) "" + denom else num + "/" + denom | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val r1 = new Rational(1, 3) | ||||||
|  | val r2 = new Rational(2, 3) | ||||||
|  | val r3 = r1 + r2 | ||||||
|  |  | ||||||
|  | r3 | ||||||
|  |  | ||||||
|  | -r2 | ||||||
|  |  | ||||||
|  | r2 < r1 | ||||||
|  | r2 < r3 | ||||||
|  |  | ||||||
|  | r2.max(r1) | ||||||
|  | r2.max(r3) | ||||||
							
								
								
									
										13
									
								
								src/Lesson4/Lists.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/Lesson4/Lists.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | def insert(x: Int, xs: List[Int]): List[Int] = { | ||||||
|  |   if (xs.isEmpty) x::Nil | ||||||
|  |   else if (x < xs.head) x::xs | ||||||
|  |   else xs.head::insert(x, xs.tail) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def isort(xs: List[Int]): List[Int] = { | ||||||
|  |   if (xs.isEmpty) Nil | ||||||
|  |   else insert(xs.head, isort(xs.tail)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | isort(7::3::9::2::Nil) | ||||||
							
								
								
									
										35
									
								
								src/Lesson4/PatternMatching.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/Lesson4/PatternMatching.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | def patFoo(value: Any): Boolean = { | ||||||
|  |   value match { | ||||||
|  |     case a: Int => a % 4 == 0 | ||||||
|  |     case c: Char => c.isUpper | ||||||
|  |     case b: Boolean => true | ||||||
|  |     case _ => false | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | abstract class Expr | ||||||
|  | case class Number(n: Int) extends Expr | ||||||
|  | case class Sum(e1: Expr, e2: Expr) extends Expr | ||||||
|  |  | ||||||
|  | def eval(e: Expr): Int = e match { | ||||||
|  |   case Number(n) => n | ||||||
|  |   case Sum(e1, e2) => eval(e1) + eval(e2) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def show(e: Expr): String = e match { | ||||||
|  |   case Number(n) => n.toString | ||||||
|  |   case Sum(e1, e2) => "(" + show(e1) + " + " + show(e2) + ")" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | patFoo(23) | ||||||
|  | patFoo(24) | ||||||
|  | patFoo('a') | ||||||
|  | patFoo('A') | ||||||
|  | patFoo(false) | ||||||
|  | patFoo(true) | ||||||
|  | patFoo("Hello") | ||||||
|  | patFoo(null) | ||||||
|  |  | ||||||
|  | val e: Expr = Sum(Number(3), Sum(Number(4), Number(5))) | ||||||
|  | eval(e) | ||||||
|  | show(e) | ||||||
							
								
								
									
										4
									
								
								src/Lesson4/Types.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/Lesson4/Types.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | val a: String = "Hell" + "o" * 50 | ||||||
|  | def b(s: String): String = "Hell" + s | ||||||
|  |  | ||||||
|  | a == b("o" * 50) | ||||||
							
								
								
									
										19
									
								
								src/Lesson5/Ex5_2.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/Lesson5/Ex5_2.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | def length[A](x: List[A]): Int = { | ||||||
|  |   x.foldRight(0)((elem: A, len: Int) => len + 1) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def map[A, B](x: List[A], f: A => B): List[B] = { | ||||||
|  |   x.foldRight(List.empty[B])((elem: A, list: List[B]) => f(elem)::list) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def dup[A](l: List[A]): List[A] = { | ||||||
|  |   l.flatMap(e => List(e, e)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def dup2[A](l: List[A]): List[A] = { | ||||||
|  |   l.foldRight(List.empty[A])((e, l) => e::e::l) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | length(1::2::3::4::Nil) | ||||||
|  | map(1::2::3::4::Nil, (x: Int) => x * 2) | ||||||
|  | dup(1::2::3::Nil) | ||||||
							
								
								
									
										18
									
								
								src/Lesson6/Comprehension.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/Lesson6/Comprehension.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | (2 to 10).foreach(i => | ||||||
|  |   (2 to 10) | ||||||
|  |     .filter(j => i % j == 0) | ||||||
|  |     .foreach(j => | ||||||
|  |       println(s"$i is an integer multiple of $j") | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | val positions = for ( | ||||||
|  |   col <- 'a' to 'h'; | ||||||
|  |   row <- 1 to 8 | ||||||
|  | ) yield (col, row) | ||||||
|  |  | ||||||
|  | val whites = for ( | ||||||
|  |   col <- 'a' to 'h'; | ||||||
|  |   row <- 1 to 8; | ||||||
|  |   if ((col - 'a' + row) % 2 == 0) | ||||||
|  | ) yield (col, row) | ||||||
							
								
								
									
										40
									
								
								src/Lesson6/Ex_6.1.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/Lesson6/Ex_6.1.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | def filter[T](func: T => Boolean, list: List[T]): List[T] = { | ||||||
|  |   list match { | ||||||
|  |     case Nil => Nil | ||||||
|  |     case e::rest if func(e) => e::filter(func, rest) | ||||||
|  |     case _::rest => filter(func, rest) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def partition[T](func: T => Boolean, list: List[T]): (List[T], List[T]) = { | ||||||
|  |   list match { | ||||||
|  |     case Nil => (List.empty[T], List.empty[T]) | ||||||
|  |     case e::rest => { | ||||||
|  |       val part = partition(func, rest) | ||||||
|  |       if (func(e)) { | ||||||
|  |         (e::part._1, part._2) | ||||||
|  |       } else { | ||||||
|  |         (part._1, e::part._2) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def partition[T](func: T => Boolean, list: List[T]): (List[T], List[T]) = { | ||||||
|  |   list.foldRight((List.empty[T], List.empty[T]))( | ||||||
|  |     (e: T, prev: (List[T], List[T])) => { | ||||||
|  |       if (func(e)) { | ||||||
|  |         (e::prev._1, prev._2) | ||||||
|  |       } else { | ||||||
|  |         (prev._1, e::prev._2) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   ) | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | val b = (1 to 10).toList | ||||||
|  |  | ||||||
|  | filter((x: Int) => x % 2 == 0, b) | ||||||
|  |  | ||||||
|  | partition((x: Int) => x % 2 == 0, b) | ||||||
							
								
								
									
										29
									
								
								src/Lesson6/Primes.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/Lesson6/Primes.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | def time(f: => Unit => Any): Long = { | ||||||
|  |   val start = System.currentTimeMillis() | ||||||
|  |   f() | ||||||
|  |   val end = System.currentTimeMillis() | ||||||
|  |   end - start | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def timeVerbose(s: String)(f: => Unit => Any): Unit = { | ||||||
|  |   println(s"[$s] Measuring time...") | ||||||
|  |   val duration = time(f) | ||||||
|  |   println(s"[$s] It took ${duration}ms") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def isPrime(i: Int): Boolean = | ||||||
|  |   i match { | ||||||
|  |     case i if i <= 1 => false | ||||||
|  |     case 2 => true | ||||||
|  |     case _ => !(2 until i).exists(x => i%x == 0) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | def primeSum(max: Int)(isPrimeFunc: Int => Boolean): List[(Int, Int)] = { | ||||||
|  |   for (i <- (1 to max).toList; | ||||||
|  |        j <- (1 to max).toList; | ||||||
|  |        if isPrimeFunc(i + j)) yield (i, j) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | timeVerbose("Normal Prime"){ | ||||||
|  |   primeSum(1000)(isPrime) | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								src/Lesson6/Translations.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/Lesson6/Translations.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | val q: List[Int] = List(1, 2, 3) | ||||||
|  | val p: List[Int] = List(4, 5, 6) | ||||||
|  |  | ||||||
|  | // 1. | ||||||
|  | for (x <- q) yield x * 2 | ||||||
|  | q.map(x => x * 2) | ||||||
|  |  | ||||||
|  | // 2. | ||||||
|  | for (x <- q if x != 2) yield x * 2 | ||||||
|  | q.filter(x => x !=2).map(x => x * 2) | ||||||
|  |  | ||||||
|  | // 3. | ||||||
|  | for (x <- q; | ||||||
|  |      y <- p) yield (x, y) | ||||||
|  | q.flatMap(x => p.map(y => (x, y))) | ||||||
|  |  | ||||||
|  | // 4. | ||||||
|  | for (x <- q if (x < 2); | ||||||
|  |      y <- p) yield (x, y) | ||||||
|  | q.filter(x => x < 2).flatMap(x => p.map(y => (x, y))) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | for (x <- 1 to 2; | ||||||
|  |      y <- 'a' to 'b') yield (x, y) | ||||||
|  | (1 to 2).flatMap(x => ('a' to 'b').map(y => (x, y))) | ||||||
							
								
								
									
										13
									
								
								src/Lesson6/Tuples.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/Lesson6/Tuples.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | def merge(x: List[Int], y: List[Int]): List[Int] = { | ||||||
|  |   (x, y) match { | ||||||
|  |     case (list, Nil) => list | ||||||
|  |     case (Nil, list) => list | ||||||
|  |     case (e1::rest1, e2::rest2) => | ||||||
|  |       if (e1 < e2) e1::merge(rest1, y) | ||||||
|  |       else e2::merge(x, rest2) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val n1 = List(0, 2, 4, 6) | ||||||
|  | val n2 = List(1, 3, 5, 7) | ||||||
|  | merge(n1, n2) | ||||||
							
								
								
									
										12
									
								
								src/Lesson7/Daltons.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/Lesson7/Daltons.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | case class Dalton(n: Int) extends Ordered[Dalton] { | ||||||
|  |   //override def compare(that: Dalton): Int = this.n compare that.n | ||||||
|  |   override def compare(that: Dalton): Int = this.n - that.n | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val a = Dalton(2); val b = Dalton(3); val c = Dalton(2) | ||||||
|  |  | ||||||
|  | a < b | ||||||
|  | a > b | ||||||
|  | a == b | ||||||
|  | a == c | ||||||
|  | a >= c | ||||||
							
								
								
									
										6
									
								
								src/Lesson7/LazyEvaluation.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/Lesson7/LazyEvaluation.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | val expr = { | ||||||
|  |   val x = {print("x"); 1} | ||||||
|  |   lazy val y = {print("y"); 2} | ||||||
|  |   def z = {print("z"); 3} | ||||||
|  |   z + y + x + z + y + x | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								src/Lesson7/LazyList.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/Lesson7/LazyList.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | def range(low: Int, high: Int): LazyList[Int] = { | ||||||
|  |   println(s"Calling range with low=$low / high=$high") | ||||||
|  |   if (low >= high) LazyList.empty[Int] | ||||||
|  |   else low #:: range(low + 1, high) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | range(1, 10)(0) | ||||||
|  |  | ||||||
|  | range(1, 10) map (x => x + 1) | ||||||
|  |  | ||||||
|  | (range(1, 10) map (x => x + 1)).toList | ||||||
							
								
								
									
										16
									
								
								src/Lesson7/LoggingFactory.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/Lesson7/LoggingFactory.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | trait Logged { | ||||||
|  |   def log(msg: String) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | trait ConsoleLogger extends Logged { | ||||||
|  |   override def log(msg: String) = println("[LOG] " + msg) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | abstract class Person(name: String) | ||||||
|  |  | ||||||
|  | class Customer(n: String) extends Person(n) with Logged { | ||||||
|  |   log(s"Person $n created") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val a = new Customer("Patrick Jane") with ConsoleLogger | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								src/Lesson7/Variance.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/Lesson7/Variance.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | class Animal(val name: String, val kind: String) | ||||||
|  | class Cat(name: String) extends Animal(name, "Cat") | ||||||
|  | class Dog(name: String) extends Animal(name, "Dog") | ||||||
|  |  | ||||||
|  | val anim1: Animal = new Animal("Booboo", "Baboon") | ||||||
|  | val cat1 = new Cat("Miaou") | ||||||
|  |  | ||||||
|  | // Standard polymorphism | ||||||
|  | val anim2: Animal = cat1 | ||||||
|  |  | ||||||
|  | val dog1: Dog = new Dog("Choucroute") | ||||||
|  | val anim3: Animal = dog1 | ||||||
|  |  | ||||||
|  | class Container[+A](val elems: List[A]) { | ||||||
|  |   def get(i: Int): A = elems(i) | ||||||
|  |   def put[B >: A](elem: B) = new Container(elem::elems) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val animalCollection = new Container[Animal](Nil).put(anim1) | ||||||
|  |  | ||||||
|  | val catCollection = new Container[Cat](Nil).put(cat1).put(new Cat("Garfield")) | ||||||
|  |  | ||||||
|  | animalCollection.put(cat1) | ||||||
|  |  | ||||||
|  | val animalCollection2: Container[Animal] = catCollection | ||||||
							
								
								
									
										19
									
								
								src/Lesson8/Actors.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/Lesson8/Actors.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | package Lesson8 | ||||||
|  |  | ||||||
|  | import akka.actor.{Actor, ActorSystem, Props} | ||||||
|  |  | ||||||
|  | object Actors extends App { | ||||||
|  |   case class Greetings(who: String) | ||||||
|  |  | ||||||
|  |   class SimplestActor extends Actor { | ||||||
|  |     def receive = { | ||||||
|  |       case Greetings(who) => println(s"Hello $who, pleased to meet you") | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   val system = ActorSystem("MySystem") | ||||||
|  |   val simple_greeter = system.actorOf(Props[SimplestActor]) | ||||||
|  |  | ||||||
|  |   simple_greeter ! Greetings("Dr Who") | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								src/Lesson8/Futures.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/Lesson8/Futures.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | package Lesson8 | ||||||
|  |  | ||||||
|  | import scala.concurrent.Future | ||||||
|  | import scala.util.{Failure, Success} | ||||||
|  |  | ||||||
|  | object Futures extends App { | ||||||
|  |   implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global | ||||||
|  |  | ||||||
|  |   val f: Future[Int] = Future { | ||||||
|  |     Thread.sleep(650) | ||||||
|  |     3 + 4 | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   f onComplete { | ||||||
|  |     case Success(x: Int) => println(s"Computing done, result is $x") | ||||||
|  |     case Failure(ex) => println("Error") | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								src/Lesson9/PimpMyLibrary.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/Lesson9/PimpMyLibrary.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | package Lesson9 | ||||||
|  |  | ||||||
|  | import scala.language.{implicitConversions, postfixOps} | ||||||
|  |  | ||||||
|  | object PimpMyLibrary extends App{ | ||||||
|  |   /*class PimpedString(s: String) { | ||||||
|  |     def increment: String = new String(s.toCharArray.map(_ + 1)) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   implicit def str2Pimped(s: String): PimpedString = new PimpedString(s) | ||||||
|  |  | ||||||
|  |   println("Hal" increment)*/ | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										7
									
								
								src/MidTerm1/Ex1.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/MidTerm1/Ex1.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | val pi: List[Long] = List(3, 1, 4, 1, 5, 9, 2) | ||||||
|  | val slice: List[Int] = List(4, 1, 5) | ||||||
|  |  | ||||||
|  | pi.indexOfSlice(slice) | ||||||
|  |  | ||||||
|  | //List("Hello", "world", "Scala").foldRight(0)((a, b) => a + b.length) | ||||||
|  | List("Hello", "world", "Scala").foldLeft(0)((a, b) => a + b.length) | ||||||
							
								
								
									
										55
									
								
								src/MidTerm1/Ex2.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/MidTerm1/Ex2.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | import scala.annotation.tailrec | ||||||
|  |  | ||||||
|  | @tailrec | ||||||
|  | def foldLeft[A, B](list: List[A])(init: B)(f: (B, A) => B): B = { | ||||||
|  |   list match { | ||||||
|  |     case Nil => init | ||||||
|  |     case head::tail => foldLeft(tail)(f(init, head))(f) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @tailrec | ||||||
|  | def dropWhile[T](list: List[T])(predicate: T => Boolean): List[T] = { | ||||||
|  |   list match { | ||||||
|  |     case head::tail if predicate(head) => dropWhile(tail)(predicate) | ||||||
|  |     case _ => list | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def predicates[T](list: List[T])(preds: List[T => Boolean]): List[T] = { | ||||||
|  |   list.foldRight(List.empty[T])((e: T, l: List[T]) => { | ||||||
|  |     //if (preds.foldLeft(true)((a, b) => a && b(e))) e::l | ||||||
|  |     if (preds.forall(b => b(e))) e::l | ||||||
|  |     else l | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val l1 = (1 to 10).toList | ||||||
|  | val f1 = ((a: Int) => a % 2 == 0) | ||||||
|  | val f2 = ((a: Int) => a > 5) | ||||||
|  | predicates(l1)(List(f1, f2))  // List(6, 8, 10) | ||||||
|  |  | ||||||
|  | val l2 = ("Hello Scala Echo").toList | ||||||
|  | val f4 = ((a: Char) => a == 'a' || a == 'e' || a == 'o') | ||||||
|  | val f3 = ((a: Char) => !a.isUpper) | ||||||
|  | predicates(l2)(List(f3, f4))  // List('e', 'o', 'a', 'a', 'o') | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | // Better solution | ||||||
|  | def predicates[T](list: List[T])(preds: List[T => Boolean]): List[T] = { | ||||||
|  |   preds.foldLeft(list)((acc, fun) => acc.filter(fun)) | ||||||
|  | } | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | def fixedPoint(f: Int => Int): Int => Int = { | ||||||
|  |   @tailrec | ||||||
|  |   def func(x: Int): Int = { | ||||||
|  |     val y: Int = f(x) | ||||||
|  |     if (x == y) y | ||||||
|  |     else func(y) | ||||||
|  |   } | ||||||
|  |   func | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fixedPoint(x => if (x % 10 == 0) x else x + 1)(35)  // 40 | ||||||
|  | fixedPoint(x => x / 2 + 5)(20)  // 10 | ||||||
							
								
								
									
										37
									
								
								src/MidTerm1/Ex3.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/MidTerm1/Ex3.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | import scala.annotation.tailrec | ||||||
|  |  | ||||||
|  | abstract class Text { | ||||||
|  |   def isEmpty: Boolean = { | ||||||
|  |     this match { | ||||||
|  |       case Chars(cs) => cs.isEmpty | ||||||
|  |       case Concat(t1, t2) => t1.isEmpty && t2.isEmpty | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   def head: Char = { | ||||||
|  |     this match { | ||||||
|  |       case Chars(cs) => cs.head | ||||||
|  |       case Concat(t1, t2) => if (t1.isEmpty) t2.head else t1.head | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   def tail: Text = { | ||||||
|  |     this match { | ||||||
|  |       case Chars(cs) => Chars(cs.tail) | ||||||
|  |       case Concat(t1, t2) => if (t1.isEmpty) t2.tail else Concat(t1.tail, t2) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   def map(f: Char => Char): Text = { | ||||||
|  |     this match { | ||||||
|  |       case Chars(cs) => Chars(cs.map(f)) | ||||||
|  |       case Concat(t1, t2) => Concat(t1.map(f), t2.map(f)) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | case class Chars(cs: List[Char]) extends Text | ||||||
|  | case class Concat(t1: Text, t2: Text) extends Text | ||||||
|  |  | ||||||
|  | @tailrec | ||||||
|  | def equals(t1: Text, t2: Text): Boolean = { | ||||||
|  |   if (t1.isEmpty) t2.isEmpty | ||||||
|  |   else if (t2.isEmpty) false | ||||||
|  |   else (t1.head == t2.head) && equals(t1.tail, t2.tail) | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								src/MidTermPrep1/Ex1.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/MidTermPrep1/Ex1.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | import scala.annotation.tailrec | ||||||
|  |  | ||||||
|  | def foo(x: Int): Int = { | ||||||
|  |   println("Foo !") | ||||||
|  |   x + 1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def bar(x: => Int): Unit = { | ||||||
|  |   println("x1=" + x) | ||||||
|  |   println("x2=" + x) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bar(foo(3)) | ||||||
|  | // Foo ! | ||||||
|  | // x1=4 | ||||||
|  | // Foo ! | ||||||
|  | // x2=4 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def toUpper(s: String): String = { | ||||||
|  |   @tailrec | ||||||
|  |   def helper(s: String, res: String): String = { | ||||||
|  |     if (s.isEmpty) res | ||||||
|  |     else helper(s.tail, res + s.head.toUpper) | ||||||
|  |   } | ||||||
|  |   helper(s, "") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | toUpper("hello") | ||||||
							
								
								
									
										36
									
								
								src/MidTermPrep1/Ex2.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/MidTermPrep1/Ex2.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | import scala.annotation.tailrec | ||||||
|  |  | ||||||
|  | def balanceMatch(chars: List[Char]): Boolean = { | ||||||
|  |   @tailrec | ||||||
|  |   def checkStep(chars: List[Char], n: Int): Boolean = { | ||||||
|  |     if (chars.isEmpty) n == 0 | ||||||
|  |     else if (n < 0) false | ||||||
|  |     else checkStep(chars.tail, chars.head match { | ||||||
|  |       case '(' => n + 1 | ||||||
|  |       case ')' => n - 1 | ||||||
|  |       case _ => n | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  |   checkStep(chars, 0) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def balanceMatch2(chars: List[Char]): Boolean = { | ||||||
|  |   @tailrec | ||||||
|  |   def checkStep(chars: List[Char], n: Int): Boolean = { | ||||||
|  |     chars match { | ||||||
|  |       case Nil => n == 0 | ||||||
|  |       case _ if n < 0 => false | ||||||
|  |       case '('::rest => checkStep(rest, n + 1) | ||||||
|  |       case ')'::rest => checkStep(rest, n - 1) | ||||||
|  |       case _::rest => checkStep(rest, n) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   checkStep(chars, 0) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | balanceMatch2("(if (x == 0) then max (1, x))".toList) | ||||||
|  | balanceMatch2("I told him (that it's not (yet) done). (But he wasn't listening)".toList) | ||||||
|  | balanceMatch2(")".toList) | ||||||
|  | balanceMatch2("())()".toList) | ||||||
|  | balanceMatch2("())(()".toList) | ||||||
|  | balanceMatch2("(".toList) | ||||||
							
								
								
									
										36
									
								
								src/MidTermPrep1/Ex3.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/MidTermPrep1/Ex3.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | import scala.annotation.tailrec | ||||||
|  |  | ||||||
|  | def countTrue(bools: List[Boolean]): Int = { | ||||||
|  |   bools.foldLeft(0)((n, bool) => if (bool) n + 1 else n) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | countTrue(List(true, true, false, true, false, false)) | ||||||
|  |  | ||||||
|  | def remDup[T](list: List[T]): List[T] = { | ||||||
|  |   list.foldRight(List.empty[T])((elem: T, res: List[T]) => { | ||||||
|  |     if (res.contains(elem)) res | ||||||
|  |     else elem::res | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def remDup2[T](list: List[T]): List[T] = { | ||||||
|  |   list.foldLeft(List.empty[T])((res: List[T], elem: T) => { | ||||||
|  |     if (res.contains(elem)) res | ||||||
|  |     else res :+ elem | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def remDup3[T](list: List[T]): List[T] = { | ||||||
|  |   @tailrec | ||||||
|  |   def helper(list: List[T], distinct: List[T]): List[T] = { | ||||||
|  |     list match { | ||||||
|  |       case head::rest if distinct.contains(head) => helper(rest, distinct) | ||||||
|  |       case head::rest => helper(rest, distinct :+ head) | ||||||
|  |       case Nil => distinct | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   helper(list, List.empty[T]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | remDup(List(5,3,2,4,3,2,3,3)) // List(5,3,2,4) | ||||||
|  | remDup(List("hello", "youpi", "hello", "hello")) // List("hello", "youpi") | ||||||
							
								
								
									
										8
									
								
								src/MidTermPrep1/Exercices.sc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/MidTermPrep1/Exercices.sc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | def compress[T](list: List[T]): List[T] = { | ||||||
|  |   list.foldRight(List.empty[T])((elmt: T, res: List[T]) => res match { | ||||||
|  |     case head::_ if head == elmt => res | ||||||
|  |     case _ => elmt::res | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | compress(List('a', 'a', 'a', 'a', 'b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e', 'e')) | ||||||
							
								
								
									
										57
									
								
								src/utils/package.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/utils/package.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | |||||||
|  | /** | ||||||
|  |  * Some useful functions for Scala. | ||||||
|  |  * | ||||||
|  |  * @author Pierre-André Mudry | ||||||
|  |  * @version 1.0 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | import java.io.{BufferedOutputStream, File, FileOutputStream} | ||||||
|  | import scala.io.{Codec, Source} | ||||||
|  |  | ||||||
|  | package object utils { | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * There are functions for micro-benchmarking, but you should not | ||||||
|  | 	 * rely on those functions for measuring short durations! | ||||||
|  | 	 */ | ||||||
|  |  | ||||||
|  | 	// Measure the time for a block of code to run, approximately | ||||||
|  | 	def timeVerbose(f: ⇒ Unit) = { | ||||||
|  | 		println("[Time] Start of measure") | ||||||
|  | 		val duration = time(f) | ||||||
|  | 		println(s"[Time] Block duration was $duration ms\n") | ||||||
|  | 		duration | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// With a customized error message | ||||||
|  | 	def timeVerbose(s: String)(f: ⇒ Unit) = { | ||||||
|  | 		println(s"[$s] Start of measure") | ||||||
|  | 		val duration = time(f) | ||||||
|  | 		println(s"[$s] Block duration was $duration ms\n") | ||||||
|  | 		duration | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Measure the time for a block of code to run, approximately | ||||||
|  | 	def time(f: ⇒ Unit) = { | ||||||
|  | 		val start = System.currentTimeMillis | ||||||
|  | 		f // Execute the block | ||||||
|  | 		val duration = System.currentTimeMillis - start | ||||||
|  | 		duration | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * A class for reading and writing to files easily | ||||||
|  | 	 */ | ||||||
|  | 	implicit class RichFile(file: File) { | ||||||
|  | 		def read() = Source.fromFile(file)(Codec.UTF8).mkString | ||||||
|  |  | ||||||
|  | 		def write(data: String) { | ||||||
|  | 			val fos = new BufferedOutputStream(new FileOutputStream(file)) | ||||||
|  | 			try { | ||||||
|  | 				fos.write(data.getBytes("UTF-8")) | ||||||
|  | 			} finally { | ||||||
|  | 				fos.close | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user