main_testing2/wordle.scala
changeset 463 0315d9983cd0
parent 439 97594b9998a8
child 475 59e005dcf163
equal deleted inserted replaced
462:34feeb53c0ba 463:0315d9983cd0
     1 // Main Part 3 about Evil Wordle
     1 // Main Part 3 about Evil Wordle
     2 //===============================
     2 //===============================
     3 
     3 
     4 // test bash
       
     5 
     4 
     6 object M2 { 
     5 object M2 { 
     7 
     6 
     8 import io.Source
     7 import io.Source
     9 import scala.util._
     8 import scala.util._
    10 
     9 
    11 // ADD YOUR CODE BELOW
    10 // ADD YOUR CODE BELOW
    12 //======================
    11 //======================
       
    12 // def main(args: Array[String]): Unit = {
    13 
    13 
    14 // test import
    14 //     val secrets = get_wordle_list("https://nms.kcl.ac.uk/christian.urban/wordle.txt")
    15 
    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 //    }
    16 
    26 
    17 //(1)
    27 //(1)
    18 def get_wordle_list(url: String) : List[String] = {
    28 def get_wordle_list(url: String) : List[String] = {
    19   Try(Source.fromURL(url)("ISO-8859-1").getLines().toList).getOrElse(Nil)
    29     try {
       
    30         Source.fromURL(url).getLines.toList;
       
    31     }
       
    32     catch {
       
    33         case _ : Throwable => List();
       
    34     }    
    20 }
    35 }
    21 
       
    22 
       
    23 // val secrets = get_wordle_list("https://nms.kcl.ac.uk/christian.urban/wordle.txt")
    36 // val secrets = get_wordle_list("https://nms.kcl.ac.uk/christian.urban/wordle.txt")
    24 // secrets.length // => 12972
    37 // secrets.length // => 12972
    25 // secrets.filter(_.length != 5) // => Nil
    38 // secrets.filter(_.length != 5) // => Nil
    26 
    39 
    27 //(2)
    40 //(2)
    28 def removeN[A](xs: List[A], elem: A, n: Int) : List[A] = {
    41 def removeN[A](xs: List[A], elem: A, n: Int) : List[A] = {
    29     if (n == 0) xs 
    42     if (xs.isEmpty || n == 0 || !xs.contains(elem)){
    30     else xs match {
    43         xs
    31         case Nil => Nil
    44     }
    32         case x::xs => 
    45     else{
    33             if (x == elem) removeN(xs, x, n - 1) 
    46         val (newLst,newLst2) = xs.splitAt(xs.indexOf(elem))
    34             else x::removeN(xs, elem, n)
    47         removeN(newLst ++ newLst2.tail,elem, n-1)
    35     } 
    48     }
    36 }    
    49 }
    37 
       
    38 
    50 
    39 // removeN(List(1,2,3,2,1), 3, 1)  // => List(1, 2, 2, 1)
    51 // 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)
    52 // 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)
    53 // 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)
    54 // removeN(List(1,2,3,2,1), 0, 2)  // => List(1, 2, 3, 2, 1)
    47 case object Present extends Tip
    59 case object Present extends Tip
    48 case object Correct extends Tip
    60 case object Correct extends Tip
    49 
    61 
    50 
    62 
    51 def pool(secret: String, word: String) : List[Char] = {
    63 def pool(secret: String, word: String) : List[Char] = {
    52   for (i <- (0 to 4).toList 
    64     //print(secret.toList, word.toList)
    53        if secret(i) != word(i))
    65     val lst= ((0 to 4).map(x => {
    54   yield secret(i) 
    66         if(!secret(x).equals(word(x))) Some(secret(x)) else None
       
    67         
       
    68         }).toList)
       
    69     lst.flatten
    55 }
    70 }
    56 
    71 
    57 def aux(secret: List[Char], word: List[Char], pool: List[Char]) : List[Tip] = (secret, word) match {
    72 
    58     case (Nil, Nil) => Nil
    73 def aux(secret: List[Char], word: List[Char], pool: List[Char]) : List[Tip] = {
    59     case (s::srest, w::wrest) => {
    74    
    60         if (s == w) Correct::aux(srest, wrest, pool)
    75     if (secret.length == 1){
    61         else if (pool.contains(w)) Present::aux(srest, wrest, removeN(pool, w, 1))
    76         if (secret.head == word.head){
    62         else  Absent::aux(srest, wrest, pool)
    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)
    63     }
    94     }
    64 }
    95 }
    65 
    96 
    66 
    97 def score(secret: String, word: String) : List[Tip] = {
    67 def score(secret: String, word: String) : List[Tip] = 
    98     aux(secret.toList,word.toList,pool(secret,word))
    68   aux(secret.toList, word.toList, pool(secret, word))
    99 }
    69 
   100 
    70 
   101 
    71 // score("chess", "caves") // => List(Correct, Absent, Absent, Present, Correct)
   102 // score("chess", "caves") // => List(Correct, Absent, Absent, Present, Correct)
    72 // score("doses", "slide") // => List(Present, Absent, Absent, Present, Present)
   103 // score("doses", "slide") // => List(Present, Absent, Absent, Present, Present)
    73 // score("chess", "swiss") // => List(Absent, Absent, Absent, Correct, Correct)
   104 // score("chess", "swiss") // => List(Absent, Absent, Absent, Correct, Correct)
    74 // score("chess", "eexss") // => List(Present, Absent, Absent, Correct, Correct)
   105 // score("chess", "eexss") // => List(Present, Absent, Absent, Correct, Correct)
    75 
   106 
    76 // (4)
   107 // (4)
    77 def eval(t: Tip) : Int = t match {
   108 def eval(t: Tip) : Int = {
    78     case Correct => 10
   109     if (t == Correct) 10
    79     case Present => 1
   110     else if (t == Present) 1
    80     case Absent => 0
   111     else 0
    81 }
   112 }
    82 
   113 
    83 def iscore(secret: String, word: String) : Int = 
   114 def iscore(secret: String, word: String) : Int = {
    84   score(secret, word).map(eval).sum
   115     val scoreList = score(secret,word)
       
   116     scoreList.map(x =>(eval(x))).toList.sum
       
   117 }
    85 
   118 
    86 //iscore("chess", "caves") // => 21
   119 //iscore("chess", "caves") // => 21
    87 //iscore("chess", "swiss") // => 20
   120 //iscore("chess", "swiss") // => 20
    88 
   121 
    89 // (5)
   122 // (5)
    90 def lowest(secrets: List[String], word: String, current: Int, acc: List[String]) : List[String] = secrets match {
   123 def lowest(secrets: List[String], word: String, current: Int, acc: List[String]) : List[String] = {
    91     case Nil => acc
   124     if(secrets.isEmpty) acc
    92     case s::srest => {
   125     else if (iscore(secrets.head,word)<current){
    93         val nscore = iscore(s, word)
   126         lowest(secrets.tail, word, iscore(secrets.head,word), List(secrets.head))
    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     }
   127     }
       
   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 
    98 }
   135 }
    99 
   136 
   100 def evil(secrets: List[String], word: String) = 
   137 def evil(secrets: List[String], word: String) = {
   101   lowest(secrets, word, Int.MaxValue, Nil)
   138     lowest(secrets, word, 100, List())
       
   139 }
   102 
   140 
   103 
   141 
   104 //evil(secrets, "stent").length
   142 //evil(secrets, "stent").length
   105 //evil(secrets, "hexes").length
   143 //evil(secrets, "hexes").length
   106 //evil(secrets, "horse").length
   144 //evil(secrets, "horse").length
   107 //evil(secrets, "hoise").length
   145 //evil(secrets, "hoise").length
   108 //evil(secrets, "house").length
   146 //evil(secrets, "house").length
   109 
   147 
   110 // (6)
   148 // (6)
   111 def frequencies(secrets: List[String]) : Map[Char, Double] = {
   149 def frequencies(secrets: List[String]) : Map[Char, Double] = {
   112     val all = secrets.flatten
   150     val totalChar = secrets.flatMap(_.toList).size.toDouble
   113     all.groupBy(identity).view.mapValues(1.0D - _.size.toDouble / all.size ).toMap
   151     val freqMap = secrets.flatMap(_.toList).groupBy(identity)
       
   152     freqMap.map(x => (x._1, (1-(x._2.size.toDouble/ totalChar))))
       
   153 
   114 }
   154 }
   115 
   155 
   116 // (7)
   156 // (7)
   117 def rank(frqs: Map[Char, Double], s: String) = {
   157 def rank(frqs: Map[Char, Double], s: String) = {
   118     s.map(frqs(_)).sum
   158     s.map(x => (frqs(x))).toList.sum
   119 }
   159 }
   120 
   160 
   121 
   161 def ranked_evil(secrets: List[String], word: String) : List[String]= {
   122 def ranked_evil(secrets: List[String], word: String) = {
   162     val evilWords = evil(secrets,word)
   123     val frqs = frequencies(secrets)
   163     val returnVal = evilWords.map(x => (x, rank(frequencies(secrets),x))).toMap.maxBy(_._2)._1
   124     val ev = evil(secrets, word)
   164     List(returnVal)
   125     ev.groupBy(rank(frqs, _)).toList.sortBy(_._1).reverse.head._2
       
   126 }
   165 }
   127 
   166 
   128 
   167 
   129 }
   168 }
   130 
   169