| author | Christian Urban <christian.urban@kcl.ac.uk> | 
| Wed, 01 Nov 2023 15:01:32 +0000 | |
| changeset 468 | c71ae4477e55 | 
| parent 460 | f5c0749858fd | 
| child 472 | fbff6f601370 | 
| 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 | |
| 5 | object M2 { 
 | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 6 | |
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 7 | import io.Source | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 8 | import scala.util._ | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 9 | |
| 436 | 10 | // ADD YOUR CODE BELOW | 
| 11 | //====================== | |
| 460 | 12 | // def main(args: Array[String]): Unit = {
 | 
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 13 | |
| 460 | 14 | //     val secrets = get_wordle_list("https://nms.kcl.ac.uk/christian.urban/wordle.txt")
 | 
| 15 | //     println(ranked_evil(secrets, "beats")== List("fuzzy"))
 | |
| 16 | //     println(ranked_evil(secrets, "vitae") == List("fuzzy"))
 | |
| 17 | //     println(ranked_evil(secrets, "bento") == List("fuzzy"))
 | |
| 18 | //     println(ranked_evil(secrets, "belts") == List("fuzzy"))
 | |
| 19 | //     println(ranked_evil(secrets, "abbey") == List("whizz"))
 | |
| 20 | //     println(ranked_evil(secrets, "afear") == List("buzzy"))
 | |
| 21 | //     println(ranked_evil(secrets, "zincy") == List("jugum"))
 | |
| 22 | //     println(ranked_evil(secrets, "zippy") == List("chuff"))
 | |
| 23 | ||
| 24 | ||
| 25 | // } | |
| 436 | 26 | |
| 27 | //(1) | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 28 | def get_wordle_list(url: String) : List[String] = {
 | 
| 460 | 29 |     try {
 | 
| 30 | Source.fromURL(url).getLines.toList; | |
| 31 | } | |
| 32 |     catch {
 | |
| 33 | case _ : Throwable => List(); | |
| 34 | } | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 35 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 36 | // val secrets = get_wordle_list("https://nms.kcl.ac.uk/christian.urban/wordle.txt")
 | 
| 436 | 37 | // secrets.length // => 12972 | 
| 38 | // secrets.filter(_.length != 5) // => Nil | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 39 | |
| 436 | 40 | //(2) | 
| 41 | def removeN[A](xs: List[A], elem: A, n: Int) : List[A] = {
 | |
| 460 | 42 |     if (xs.isEmpty || n == 0 || !xs.contains(elem)){
 | 
| 43 | xs | |
| 44 | } | |
| 45 |     else{
 | |
| 46 | val (newLst,newLst2) = xs.splitAt(xs.indexOf(elem)) | |
| 47 | removeN(newLst ++ newLst2.tail,elem, n-1) | |
| 48 | } | |
| 49 | } | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 50 | |
| 436 | 51 | // removeN(List(1,2,3,2,1), 3, 1) // => List(1, 2, 2, 1) | 
| 52 | // removeN(List(1,2,3,2,1), 2, 1) // => List(1, 3, 2, 1) | |
| 53 | // removeN(List(1,2,3,2,1), 1, 1) // => List(2, 3, 2, 1) | |
| 54 | // 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 | 55 | |
| 436 | 56 | // (3) | 
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 57 | abstract class Tip | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 58 | case object Absent extends Tip | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 59 | case object Present extends Tip | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 60 | case object Correct extends Tip | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 61 | |
| 436 | 62 | |
| 63 | def pool(secret: String, word: String) : List[Char] = {
 | |
| 460 | 64 | //print(secret.toList, word.toList) | 
| 65 |     val lst= ((0 to 4).map(x => {
 | |
| 66 | if(!secret(x).equals(word(x))) Some(secret(x)) else None | |
| 67 | ||
| 68 | }).toList) | |
| 69 | lst.flatten | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 70 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 71 | |
| 460 | 72 | |
| 73 | def aux(secret: List[Char], word: List[Char], pool: List[Char]) : List[Tip] = {
 | |
| 74 | ||
| 75 |     if (secret.length == 1){
 | |
| 76 |         if (secret.head == word.head){
 | |
| 77 | List(Correct) | |
| 78 | } | |
| 79 |         else if (pool.contains(word.head)){
 | |
| 80 | List(Present) | |
| 81 | } | |
| 82 |         else {
 | |
| 83 | List(Absent) | |
| 84 | } | |
| 85 | } | |
| 86 |     else if (secret.head == word.head){
 | |
| 87 | List(Correct) ++ aux(secret.tail, word.tail, pool) | |
| 88 | } | |
| 89 |     else if (pool.contains(word.head)){
 | |
| 90 | List(Present) ++ aux(secret.tail, word.tail, removeN(pool, word.head, 1)) | |
| 91 | } | |
| 92 |     else {
 | |
| 93 | List(Absent) ++ aux(secret.tail, word.tail, pool) | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 94 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 95 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 96 | |
| 460 | 97 | def score(secret: String, word: String) : List[Tip] = {
 | 
| 98 | aux(secret.toList,word.toList,pool(secret,word)) | |
| 99 | } | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 100 | |
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 101 | |
| 436 | 102 | // score("chess", "caves") // => List(Correct, Absent, Absent, Present, Correct)
 | 
| 103 | // score("doses", "slide") // => List(Present, Absent, Absent, Present, Present)
 | |
| 104 | // score("chess", "swiss") // => List(Absent, Absent, Absent, Correct, Correct)
 | |
| 105 | // score("chess", "eexss") // => List(Present, Absent, Absent, Correct, Correct)
 | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 106 | |
| 436 | 107 | // (4) | 
| 460 | 108 | def eval(t: Tip) : Int = {
 | 
| 109 | if (t == Correct) 10 | |
| 110 | else if (t == Present) 1 | |
| 111 | else 0 | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 112 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 113 | |
| 460 | 114 | def iscore(secret: String, word: String) : Int = {
 | 
| 115 | val scoreList = score(secret,word) | |
| 116 | scoreList.map(x =>(eval(x))).toList.sum | |
| 117 | } | |
| 436 | 118 | |
| 119 | //iscore("chess", "caves") // => 21
 | |
| 120 | //iscore("chess", "swiss") // => 20
 | |
| 121 | ||
| 122 | // (5) | |
| 460 | 123 | def lowest(secrets: List[String], word: String, current: Int, acc: List[String]) : List[String] = {
 | 
| 124 | if(secrets.isEmpty) acc | |
| 125 |     else if (iscore(secrets.head,word)<current){
 | |
| 126 | lowest(secrets.tail, word, iscore(secrets.head,word), List(secrets.head)) | |
| 436 | 127 | } | 
| 460 | 128 |     else if (iscore(secrets.head,word)==current){
 | 
| 129 | lowest(secrets.tail, word, current, acc :+ secrets.head) | |
| 130 | } | |
| 131 |     else {
 | |
| 132 | lowest(secrets.tail, word, current, acc) | |
| 133 | } | |
| 134 | ||
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 135 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 136 | |
| 460 | 137 | def evil(secrets: List[String], word: String) = {
 | 
| 138 | lowest(secrets, word, 100, List()) | |
| 139 | } | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 140 | |
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 141 | |
| 436 | 142 | //evil(secrets, "stent").length | 
| 143 | //evil(secrets, "hexes").length | |
| 144 | //evil(secrets, "horse").length | |
| 145 | //evil(secrets, "hoise").length | |
| 146 | //evil(secrets, "house").length | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 147 | |
| 436 | 148 | // (6) | 
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 149 | def frequencies(secrets: List[String]) : Map[Char, Double] = {
 | 
| 460 | 150 | val totalChar = secrets.flatMap(_.toList).size.toDouble | 
| 151 | val freqMap = secrets.flatMap(_.toList).groupBy(identity) | |
| 152 | freqMap.map(x => (x._1, (1-(x._2.size.toDouble/ totalChar)))) | |
| 153 | ||
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 154 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 155 | |
| 436 | 156 | // (7) | 
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 157 | def rank(frqs: Map[Char, Double], s: String) = {
 | 
| 460 | 158 | s.map(x => (frqs(x))).toList.sum | 
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 159 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 160 | |
| 460 | 161 | def ranked_evil(secrets: List[String], word: String) : List[String]= {
 | 
| 162 | val evilWords = evil(secrets,word) | |
| 163 | val returnVal = evilWords.map(x => (x, rank(frequencies(secrets),x))).toMap.maxBy(_._2)._1 | |
| 164 | List(returnVal) | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 165 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 166 | |
| 436 | 167 | |
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 168 | } | 
| 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 169 | |
| 436 | 170 | |
| 171 | ||
| 172 | ||
| 173 | ||
| 432 
87e487ccbd7c
updated wordle testing
 Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset | 174 | |
| 436 | 175 | // This template code is subject to copyright | 
| 176 | // by King's College London, 2022. Do not | |
| 177 | // make the template code public in any shape | |
| 178 | // or form, and do not exchange it with other | |
| 179 | // students under any circumstance. |