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