| author | Christian Urban <christian.urban@kcl.ac.uk> | 
| Fri, 02 Dec 2022 11:05:41 +0000 | |
| changeset 447 | 0cf1b374e146 | 
| parent 436 | 2f17f233cddc | 
| child 460 | f5c0749858fd | 
| permissions | -rw-r--r-- | 
| 436 | 1 | // Main Part 3 about Evil Wordle | 
| 2 | //=============================== | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 3 | |
| 436 | 4 | // test bash | 
| 5 | ||
| 6 | object M2 { 
 | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 7 | |
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 8 | import io.Source | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 9 | import scala.util._ | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 10 | |
| 436 | 11 | // ADD YOUR CODE BELOW | 
| 12 | //====================== | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 13 | |
| 436 | 14 | // test import | 
| 15 | ||
| 16 | ||
| 17 | //(1) | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 18 | def get_wordle_list(url: String) : List[String] = {
 | 
| 436 | 19 |   Try(Source.fromURL(url)("ISO-8859-1").getLines().toList).getOrElse(Nil)
 | 
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 20 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 21 | |
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 22 | |
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 23 | // val secrets = get_wordle_list("https://nms.kcl.ac.uk/christian.urban/wordle.txt")
 | 
| 436 | 24 | // secrets.length // => 12972 | 
| 25 | // secrets.filter(_.length != 5) // => Nil | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 26 | |
| 436 | 27 | //(2) | 
| 28 | def removeN[A](xs: List[A], elem: A, n: Int) : List[A] = {
 | |
| 29 | if (n == 0) xs | |
| 30 |     else xs match {
 | |
| 31 | case Nil => Nil | |
| 32 | case x::xs => | |
| 33 | if (x == elem) removeN(xs, x, n - 1) | |
| 34 | else x::removeN(xs, elem, n) | |
| 35 | } | |
| 36 | } | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 37 | |
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 38 | |
| 436 | 39 | // removeN(List(1,2,3,2,1), 3, 1) // => List(1, 2, 2, 1) | 
| 40 | // removeN(List(1,2,3,2,1), 2, 1) // => List(1, 3, 2, 1) | |
| 41 | // removeN(List(1,2,3,2,1), 1, 1) // => List(2, 3, 2, 1) | |
| 42 | // removeN(List(1,2,3,2,1), 0, 2) // => List(1, 2, 3, 2, 1) | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 43 | |
| 436 | 44 | // (3) | 
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 45 | abstract class Tip | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 46 | case object Absent extends Tip | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 47 | case object Present extends Tip | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 48 | case object Correct extends Tip | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 49 | |
| 436 | 50 | |
| 51 | def pool(secret: String, word: String) : List[Char] = {
 | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 52 | for (i <- (0 to 4).toList | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 53 | if secret(i) != word(i)) | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 54 | yield secret(i) | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 55 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 56 | |
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 57 | def aux(secret: List[Char], word: List[Char], pool: List[Char]) : List[Tip] = (secret, word) match {
 | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 58 | case (Nil, Nil) => Nil | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 59 |     case (s::srest, w::wrest) => {
 | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 60 | if (s == w) Correct::aux(srest, wrest, pool) | 
| 436 | 61 | else if (pool.contains(w)) Present::aux(srest, wrest, removeN(pool, w, 1)) | 
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 62 | else Absent::aux(srest, wrest, pool) | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 63 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 64 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 65 | |
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 66 | |
| 436 | 67 | def score(secret: String, word: String) : List[Tip] = | 
| 68 | aux(secret.toList, word.toList, pool(secret, word)) | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 69 | |
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 70 | |
| 436 | 71 | // score("chess", "caves") // => List(Correct, Absent, Absent, Present, Correct)
 | 
| 72 | // score("doses", "slide") // => List(Present, Absent, Absent, Present, Present)
 | |
| 73 | // score("chess", "swiss") // => List(Absent, Absent, Absent, Correct, Correct)
 | |
| 74 | // score("chess", "eexss") // => List(Present, Absent, Absent, Correct, Correct)
 | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 75 | |
| 436 | 76 | // (4) | 
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 77 | def eval(t: Tip) : Int = t match {
 | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 78 | case Correct => 10 | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 79 | case Present => 1 | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 80 | case Absent => 0 | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 81 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 82 | |
| 436 | 83 | def iscore(secret: String, word: String) : Int = | 
| 84 | score(secret, word).map(eval).sum | |
| 85 | ||
| 86 | //iscore("chess", "caves") // => 21
 | |
| 87 | //iscore("chess", "swiss") // => 20
 | |
| 88 | ||
| 89 | // (5) | |
| 90 | def lowest(secrets: List[String], word: String, current: Int, acc: List[String]) : List[String] = secrets match {
 | |
| 91 | case Nil => acc | |
| 92 |     case s::srest => {
 | |
| 93 | val nscore = iscore(s, word) | |
| 94 | if (nscore < current) lowest(srest, word, nscore, List(s)) | |
| 95 | else if (nscore == current) lowest(srest, word, current, s::acc) | |
| 96 | else lowest(srest, word, current, acc) | |
| 97 | } | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 98 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 99 | |
| 436 | 100 | def evil(secrets: List[String], word: String) = | 
| 101 | lowest(secrets, word, Int.MaxValue, Nil) | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 102 | |
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 103 | |
| 436 | 104 | //evil(secrets, "stent").length | 
| 105 | //evil(secrets, "hexes").length | |
| 106 | //evil(secrets, "horse").length | |
| 107 | //evil(secrets, "hoise").length | |
| 108 | //evil(secrets, "house").length | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 109 | |
| 436 | 110 | // (6) | 
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 111 | def frequencies(secrets: List[String]) : Map[Char, Double] = {
 | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 112 | val all = secrets.flatten | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 113 | all.groupBy(identity).view.mapValues(1.0D - _.size.toDouble / all.size ).toMap | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 114 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 115 | |
| 436 | 116 | // (7) | 
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 117 | def rank(frqs: Map[Char, Double], s: String) = {
 | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 118 | s.map(frqs(_)).sum | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 119 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 120 | |
| 436 | 121 | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 122 | def ranked_evil(secrets: List[String], word: String) = {
 | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 123 | val frqs = frequencies(secrets) | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 124 | val ev = evil(secrets, word) | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 125 | ev.groupBy(rank(frqs, _)).toList.sortBy(_._1).reverse.head._2 | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 126 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 127 | |
| 436 | 128 | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 129 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 130 | |
| 436 | 131 | |
| 132 | ||
| 133 | ||
| 134 | ||
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 135 | |
| 436 | 136 | // This template code is subject to copyright | 
| 137 | // by King's College London, 2022. Do not | |
| 138 | // make the template code public in any shape | |
| 139 | // or form, and do not exchange it with other | |
| 140 | // students under any circumstance. |