main_testing2/wordle.scala
changeset 435 fda7c39f3b6a
child 439 97594b9998a8
equal deleted inserted replaced
434:8c5804b2f9d2 435:fda7c39f3b6a
       
     1 // Resit Part about an Evil Wordle Clone
       
     2 //==========================================
       
     3 //
       
     4 // Task description are on KEATS
       
     5 //
       
     6 // Make sure you use Scala Version 2.13 (not Scala 3)
       
     7 //
       
     8 // Upload your submision to OneSpace and give Senir and Christian
       
     9 // write access to the folder. The folder should have you email
       
    10 // address as name. Give us write permission by July 25th such
       
    11 // that we can download your solution by the closing date August 4th.
       
    12 
       
    13 object Resit {
       
    14 
       
    15 import io.Source
       
    16 import scala.util._
       
    17 
       
    18 //=============================
       
    19 // Task 1 [0.25 Marks]
       
    20 
       
    21 def get_wordle_list(url: String) : List[String] = {
       
    22     try{
       
    23 		val raw = Source.fromURL(url).mkString
       
    24 		raw.split("\n").toList
       
    25 	}
       
    26 	catch {
       
    27 		case e : Exception => List[String]()
       
    28     }
       
    29 }
       
    30 
       
    31 
       
    32 // val secrets = get_wordle_list("https://nms.kcl.ac.uk/christian.urban/wordle.txt")
       
    33 // secrets.length => 12972
       
    34 // secrets.filter(_.length != 5) => Nil
       
    35 
       
    36 //=============================
       
    37 // Task 2 [0.25 Marks]
       
    38 
       
    39 def removeOne[A](xs: List[A], elem: A) : List[A] = {
       
    40     val index = xs.indexOf(elem)
       
    41 	val first = xs.take(index)
       
    42 	val second = xs.drop(index + 1)
       
    43 	first ::: second
       
    44 }
       
    45 
       
    46 // removeOne(List(1,2,3,2,1), 3)  => List(1, 2, 2, 1)
       
    47 // removeOne(List(1,2,3,2,1), 2)  => List(1, 3, 2, 1)
       
    48 // removeOne(List(1,2,3,2,1), 1)  => List(2, 3, 2, 1)
       
    49 // removeOne(List(1,2,3,2,1), 0)  => List(1, 2, 3, 2, 1)
       
    50 
       
    51 
       
    52 //=============================
       
    53 // Task 3 [1.5 Marks]
       
    54 
       
    55 abstract class Tip
       
    56 case object Absent extends Tip
       
    57 case object Present extends Tip
       
    58 case object Correct extends Tip
       
    59 
       
    60 def pool(secret: String, word: String) : List[Char]= {
       
    61   for (i <- (0 to 4).toList 
       
    62        if secret(i) != word(i))
       
    63   yield secret(i) 
       
    64 }
       
    65 
       
    66 def aux(secret: List[Char], word: List[Char], pool: List[Char]) : List[Tip] = (secret, word) match {
       
    67     case (Nil, Nil) => Nil
       
    68     case (s::srest, w::wrest) => {
       
    69         if (s == w) Correct::aux(srest, wrest, pool)
       
    70         else if (pool.contains(w)) Present::aux(srest, wrest, removeOne(pool, w))
       
    71         else  Absent::aux(srest, wrest, pool)
       
    72     }
       
    73 }
       
    74 
       
    75 def score(secret: String, word: String) : List[Tip] =
       
    76     aux(secret.toList, word.toList, pool(secret, word))
       
    77 
       
    78 /*
       
    79 def pool(secret: String, word: String) : List[Char] = {
       
    80 	(secret zip word).collect {
       
    81 		case (c1, c2) if c1 != c2 => s"$c1"
       
    82 	}.toList.flatten
       
    83 }
       
    84 
       
    85 def aux2(secret: String, word: String, pool: List[Char], result: List[Tip]) : List[Tip] = {
       
    86     if (word.length == 0){
       
    87         result.reverse
       
    88     }
       
    89     else{
       
    90 		if (word.take(1) == secret.take(1)) {
       
    91 			val updated = Correct :: result	
       
    92 			aux2(secret.drop(1), word.drop(1), pool, updated)
       
    93 		}	
       
    94 		else {
       
    95 			if(pool.contains(word.take(1)(0))){
       
    96 				val updated = Present :: result
       
    97 				val removed = removeOne(pool, word.take(1)(0)).mkString.toList 
       
    98 				aux2(secret.drop(1), word.drop(1), removed, updated)
       
    99 			}
       
   100 			else{
       
   101 				val updated = Absent :: result
       
   102 				aux2(secret.drop(1), word.drop(1), pool, updated)
       
   103 			}
       
   104 		}
       
   105 	}
       
   106 }
       
   107 
       
   108 def aux(secret: List[Char], word: List[Char], pool: List[Char]) : List[Tip] = {
       
   109     aux2(secret.mkString, word.mkString, pool, List())
       
   110 }
       
   111 
       
   112 def score(secret: String, word: String) : List[Tip] = {
       
   113     aux(secret.toList, word.toList, pool(secret, word))
       
   114 }
       
   115 */
       
   116 
       
   117 // score("chess", "caves")
       
   118 // score("doses", "slide")
       
   119 // score("chess", "swiss")
       
   120 // score("chess", "eexss")
       
   121 
       
   122 
       
   123 //=============================
       
   124 // Task 4 [0.5 Marks]
       
   125 
       
   126 def eval(t: Tip) : Int = t match {
       
   127     case Correct => 10
       
   128     case Present => 1
       
   129     case Absent => 0
       
   130 }
       
   131 
       
   132 def iscore(secret: String, word: String) : Int = {
       
   133     val list = score(secret, word)
       
   134 	val values = list.map(n => eval(n))
       
   135 	values.sum
       
   136 }
       
   137 
       
   138 // iscore("chess", "caves")
       
   139 // iscore("doses", "slide")
       
   140 // iscore("chess", "swiss")
       
   141 // iscore("chess", "eexss")
       
   142 
       
   143 //=============================
       
   144 // Task 5 [1.5 Mark]
       
   145 
       
   146 def lowest(secrets: List[String], word: String, current: Int, acc: List[String]) : List[String] = {
       
   147     val mapped = secrets.map(x => (x, iscore(x, word)))
       
   148     val min = mapped.minBy(_._2)._2
       
   149     val filt = mapped.filter(_._2 == min)
       
   150     filt.map(x => x._1)
       
   151 }
       
   152 
       
   153 def evil(secrets: List[String], word: String) : List[String] = {
       
   154     lowest(secrets, word, Int.MaxValue, List())
       
   155 }
       
   156 
       
   157 //evil(secrets, "stent").length 
       
   158 //evil(secrets, "hexes").length 
       
   159 //evil(secrets, "horse").length 
       
   160 //evil(secrets, "hoise").length 
       
   161 //evil(secrets, "house").length 
       
   162 
       
   163 
       
   164 //=============================
       
   165 // Task 6 [1 Mark]
       
   166 
       
   167 def frequencies(secrets: List[String]) : Map[Char, Double] = {
       
   168     val all = secrets.flatten
       
   169     all.groupBy(identity).view.mapValues(1.0D - _.size.toDouble / all.size ).toMap
       
   170 }
       
   171 
       
   172 //frequencies(secrets)('y')
       
   173 
       
   174 /*
       
   175 
       
   176 def frequencies(secrets: List[String]) : Map[Char, Double] = {
       
   177     val letters = secrets.flatten
       
   178     val totalLetters = letters.length.toDouble
       
   179     val alph = ('a' to 'z').toList
       
   180     val letterCount = alph.map(x => (x, letters.filter(_ == x).length.toDouble))
       
   181     letterCount.map(x => (x._1, 1.0-(letterCount.filter(_._1 == x._1)(0)._2/totalLetters))).toMap
       
   182 }
       
   183 */
       
   184 
       
   185 // frequencies(secrets)('y')
       
   186 // frequencies(secrets)('e')
       
   187 
       
   188 //=============================
       
   189 // Task 7 [1 Mark]
       
   190 
       
   191 def rank(frqs: Map[Char, Double], s: String) = {
       
   192     s.map(frqs(_)).sum
       
   193 }
       
   194 
       
   195 def ranked_evil(secrets: List[String], word: String) = {
       
   196     val frqs = frequencies(secrets)
       
   197     val ev = evil(secrets, word)
       
   198     ev.groupBy(rank(frqs, _)).toList.sortBy(_._1).reverse.head._2
       
   199 }
       
   200 
       
   201 /*
       
   202 def rank(frqs: Map[Char, Double], s: String) : Double = {
       
   203     val letters = s.toList
       
   204     val scores = letters.map(x => frqs(x).toDouble)
       
   205     scores.sum
       
   206 }
       
   207 
       
   208 def ranked_evil(secrets: List[String], word: String) : List[String] = {
       
   209     val most = evil(secrets, word)
       
   210     val mapped = most.map(x => (x, rank(frequencies(secrets),x)))
       
   211     val mx = mapped.maxBy(_._2)._2
       
   212     val filt = mapped.filter(_._2 == mx)
       
   213     filt.map(x => x._1)
       
   214 }
       
   215 */
       
   216 //rank(frequencies(secrets), "adobe") 
       
   217 //rank(frequencies(secrets), "gaffe") 
       
   218 //rank(frequencies(secrets), "fuzzy") 
       
   219 
       
   220 //ranked_evil(secrets, "beats") 
       
   221 //ranked_evil(secrets, "vitae") 
       
   222 //ranked_evil(secrets, "bento") 
       
   223 //ranked_evil(secrets, "belts") 
       
   224 
       
   225 }