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 |