@mwildon/

SubstitutionHillClimbWeb

Haskell

Decrypt monoalphabetic substitution ciphers by hill climbing, scoring by n-gram frequencies.

fork
loading
Files
  • main.hs
main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
-- Mark Wildon, for Royal Holloway MT362/462/5462 Cipher Systems 2018 

-- Hit run above: it will take a few seconds because of the huge list of trigrams below

module SubstitutionHillClimbWeb2 where

import Data.Char
import Data.List
import qualified Data.Set as S
import qualified Data.Map as M

main = putStrLn "Welcome to SubstitutionHillClimbWeb: try\n  (*) trigramSolve 2000 <your ciphertext in quotes> to hill climb scoring using a list of the 2000 most common trigrams, starting with the guess implied by frequency analysis \n  (*) trigramSolveRev m; as above, but starting with a->z, ..., z->a. \n  (*) trigramSolve 2000 testCiphertext to run on the ciphertext from Example 2.5.\n  (*) digramSolve <your ciphertext in quotes> to hill climb using all digrams.\n\nRemarks:\n  (a) The ciphertext from Example 2.5' is available as testCiphertextAlt.\n  (b) Use trigramSolveMoreSteps and digramSolveMoreSteps to try more steps when a single swap does not improve the score.\n  (c) In the web version only 4000 of the 26^3 = 17576 trigrams are available. Unknown grams are given a guessed loglikelihood less than the least likely gram in the list."


-------------------------------------------------------------------------------
-- From frequencies of grams to log-likelihoods

gramCountsToMap :: [(Gram, Integer)] -> M.Map Gram Double
gramCountsToMap gramCounts = 
    M.fromList [(map toLower gram, log (fromInteger count) - log (fromInteger n)) | (gram, count) <- gramCounts]
    where n = sum $ map snd $ gramCounts   


-------------------------------------------------------------------------------
-- Digrams: the list below of digram frequencies was taken from the data at
--      http://practicalcryptography.com/cryptanalysis/text-characterisation/quadgrams/#a-python-implementation 

digramFs = [("TH", 116997844), ("HE", 100689263), ("IN", 87674002), ("ER", 77134382), ("AN", 69775179), ("RE", 60923600), ("ES", 57070453), ("ON", 56915252), ("ST", 54018399), ("NT", 50701084), ("EN", 48991276), ("AT", 48274564), ("ED", 46647960), ("ND", 46194306), ("TO", 46115188), ("OR", 45725191), ("EA", 43329810), ("TI", 42888666), ("AR", 42353262), ("TE", 42295813), ("NG", 38567365), ("AL", 38211584), ("IT", 37938534), ("AS", 37773878), ("IS", 37349981), ("HA", 35971841), ("ET", 32872552), ("SE", 31532272), ("OU", 31112284), ("OF", 30540904), ("LE", 30383262), ("SA", 30080131), ("VE", 29320973), ("RO", 29230770), ("RA", 28645577), ("RI", 27634643), ("HI", 27495342), ("NE", 27331675), ("ME", 27237733), ("DE", 27029835), ("CO", 26737101), ("TA", 26147593), ("EC", 25775798), ("SI", 25758841), ("LL", 24636875), ("SO", 23903631), ("NA", 23547524), ("LI", 23291169), ("LA", 23178317), ("EL", 23092248), ("MA", 21828378), ("DI", 21673998), ("IC", 21468412), ("RT", 21456059), ("NS", 21306421), ("RS", 21237259), ("IO", 21210160), ("OM", 21066156), ("CH", 20132750), ("OT", 20088048), ("CA", 19930754), ("CE", 19803619), ("HO", 19729026), ("BE", 19468489), ("TT", 19367472), ("FO", 18923772), ("TS", 18922522), ("SS", 18915696), ("NO", 18894111), ("EE", 18497942), ("EM", 18145294), ("AC", 17904683), ("IL", 17877600), ("DA", 17584055), ("NI", 17452104), ("UR", 17341717), ("WA", 16838794), ("SH", 16773127), ("EI", 16026915), ("AM", 15975981), ("TR", 15821226), ("DT", 15759673), ("US", 15699353), ("LO", 15596310), ("PE", 15573318), ("UN", 15237699), ("NC", 15214623), ("WI", 15213018), ("UT", 15137169), ("AD", 14877234), ("EW", 14776406), ("OW", 14610429), ("GE", 14425023), ("EP", 14024377), ("AI", 13974919), ("LY", 13742031), ("OL", 13726491), ("FT", 13696078), ("OS", 13596265), ("EO", 13524186), ("EF", 13252227), ("PR", 13191182), ("WE", 13185116), ("DO", 13120322), ("MO", 12950768), ("ID", 12896787), ("IE", 12505546), ("MI", 12168944), ("PA", 12068709), ("FI", 11993833), ("PO", 11917535), ("CT", 11888752), ("WH", 11852909), ("IR", 11681353), ("AY", 11523416), ("GA", 11239788), ("SC", 10800636), ("KE", 10650670), ("EV", 10574011), ("SP", 10570626), ("IM", 10544422), ("OP", 10459455), ("DS", 10429887), ("LD", 10245579), ("UL", 10173468), ("OO", 10168856), ("SU", 10031005), ("IA", 10002012), ("GH", 9880399), ("PL", 9812226), ("EB", 9738798), ("IG", 9530574), ("VI", 9380037), ("IV", 9129232), ("WO", 9106647), ("YO", 9088497), ("RD", 9025637), ("TW", 8910254), ("BA", 8867461), ("AG", 8809266), ("RY", 8788539), ("AB", 8775582), ("LS", 8675452), ("SW", 8673234), ("AP", 8553911), ("FE", 8529289), ("TU", 8477495), ("CI", 8446084), ("FA", 8357929), ("HT", 8351551), ("FR", 8339376), ("AV", 8288885), ("EG", 8286463), ("GO", 8188708), ("BO", 8172395), ("BU", 8113271), ("TY", 8008918), ("MP", 7835172), ("OC", 7646952), ("OD", 7610214), ("EH", 7559141), ("YS", 7539621), ("EY", 7528342), ("RM", 7377989), ("OV", 7350014), ("GT", 7347990), ("YA", 7239548), ("CK", 7205091), ("GI", 7103140), ("RN", 7064635), ("GR", 6989963), ("RC", 6974063), ("BL", 6941044), ("LT", 6817273), ("YT", 6714151), ("OA", 6554221), ("YE", 6499305), ("OB", 6212512), ("DB", 6106719), ("FF", 6085519), ("SF", 6073995), ("RR", 5896212), ("DU", 5861311), ("KI", 5814357), ("UC", 5742385), ("IF", 5740414), ("AF", 5702567), ("DR", 5701879), ("CL", 5683204), ("EX", 5649363), ("SM", 5580755), ("PI", 5559210), ("SB", 5553684), ("CR", 5514347), ("TL", 5403137), ("OI", 5336616), ("RU", 5330557), ("UP", 5306948), ("BY", 5232074), ("TC", 5196817), ("NN", 5180899), ("AK", 5137311), ("SL", 4965012), ("NF", 4950333), ("UE", 4927837), ("DW", 4906814), ("AU", 4884168), ("PP", 4873393), ("UG", 4832325), ("RL", 4803246), ("RG", 4645938), ("BR", 4621080), ("CU", 4604045), ("UA", 4589997), ("DH", 4585765), ("RK", 4491400), ("YI", 4461214), ("LU", 4402940), ("UM", 4389720), ("BI", 4356462), ("NY", 4343290), ("NW", 4215967), ("QU", 4169424), ("OG", 4163126), ("SN", 4157990), ("MB", 4121764), ("VA", 4111375), ("DF", 4033878), ("DD", 4001275), ("MS", 3922855), ("GS", 3920675), ("AW", 3918960), ("NH", 3915410), ("PU", 3858148), ("HR", 3843001), ("SD", 3842250), ("TB", 3815459), ("PT", 3812475), ("NM", 3796928), ("DC", 3782481), ("GU", 3768430), ("TM", 3759861), ("MU", 3755834), ("NU", 3732602), ("MM", 3730508), ("NL", 3692985), ("EU", 3674130), ("WN", 3649615), ("NB", 3602692), ("RP", 3588188), ("DM", 3544905), ("SR", 3513808), ("UD", 3499535), ("UI", 3481482), ("RF", 3436232), ("OK", 3397570), ("YW", 3379064), ("TF", 3368452), ("IP", 3348621), ("RW", 3348005), ("RB", 3346212), ("OH", 3254659), ("KS", 3227333), ("DP", 3145043), ("FU", 3138900), ("YC", 3128053), ("TP", 3070427), ("MT", 3055946), ("DL", 3050945), ("NK", 3043200), ("CC", 3026492), ("UB", 2990868), ("RH", 2968706), ("NP", 2968126), ("JU", 2924815), ("FL", 2890839), ("DN", 2840522), ("KA", 2833038), ("PH", 2825344), ("HU", 2771830), ("JO", 2721345), ("LF", 2702522), ("YB", 2696786), ("RV", 2692445), ("OE", 2616308), ("IB", 2598444), ("IK", 2585124), ("YP", 2581863), ("GL", 2576787), ("LP", 2543957), ("YM", 2516273), ("LB", 2463693), ("HS", 2462026), ("DG", 2442139), ("GN", 2426429), ("EK", 2411639), ("NR", 2393580), ("PS", 2377036), ("TD", 2346516), ("LC", 2328063), ("SK", 2321888), ("YF", 2305244), ("YH", 2291273), ("VO", 2253292), ("AH", 2225270), ("DY", 2218040), ("LM", 2216514), ("SY", 2214270), ("NV", 2194534), ("YD", 2122337), ("FS", 2047416), ("SG", 2043770), ("YR", 2021939), ("YL", 2013939), ("WS", 1988727), ("MY", 1949129), ("OY", 1932892), ("KN", 1903836), ("IZ", 1865802), ("XP", 1840696), ("LW", 1836811), ("TN", 1782119), ("KO", 1758001), ("AA", 1721143), ("JA", 1712763), ("ZE", 1709871), ("FC", 1570791), ("GW", 1567991), ("TG", 1530045), ("XT", 1509969), ("FH", 1507604), ("LR", 1505092), ("JE", 1487348), ("YN", 1485655), ("GG", 1468286), ("GF", 1465290), ("EQ", 1461436), ("HY", 1446451), ("KT", 1443985), ("HC", 1441057), ("BS", 1409672), ("HW", 1403223), ("HN", 1383958), ("CS", 1381608), ("HM", 1353001), ("NJ", 1342735), ("HH", 1329998), ("WT", 1301293), ("GC", 1299541), ("LH", 1274048), ("EJ", 1256993), ("FM", 1251312), ("DV", 1238565), ("LV", 1238287), ("WR", 1226755), ("GP", 1215204), ("FP", 1199845), ("GB", 1184377), ("GM", 1178511), ("HL", 1169468), ("LK", 1164186), ("CY", 1145316), ("MC", 1101727), ("YG", 1049082), ("XI", 1024736), ("HB", 1014004), ("FW", 1005903), ("GY", 979804), ("HP", 978649), ("MW", 937621), ("PM", 931225), ("ZA", 929119), ("LG", 926472), ("IW", 922059), ("XA", 904148), ("FB", 888155), ("SV", 882083), ("GD", 879792), ("IX", 879360), ("AJ", 870262), ("KL", 846309), ("HF", 834284), ("HD", 828755), ("AE", 815963), ("SQ", 800346), ("DJ", 799366), ("FY", 789961), ("AZ", 768359), ("LN", 752316), ("AO", 749566), ("FD", 748027), ("KW", 719633), ("MF", 715087), ("MH", 710864), ("SJ", 704442), ("UF", 701892), ("TV", 698150), ("XC", 697995), ("YU", 695512), ("BB", 689158), ("WW", 674610), ("OJ", 661082), ("AX", 660826), ("MR", 660619), ("WL", 657782), ("XE", 653947), ("KH", 650095), ("OX", 650078), ("UO", 649906), ("ZI", 644035), ("FG", 637758), ("IH", 610683), ("TK", 610333), ("II", 607124), ("IU", 576683), ("TJ", 559473), ("MN", 558397), ("WY", 553647), ("KY", 553296), ("KF", 537342), ("FN", 534362), ("UY", 531960), ("PW", 530411), ("DK", 525744), ("RJ", 518157), ("UK", 514873), ("KR", 507020), ("KU", 506618), ("WM", 505687), ("KM", 485617), ("MD", 481126), ("ML", 478528), ("EZ", 465466), ("KB", 457860), ("WC", 448394), ("WD", 432646), ("HG", 429607), ("BT", 428276), ("ZO", 424016), ("KC", 420017), ("PF", 418168), ("YV", 411487), ("PC", 400308), ("PY", 396147), ("WB", 394820), ("YK", 391953), ("CP", 382923), ("YJ", 378679), ("KP", 375653), ("PB", 369336), ("CD", 358435), ("JI", 357577), ("UW", 352732), ("UH", 339341), ("WF", 336213), ("YY", 332973), ("WP", 321746), ("BC", 320380), ("AQ", 315068), ("CB", 298053), ("IQ", 291635), ("CM", 285942), ("MG", 285133), ("DQ", 283314), ("BJ", 282608), ("TZ", 280007), ("KD", 277982), ("PD", 273162), ("FJ", 269865), ("CF", 267630), ("NZ", 266461), ("CW", 257253), ("FV", 244685), ("VY", 233082), ("FK", 228905), ("OZ", 228556), ("ZZ", 221275), ("IJ", 219128), ("LJ", 218362), ("NQ", 217422), ("UV", 212051), ("XO", 211173), ("PG", 211133), ("HK", 210385), ("KG", 209266), ("VS", 204093), ("HV", 197539), ("BM", 191807), ("HJ", 189906), ("CN", 188046), ("GV", 186777), ("CG", 181590), ("WU", 180884), ("GJ", 176947), ("XH", 166599), ("GK", 163830), ("TQ", 159111), ("CQ", 157546), ("RQ", 156933), ("BH", 154489), ("XS", 154347), ("UZ", 153736), ("WK", 148964), ("XU", 147533), ("UX", 144814), ("BD", 141752), ("BW", 140189), ("WG", 139890), ("MV", 136314), ("MJ", 134263), ("PN", 131645), ("XM", 127492), ("OQ", 122677), ("BV", 120081), ("XW", 119322), ("KK", 118811), ("BP", 115161), ("ZU", 113538), ("RZ", 113432), ("XF", 113031), ("MK", 111041), ("ZH", 107639), ("BN", 106125), ("ZY", 105871), ("HQ", 101241), ("WJ", 99435), ("IY", 98361), ("DZ", 98038), ("VR", 96416), ("ZS", 94993), ("XY", 94329), ("CV", 94224), ("XB", 94041), ("XR", 90046), ("UJ", 88168), ("YQ", 87953), ("VD", 85611), ("PK", 83017), ("VU", 82830), ("JR", 80471), ("ZL", 80039), ("SZ", 79840), ("YZ", 78281), ("LQ", 77148), ("KJ", 76816), ("BF", 75352), ("NX", 74844), ("QA", 73527), ("QI", 73387), ("KV", 73184), ("ZW", 68865), ("WV", 63930), ("UU", 63043), ("VT", 62912), ("VP", 62577), ("XD", 60101), ("GQ", 59750), ("XL", 59585), ("VC", 59024), ("CZ", 57914), ("LZ", 57314), ("ZT", 56955), ("WZ", 52836), ("SX", 50975), ("ZB", 50652), ("VL", 49032), ("PV", 48105), ("FQ", 47504), ("PJ", 47043), ("ZM", 46034), ("VW", 45608), ("CJ", 41526), ("ZC", 41037), ("BG", 40516), ("JS", 39326), ("XG", 39289), ("RX", 38654), ("HZ", 37066), ("XX", 35052), ("VM", 35024), ("XN", 34734), ("QW", 34669), ("JP", 34520), ("VN", 33082), ("ZD", 32906), ("ZR", 32685), ("FZ", 31186), ("XV", 31117), ("ZP", 30389), ("VH", 30203), ("VB", 29192), ("ZF", 28658), ("GZ", 28514), ("TX", 28156), ("VF", 28090), ("DX", 27413), ("QB", 27307), ("BK", 26993), ("ZG", 26369), ("VG", 25585), ("JC", 24770), ("ZK", 24262), ("ZN", 24241), ("UQ", 23386), ("JM", 22338), ("VV", 22329), ("JD", 21903), ("MQ", 21358), ("JH", 20960), ("QS", 20847), ("JT", 20408), ("JB", 19380), ("FX", 19313), ("PQ", 18607), ("MZ", 18271), ("YX", 16945), ("QT", 16914), ("WQ", 16245), ("JJ", 16085), ("JW", 16083), ("LX", 15467), ("GX", 14778), ("JN", 14452), ("ZV", 14339), ("MX", 14250), ("JK", 13967), ("KQ", 13905), ("XK", 13651), ("JF", 12640), ("QM", 12315), ("QH", 12273), ("JL", 12149), ("JG", 12023), ("VK", 11469), ("VJ", 11432), ("KZ", 11192), ("QC", 10667), ("XJ", 10629), ("PZ", 9697), ("QL", 9603), ("QO", 9394), ("JV", 8925), ("QF", 8778), ("QD", 8678), ("BZ", 8132), ("HX", 7526), ("ZJ", 7167), ("PX", 6814), ("QP", 6062), ("QE", 6020), ("QR", 5975), ("ZQ", 5773), ("JY", 5723), ("BQ", 5513), ("XQ", 5416), ("CX", 5300), ("KX", 5083), ("WX", 4678), ("QY", 4557), ("QV", 4212), ("QN", 3808), ("VX", 3192), ("BX", 3021), ("JZ", 2859), ("VZ", 2633), ("QG", 2567), ("QQ", 2499), ("ZX", 2463), ("XZ", 2082), ("QK", 2023), ("VQ", 1488), ("QJ", 1342), ("QX", 765), ("JX", 747), ("JQ", 722), ("QZ", 280)]

digramLLs n = gramCountsToMap $ take n digramFs

-------------------------------------------------------------------------------
-- Trigrams: again taken from http://practicalcryptography.com/cryptanalysis/text-characterisation/quadgrams/#a-python-implementation, pruned to 3500 (2500 is chosen to work well on testCiphertext: does not work with testCiphertextAlt, but hill climb still gives a much better guess for the key than just using frequencies)

trigramFs = [("THE", 77534223), ("AND", 30997177), ("ING", 30679488), ("ENT", 17902107), ("ION", 17769261), ("HER", 15277018), ("FOR", 14686159), ("THA", 14222073), ("NTH", 14115952), ("INT", 13656197), ("ERE", 13287155), ("TIO", 13285065), ("TER", 12769843), ("EST", 11956466), ("ERS", 11823017), ("ATI", 11227573), ("HAT", 10900482), ("ATE", 10712298), ("ALL", 10501105), ("ETH", 10304110), ("HES", 10189449), ("VER", 10156140), ("HIS", 10051039), ("OFT", 9434246), ("ITH", 9142241), ("FTH", 9036651), ("STH", 9024058), ("OTH", 8869058), ("RES", 8835871), ("ONT", 8757161), ("DTH", 8745845), ("ARE", 8741156), ("REA", 8700830), ("EAR", 8697937), ("WAS", 8640940), ("SIN", 8629893), ("STO", 8556837), ("TTH", 8476119), ("STA", 8399345), ("THI", 8363593), ("TIN", 8218047), ("TED", 8041574), ("ONS", 8021511), ("EDT", 8020254), ("WIT", 8004722), ("SAN", 7891127), ("DIN", 7875604), ("ORT", 7874634), ("CON", 7783588), ("RTH", 7614477), ("EVE", 7496438), ("ECO", 7431806), ("ERA", 7356760), ("IST", 7313698), ("NGT", 7144484), ("AST", 7076453), ("ILL", 6975276), ("COM", 6822254), ("ORE", 6741972), ("IVE", 6712953), ("NCE", 6427055), ("ONE", 6425910), ("EDI", 6392677), ("PRO", 6391322), ("ESS", 6386660), ("OUT", 6378894), ("EIN", 6185157), ("ATT", 6182518), ("MEN", 6180305), ("HEC", 6149122), ("ESA", 6111223), ("HEN", 6104692), ("INA", 6075550), ("ERI", 6050105), ("ERT", 5996178), ("AME", 5865810), ("ITI", 5865519), ("OME", 5860498), ("SON", 5847185), ("ART", 5831801), ("MAN", 5817313), ("EAN", 5799025), ("ONA", 5779945), ("EOF", 5756556), ("TOR", 5747955), ("HEA", 5690657), ("RAN", 5689705), ("RIN", 5638699), ("INE", 5633622), ("EDA", 5631878), ("NTO", 5586276), ("AVE", 5572665), ("NIN", 5546959), ("OVE", 5531804), ("OUN", 5481400), ("AIN", 5432669), ("ANT", 5421991), ("STR", 5396497), ("ETO", 5376005), ("HEM", 5373422), ("SOF", 5368053), ("PER", 5287148), ("NDE", 5281816), ("STE", 5280710), ("NTE", 5254251), ("EAS", 5242816), ("DTO", 5221682), ("OUR", 5202269), ("RED", 5156973), ("ROM", 5100537), ("TOF", 5096219), ("GHT", 5092181), ("TOT", 5056852), ("ESE", 5051138), ("CHA", 5041682), ("ICA", 5019144), ("HEI", 5014871), ("HIN", 5012646), ("IDE", 4997387), ("NDT", 4988098), ("HAN", 4986889), ("TAN", 4986672), ("LIN", 4958736), ("NOT", 4926753), ("DER", 4926618), ("ECT", 4884814), ("TRA", 4876453), ("IGH", 4863948), ("FRO", 4829903), ("EAT", 4829589), ("STI", 4809152), ("HEP", 4734063), ("NDI", 4733858), ("INS", 4731177), ("SHE", 4695713), ("NAL", 4588739), ("PLA", 4569489), ("ALS", 4535715), ("EEN", 4523428), ("NTI", 4517533), ("YOU", 4497537), ("LAN", 4497041), ("UND", 4458299), ("NDA", 4455712), ("RAT", 4421262), ("LEA", 4411707), ("CAN", 4410865), ("HAS", 4380710), ("NDS", 4369577), ("NGA", 4351576), ("HEL", 4339499), ("HED", 4315177), ("INC", 4296681), ("USE", 4234618), ("ESI", 4227261), ("GTH", 4226728), ("ASA", 4218160), ("HET", 4213058), ("NTS", 4199148), ("HAV", 4185092), ("HEW", 4184148), ("THO", 4180901), ("BUT", 4177438), ("NAN", 4169159), ("ASS", 4163441), ("HEF", 4130591), ("IES", 4122201), ("RET", 4119632), ("END", 4086364), ("PAR", 4078396), ("WER", 4049354), ("CTI", 4040752), ("REN", 4028281), ("REC", 4007198), ("CAL", 3993323), ("ITS", 3991750), ("REE", 3967861), ("ENE", 3964480), ("RST", 3957939), ("EAL", 3953609), ("ANA", 3928099), ("NST", 3917821), ("COU", 3904778), ("TUR", 3898211), ("MIN", 3872245), ("ITY", 3867433), ("YTH", 3864146), ("HEY", 3860009), ("ECA", 3843331), ("OUL", 3841433), ("LLE", 3814820), ("ARD", 3801093), ("ROU", 3800095), ("ANC", 3795939), ("OST", 3793366), ("PRE", 3756624), ("AGE", 3754029), ("EFO", 3748577), ("LES", 3743640), ("SSI", 3725958), ("EMA", 3718163), ("ESO", 3717656), ("TAT", 3713099), ("ATH", 3709084), ("WOR", 3693086), ("UST", 3688271), ("HEB", 3686363), ("EWA", 3681800), ("SHO", 3671437), ("IND", 3654793), ("SED", 3611490), ("HOU", 3592900), ("LLY", 3592380), ("ULD", 3587562), ("ASE", 3574910), ("URE", 3574802), ("ONO", 3567789), ("ELE", 3563169), ("ENC", 3544513), ("NAT", 3534314), ("EAD", 3528638), ("WHE", 3521734), ("ELL", 3518676), ("BLE", 3507036), ("KIN", 3501761), ("ANS", 3499108), ("TIC", 3488924), ("ALI", 3484802), ("SCO", 3482956), ("ERO", 3478803), ("WHI", 3477798), ("CES", 3462307), ("OWN", 3448194), ("NTA", 3445108), ("ACT", 3435753), ("BER", 3434019), ("VEN", 3419784), ("TIM", 3398024), ("DON", 3379285), ("DAN", 3372178), ("OSE", 3371757), ("ICE", 3371391), ("ISA", 3370411), ("TON", 3353323), ("DEN", 3344602), ("NGS", 3330887), ("UGH", 3317738), ("NES", 3309971), ("LAT", 3301464), ("TAL", 3291050), ("EDO", 3288422), ("TEN", 3283334), ("IME", 3280655), ("EME", 3269842), ("ACK", 3266991), ("TES", 3261242), ("PLE", 3255207), ("OUS", 3244841), ("OFF", 3240799), ("TTO", 3212842), ("CHI", 3205773), ("ANI", 3205086), ("ORM", 3199470), ("NED", 3184818), ("ENS", 3182416), ("SHA", 3173536), ("MOR", 3166737), ("ISS", 3165374), ("ITE", 3156935), ("NGE", 3151309), ("TIS", 3146867), ("ORA", 3143350), ("LLI", 3136609), ("EDE", 3129961), ("SSE", 3127188), ("ADE", 3123890), ("RIE", 3113740), ("AID", 3113433), ("EMO", 3110111), ("RAL", 3107661), ("SIT", 3101675), ("OIN", 3088712), ("HTH", 3060456), ("TRE", 3052381), ("ANY", 3050533), ("AKE", 3044556), ("ERN", 3041646), ("MER", 3035537), ("RIC", 3027796), ("DIS", 3027620), ("ISH", 3024492), ("OUG", 3024430), ("INI", 3019795), ("ONG", 3012833), ("NTR", 3012084), ("ELI", 3008425), ("WIL", 3000772), ("LED", 2999231), ("SAR", 2998776), ("HOW", 2984334), ("EDB", 2964266), ("ICH", 2961735), ("SPE", 2959184), ("SEA", 2956202), ("LIT", 2955844), ("YIN", 2951913), ("SAI", 2950251), ("NDO", 2945961), ("GIN", 2943401), ("SHI", 2938082), ("ORD", 2930631), ("MON", 2928062), ("ENA", 2927601), ("NEW", 2923860), ("POR", 2913196), ("SER", 2910499), ("IAL", 2904791), ("ORI", 2904248), ("TTE", 2896816), ("MAR", 2888260), ("EPR", 2880538), ("ACH", 2875296), ("HAR", 2871397), ("YEA", 2868255), ("TRI", 2866053), ("CHE", 2845883), ("TEA", 2838622), ("UNT", 2838483), ("OMP", 2837254), ("WHO", 2814944), ("TAR", 2792635), ("OWE", 2781353), ("RIT", 2761257), ("DED", 2753361), ("ORS", 2748974), ("DAY", 2743116), ("HEE", 2740198), ("THR", 2735049), ("EIR", 2733155), ("OND", 2727008), ("MES", 2724139), ("EFI", 2723419), ("HAD", 2720653), ("NER", 2711700), ("ELA", 2709547), ("LET", 2707044), ("LSO", 2705546), ("RIS", 2704354), ("IRE", 2671468), ("ISI", 2670537), ("MET", 2662370), ("ARS", 2649688), ("HIC", 2647497), ("CEN", 2640052), ("ARI", 2638406), ("FIN", 2636201), ("TOB", 2630326), ("NSI", 2628939), ("LAS", 2628928), ("OPE", 2622250), ("LAR", 2615291), ("DES", 2611133), ("FTE", 2609919), ("NIT", 2603876), ("SEN", 2603148), ("ANG", 2602649), ("SOM", 2589499), ("ABO", 2580787), ("SIO", 2579046), ("TWO", 2579039), ("IAN", 2576268), ("EIS", 2575332), ("TSA", 2574013), ("NGI", 2571550), ("UNI", 2567464), ("SES", 2562382), ("REP", 2561408), ("RAC", 2559421), ("TOP", 2544041), ("ABL", 2540517), ("ETI", 2525353), ("EBE", 2524168), ("EHA", 2512754), ("NOW", 2510743), ("ONI", 2508299), ("VES", 2501984), ("FIR", 2498628), ("ERC", 2496623), ("OFA", 2496302), ("ACE", 2494820), ("SAL", 2486424), ("GET", 2470450), ("APP", 2466311), ("ANE", 2464984), ("RSA", 2460648), ("NOF", 2459001), ("HEH", 2449367), ("GRE", 2446901), ("WIN", 2446474), ("CAR", 2441448), ("ETE", 2441107), ("MAT", 2437642), ("CHO", 2434122), ("LAY", 2432717), ("SWE", 2405370), ("ESP", 2403354), ("PRI", 2401791), ("TIV", 2399821), ("ROF", 2399401), ("GRA", 2397193), ("LLO", 2396797), ("COR", 2395975), ("EAC", 2395043), ("NIS", 2393749), ("DIT", 2388160), ("GAN", 2383084), ("GTO", 2380628), ("ENO", 2377544), ("BOU", 2375317), ("OBE", 2373367), ("ESH", 2364550), ("TOS", 2357896), ("ERY", 2357442), ("RMA", 2355852), ("NGO", 2355332), ("EWI", 2353887), ("ARA", 2352538), ("RTO", 2347763), ("REL", 2346911), ("OMA", 2338186), ("ALA", 2336606), ("ASI", 2327348), ("TST", 2322274), ("UTT", 2320714), ("IRS", 2319648), ("YAN", 2319387), ("LLA", 2318801), ("SFO", 2317576), ("ORK", 2313798), ("ETT", 2310024), ("LTH", 2309490), ("SID", 2309025), ("ASO", 2302496), ("SWI", 2302441), ("ITA", 2296822), ("SET", 2293924), ("TWA", 2290810), ("ERM", 2287584), ("EPA", 2287225), ("RON", 2286879), ("TIT", 2286372), ("AFT", 2285964), ("DRE", 2276501), ("TLE", 2274431), ("MIL", 2272608), ("DBY", 2271890), ("ALE", 2270031), ("PEN", 2258154), ("BEC", 2255869), ("MBE", 2249956), ("TOA", 2249363), ("HEG", 2247902), ("SCH", 2241757), ("SIS", 2237771), ("RTI", 2236581), ("HEO", 2235077), ("LOW", 2229147), ("LIS", 2227116), ("OLL", 2221181), ("WAR", 2218688), ("ALT", 2217527), ("ELO", 2217042), ("TRO", 2211596), ("CAT", 2201423), ("MED", 2201202), ("LIC", 2199356), ("HIL", 2195082), ("ILE", 2194746), ("THT", 2194530), ("REM", 2192851), ("RRE", 2192796), ("AYS", 2189923), ("OLI", 2188506), ("RSO", 2185861), ("NSA", 2176150), ("OMM", 2171097), ("OLD", 2165975), ("CRE", 2144746), ("ATA", 2142046), ("ISE", 2139169), ("CIA", 2122300), ("POS", 2117203), ("GER", 2116445), ("SMA", 2104563), ("UTI", 2103488), ("STS", 2101136), ("SEC", 2100837), ("SBE", 2099662), ("ENI", 2086703), ("SRE", 2085472), ("LON", 2085276), ("ISC", 2083075), ("NSE", 2074596), ("NOR", 2069326), ("BEE", 2065528), ("ANO", 2063752), ("NCO", 2060275), ("FER", 2058315), ("ITT", 2050561), ("SNO", 2047854), ("EPO", 2044817), ("EON", 2044067), ("EDS", 2037518), ("EAM", 2036924), ("ESC", 2036009), ("FIC", 2033404), ("ECH", 2028173), ("WAY", 2027041), ("VED", 2026846), ("IKE", 2026414), ("ALO", 2023953), ("YOF", 2021352), ("ASH", 2015194), ("OTE", 2008201), ("OOK", 1999949), ("ETA", 1996461), ("ERF", 1988818), ("ONC", 1984989), ("EMI", 1982819), ("ECI", 1972328), ("ATS", 1972278), ("ERV", 1970915), ("RSI", 1967666), ("SST", 1964979), ("ILI", 1962435), ("EED", 1955714), ("ARY", 1952466), ("SSO", 1951058), ("MTH", 1947257), ("VEL", 1945990), ("DAT", 1941336), ("MEA", 1936265), ("ESU", 1936169), ("URI", 1935162), ("PAN", 1932891), ("RCH", 1926389), ("UTH", 1926382), ("SPO", 1923682), ("WOU", 1923420), ("FFE", 1922327), ("SEL", 1921792), ("REI", 1917688), ("RGE", 1916665), ("RSE", 1915405), ("TOM", 1913479), ("USI", 1911341), ("EGA", 1900673), ("SAS", 1899943), ("SSA", 1897725), ("ATO", 1892931), ("ERW", 1888240), ("OOD", 1886459), ("AMA", 1883841), ("SAT", 1883499), ("ECE", 1883004), ("MPL", 1882970), ("TSO", 1879869), ("GEN", 1874679), ("ARR", 1868467), ("DEA", 1866349), ("SCA", 1864375), ("DOF", 1863197), ("UAL", 1862470), ("DBE", 1858905), ("EWO", 1857253), ("NSO", 1856959), ("RTE", 1856509), ("VIN", 1851748), ("ADI", 1851016), ("NDW", 1850414), ("NDH", 1849404), ("EDF", 1848247), ("SWH", 1844352), ("SEE", 1841310), ("TOC", 1836740), ("TCH", 1832199), ("EWH", 1821567), ("EBA", 1811725), ("ONL", 1806999), ("TEM", 1805921), ("DWI", 1790037), ("ERR", 1787600), ("LEC", 1784146), ("LAC", 1781542), ("EOP", 1780687), ("TEL", 1776664), ("AMI", 1770347), ("EHE", 1769301), ("DFO", 1768076), ("IEN", 1767735), ("UCH", 1765400), ("NDC", 1765357), ("ELY", 1763560), ("DST", 1760687), ("ICI", 1759901), ("EDW", 1744328), ("AUS", 1739916), ("NFO", 1738113), ("NTT", 1737999), ("NNE", 1735576), ("EWE", 1733602), ("SUR", 1732785), ("EXP", 1731960), ("BET", 1726872), ("KET", 1724117), ("INF", 1723019), ("ETR", 1721605), ("YTO", 1720045), ("RDE", 1718798), ("RCE", 1711836), ("OMT", 1711478), ("EVI", 1709656), ("VET", 1709103), ("PEC", 1705376), ("RAI", 1704886), ("ARL", 1699355), ("YST", 1698599), ("SOU", 1698194), ("HIM", 1697355), ("REF", 1690774), ("LIK", 1684406), ("GES", 1684204), ("CTO", 1684050), ("URN", 1681169), ("FOU", 1679554), ("LLS", 1678097), ("RNE", 1676735), ("WHA", 1674516), ("TOW", 1674141), ("NDR", 1673266), ("DAS", 1668669), ("SSU", 1668562), ("SPR", 1665665), ("OPL", 1665409), ("RAD", 1657646), ("ESW", 1655566), ("ONF", 1653251), ("COL", 1653235), ("OMI", 1652948), ("DUC", 1647753), ("MOS", 1646365), ("ARK", 1645609), ("TAI", 1644521), ("ICK", 1643469), ("HOS", 1637290), ("ULT", 1637016), ("EMB", 1634801), ("IGN", 1631196), ("HOO", 1628375), ("TOO", 1625886), ("NEA", 1624887), ("ITW", 1616943), ("PPE", 1615061), ("FFI", 1612124), ("ULA", 1611192), ("NAM", 1609688), ("MIS", 1605479), ("CED", 1603598), ("LOS", 1602442), ("GAM", 1602247), ("NAS", 1601741), ("REG", 1597733), ("LIE", 1594739), ("OLO", 1594420), ("TWE", 1587270), ("ANN", 1586455), ("TOD", 1581803), ("AIL", 1580257), ("OTA", 1579930), ("ISO", 1579642), ("AYE", 1577851), ("TCO", 1576339), ("GRO", 1575747), ("CAM", 1574337), ("EFE", 1573141), ("ONW", 1566810), ("BEA", 1565698), ("NGL", 1565333), ("WEE", 1562110), ("EDU", 1553785), ("REW", 1548929), ("AGA", 1546877), ("TIL", 1545610), ("ODE", 1543174), ("ORY", 1541795), ("ERB", 1541342), ("BAC", 1540779), ("LEN", 1536397), ("NLY", 1536381), ("IMP", 1535894), ("ARO", 1532759), ("EHI", 1530705), ("AMP", 1530333), ("MPA", 1529992), ("SPA", 1528054), ("IVI", 1526689), ("ICT", 1522977), ("STT", 1520500), ("NET", 1518271), ("RTA", 1515487), ("HRE", 1514079), ("ERH", 1512676), ("EET", 1506042), ("ROW", 1502520), ("SOR", 1500949), ("EPE", 1494253), ("TIE", 1489751), ("NCH", 1489431), ("TRU", 1489404), ("MAL", 1487982), ("CTE", 1487884), ("NDM", 1484172), ("ATC", 1482545), ("FAC", 1480054), ("TWI", 1479582), ("ORC", 1478504), ("DCO", 1476786), ("NDP", 1474820), ("FRE", 1474808), ("OFS", 1472502), ("ARG", 1472465), ("IMA", 1471252), ("DEC", 1470797), ("ENG", 1470110), ("RIA", 1469607), ("OWI", 1466971), ("EIT", 1466665), ("POL", 1460040), ("KED", 1458064), ("INN", 1457052), ("BLI", 1455188), ("DOW", 1453863), ("ETW", 1453345), ("CLU", 1453288), ("HOL", 1452519), ("AIR", 1452477), ("RRI", 1451834), ("RIG", 1451573), ("SLA", 1451493), ("ROP", 1450690), ("OFI", 1442502), ("TOH", 1442156), ("NON", 1440732), ("OOL", 1439680), ("ISP", 1438457), ("MAK", 1436485), ("REV", 1436262), ("EQU", 1435915), ("LYT", 1435747), ("JUS", 1432941), ("LYA", 1432205), ("OLE", 1432129), ("CIT", 1430939), ("PEA", 1429742), ("VEA", 1428357), ("KNO", 1427519), ("OCA", 1426991), ("TAK", 1426629), ("ACC", 1425476), ("CER", 1423677), ("ADA", 1423365), ("SUP", 1422660), ("NGW", 1422627), ("PEO", 1422371), ("DSO", 1419444), ("RDI", 1418963), ("TOU", 1417176), ("CAU", 1416389), ("ROV", 1414811), ("TFO", 1411495), ("STU", 1409543), ("PIN", 1407254), ("TLY", 1402323), ("IED", 1397547), ("UES", 1397451), ("TSI", 1397349), ("AWA", 1393952), ("LER", 1393473), ("WEL", 1391559), ("EPL", 1386318), ("HOR", 1386236), ("ERP", 1385471), ("HRO", 1383286), ("UTE", 1381204), ("OSS", 1381105), ("TBE", 1380773), ("TYO", 1377771), ("TOG", 1377004), ("HEU", 1374864), ("BYT", 1372919), ("NGF", 1372845), ("NGH", 1370514), ("HAL", 1366096), ("BAN", 1364335), ("ISM", 1364013), ("ROL", 1362117), ("ATU", 1360997), ("SAM", 1357990), ("HOM", 1356978), ("DHI", 1356938), ("ILD", 1353068), ("GAI", 1352873), ("RDS", 1350997), ("EDH", 1350936), ("INO", 1349660), ("EGO", 1344776), ("EGI", 1343491), ("LLT", 1342420), ("ARC", 1342124), ("RAM", 1336917), ("OTO", 1333585), ("CLE", 1331933), ("DHE", 1330580), ("ACO", 1326689), ("ORL", 1324745), ("CAS", 1323734), ("RIV", 1323585), ("OFC", 1322736), ("ORN", 1321723), ("RNA", 1320486), ("URS", 1319719), ("AVI", 1319342), ("NAR", 1308406), ("UBL", 1305930), ("TTI", 1303589), ("MEM", 1299230), ("AMO", 1298805), ("RME", 1297846), ("QUI", 1297027), ("QUE", 1295216), ("NEE", 1295028), ("NDF", 1293951), ("INH", 1291301), ("INK", 1291259), ("EHO", 1290659), ("NCL", 1287912), ("OCK", 1285973), ("VIC", 1285160), ("RTS", 1285059), ("ETS", 1283594), ("LEG", 1280961), ("CLA", 1280292), ("TSE", 1278787), ("EOR", 1277439), ("NCI", 1277098), ("SLI", 1276516), ("ERG", 1275250), ("DID", 1273273), ("RCO", 1272521), ("BAS", 1269571), ("LOC", 1267778), ("EBU", 1267644), ("HIG", 1266946), ("ASP", 1264261), ("EXT", 1264120), ("EGR", 1263778), ("DIA", 1263355), ("TAB", 1262022), ("BRI", 1258167), ("CEI", 1256877), ("RAS", 1256196), ("DAL", 1253918), ("ALC", 1252782), ("RUN", 1252259), ("PPO", 1251513), ("OFH", 1251418), ("CKE", 1251112), ("ATW", 1251071), ("CEA", 1249363), ("OTT", 1248716), ("BAL", 1247492), ("NSH", 1247220), ("MAI", 1247125), ("DAR", 1246732), ("ASB", 1246692), ("RFO", 1246153), ("VIS", 1246067), ("OWA", 1244485), ("UDE", 1244334), ("RSH", 1242784), ("IFI", 1242367), ("LOO", 1237754), ("HIT", 1236658), ("UAR", 1235409), ("CET", 1234925), ("OVI", 1230666), ("NDB", 1229829), ("TOL", 1229522), ("UTO", 1228795), ("LEM", 1226802), ("BRO", 1226231), ("VID", 1226025), ("RIO", 1225040), ("UCT", 1223250), ("TRY", 1221955), ("EFR", 1219841), ("SDE", 1218798), ("DHA", 1216559), ("BEL", 1216264), ("BIL", 1216161), ("TAS", 1212346), ("SUC", 1212180), ("EBO", 1211243), ("ORO", 1210118), ("SEV", 1209104), ("MIT", 1207978), ("YCO", 1205248), ("NWH", 1202340), ("NEO", 1201979), ("RVI", 1201676), ("DEV", 1201012), ("EUN", 1199397), ("WAN", 1199161), ("SIG", 1198981), ("THS", 1198494), ("ASC", 1198386), ("DSA", 1195432), ("TAC", 1194122), ("EMP", 1190815), ("ANK", 1190563), ("RKE", 1189902), ("NHE", 1187989), ("NME", 1186511), ("NRE", 1186133), ("ROS", 1185577), ("NGC", 1185531), ("MAY", 1184263), ("UNC", 1184159), ("NIC", 1179045), ("NNI", 1178268), ("URA", 1178165), ("FUL", 1177774), ("OCO", 1176155), ("OSI", 1175625), ("DEF", 1173126), ("NGR", 1172606), ("TEC", 1171805), ("SAY", 1167136), ("NBE", 1166379), ("YRE", 1163260), ("NTL", 1158736), ("DGE", 1158225), ("SAC", 1157300), ("SFR", 1156780), ("TSH", 1155832), ("ISN", 1155747), ("LDI", 1154685), ("ARM", 1154487), ("CUR", 1154026), ("EAG", 1152862), ("NDL", 1152382), ("ELD", 1151107), ("SMO", 1151066), ("ORG", 1150650), ("LLB", 1146334), ("DEL", 1142439), ("POI", 1142345), ("IAT", 1138390), ("URT", 1138386), ("KER", 1138342), ("SOL", 1135331), ("TMA", 1135216), ("MUS", 1134974), ("BEI", 1129248), ("QUA", 1128688), ("LYS", 1127961), ("DWA", 1126001), ("NMA", 1124451), ("HIP", 1121067), ("ROD", 1117901), ("EFA", 1117822), ("INV", 1117314), ("ISL", 1114965), ("PON", 1114638), ("YON", 1110394), ("PAS", 1110326), ("LIA", 1110281), ("REO", 1109542), ("LIF", 1106740), ("TIA", 1101436), ("CRI", 1101185), ("NSU", 1101079), ("RLY", 1101077), ("LBE", 1100732), ("OHA", 1100513), ("NDD", 1099241), ("HAM", 1095060), ("EPT", 1094478), ("EBR", 1092945), ("BES", 1091585), ("NGP", 1087836), ("YHA", 1086604), ("TME", 1085683), ("LEF", 1085376), ("ADD", 1085339), ("OFM", 1084713), ("MAD", 1084502), ("DMA", 1083866), ("DUR", 1082620), ("MME", 1082430), ("MAS", 1082265), ("IZE", 1081305), ("ICS", 1081149), ("YBE", 1079784), ("DNO", 1079585), ("EGE", 1078863), ("GAT", 1078328), ("DDE", 1077820), ("CUL", 1076597), ("UTA", 1073065), ("MEO", 1071803), ("LCO", 1070168), ("VAL", 1068682), ("ATR", 1068298), ("ECU", 1066153), ("GED", 1064754), ("NDU", 1064326), ("YAR", 1064023), ("DET", 1064013), ("ISF", 1063940), ("OFP", 1062855), ("SPI", 1061878), ("ROT", 1057524), ("ROB", 1056410), ("PED", 1054595), ("LDE", 1053046), ("OTI", 1053021), ("EEK", 1052504), ("DEM", 1052486), ("BEF", 1052183), ("MOV", 1050191), ("ELS", 1046167), ("IOU", 1044561), ("SWA", 1043925), ("ERL", 1043663), ("IMI", 1042889), ("FAM", 1042513), ("NEX", 1041420), ("LOF", 1041254), ("FAN", 1037972), ("OES", 1036896), ("SCR", 1036292), ("ISW", 1035637), ("ULL", 1035476), ("ERD", 1035369), ("INM", 1031264), ("SOC", 1030632), ("RNI", 1029771), ("EEL", 1029077), ("APA", 1024211), ("MIC", 1022874), ("DEP", 1021947), ("RDA", 1021457), ("PIT", 1020699), ("OGR", 1020261), ("SUN", 1018713), ("ESF", 1016834), ("IDA", 1015249), ("GAR", 1014790), ("CKS", 1013705), ("RAG", 1012208), ("GEO", 1010675), ("GOO", 1010645), ("LUD", 1010627), ("NHI", 1010492), ("IFE", 1010418), ("BRA", 1010344), ("DDI", 1007782), ("PAT", 1007038), ("CEO", 1006221), ("NGB", 1005382), ("KES", 1004681), ("YER", 1003964), ("NWA", 1003919), ("DRA", 1002812), ("LYI", 1002743), ("ODU", 1002645), ("PUB", 1001460), ("INU", 1000911), ("ORR", 1000290), ("AYA", 996464), ("LOR", 995464), ("TTL", 994910), ("HON", 993715), ("SAB", 992618), ("NHA", 992520), ("LDB", 991325), ("LIV", 991168), ("EDR", 990568), ("SEO", 990217), ("OAD", 989827), ("RMO", 989810), ("DLE", 988862), ("ECR", 987834), ("UDI", 987132), ("GON", 986074), ("ALF", 985711), ("DIE", 985489), ("RWA", 985285), ("LST", 984346), ("LIG", 983332), ("RID", 983247), ("RMI", 983003), ("OFE", 982887), ("URC", 982799), ("SIC", 981605), ("APE", 981487), ("AYI", 979574), ("BOT", 978895), ("EYE", 978505), ("FRI", 977788), ("ILA", 977050), ("RYO", 976002), ("ADO", 975029), ("ALM", 973709), ("SAG", 971371), ("NWI", 970417), ("WED", 968979), ("NNO", 967863), ("ABI", 967606), ("RVE", 963010), ("EES", 962543), ("AKI", 961187), ("FIE", 958012), ("BOR", 957789), ("DOU", 956789), ("EEP", 956756), ("DIF", 955736), ("TET", 953672), ("ORP", 951409), ("ITO", 950819), ("AYT", 950677), ("ONH", 950343), ("OBA", 949834), ("TUD", 949705), ("VIE", 948746), ("NYO", 948617), ("SBU", 947427), ("DIC", 946442), ("DRI", 944706), ("OFO", 944159), ("OAN", 942758), ("RYA", 941495), ("RUS", 940945), ("XPE", 940860), ("NCA", 940507), ("NVE", 940457), ("ILY", 940279), ("HOT", 940089), ("NAG", 939358), ("UTS", 938259), ("LRE", 936657), ("RAP", 936308), ("ECL", 935699), ("DSE", 935507), ("OUP", 934968), ("LEO", 934394), ("UPP", 932971), ("ROA", 932716), ("NAD", 932247), ("BUS", 931889), ("NTW", 931065), ("ALP", 930693), ("URR", 929826), ("YFO", 927898), ("OMO", 927335), ("ONM", 926902), ("NTU", 925885), ("OWS", 925801), ("IFF", 924171), ("RSW", 922934), ("ASW", 922855), ("ASN", 921959), ("HAP", 921917), ("CCE", 921547), ("CRO", 920008), ("IER", 919867), ("CCO", 918426), ("CAP", 917801), ("LEV", 917563), ("TSW", 916039), ("KEN", 915282), ("OKE", 914528), ("OWT", 913700), ("ASM", 913312), ("NGM", 909434), ("CTS", 908610), ("NOU", 908318), ("PUT", 907446), ("REB", 907423), ("TTA", 907276), ("EDM", 907261), ("LIO", 905570), ("NEY", 903730), ("ONB", 902750), ("SFI", 902516), ("TAG", 899915), ("EEM", 899762), ("UMB", 898970), ("CRA", 897487), ("ANU", 897419), ("SWO", 896032), ("WEV", 894124), ("EIG", 894075), ("SSH", 893882), ("EUS", 893372), ("EYO", 893226), ("SIM", 892620), ("GLE", 891111), ("ROC", 890590), ("CIE", 889282), ("LOG", 887902), ("REH", 887583), ("WTH", 887581), ("SLO", 886813), ("EER", 885791), ("IFT", 885634), ("HEV", 885429), ("FIT", 885162), ("TUA", 884810), ("EPU", 883236), ("GOV", 882757), ("GOT", 881689), ("CIN", 881481), ("INW", 881201), ("INP", 880744), ("WES", 880455), ("AGO", 878275), ("AMS", 877451), ("SAP", 877362), ("ITU", 874511), ("OAC", 874056), ("OPP", 873487), ("ETU", 873006), ("WAT", 872808), ("SUS", 872787), ("LAI", 871693), ("ARN", 870961), ("EEA", 870693), ("ITC", 870348), ("ISR", 869416), ("TCA", 869399), ("RLD", 869118), ("ALR", 867408), ("ASK", 866144), ("CTU", 864234), ("LTO", 864157), ("OGE", 863518), ("OOT", 863453), ("EAP", 861991), ("PTI", 860467), ("EDP", 860390), ("FEA", 859460), ("FIL", 859216), ("TWH", 858217), ("NGU", 857993), ("EMS", 855525), ("VEB", 855318), ("UIL", 855123), ("MOT", 853945), ("ROO", 853786), ("RPR", 853610), ("RLI", 853213), ("MPO", 851424), ("ISB", 850560), ("ELF", 850206), ("DFR", 850149), ("SEI", 849888), ("OON", 849833), ("SLE", 849731), ("MOU", 848665), ("NEV", 848535), ("NEC", 847896), ("CLO", 847813), ("IEL", 847624), ("LOT", 847535), ("USA", 846781), ("APR", 843542), ("EDC", 843066), ("RER", 842459), ("LEI", 842440), ("FRA", 842263), ("WEA", 841454), ("NEN", 841269), ("ALW", 841195), ("ESB", 840316), ("BAR", 840216), ("EYA", 839220), ("NEI", 837374), ("NSW", 836504), ("ELP", 835693), ("OLA", 834566), ("EAK", 833378), ("FEN", 832986), ("ESN", 832939), ("RYT", 832890), ("ORH", 830305), ("ANB", 829651), ("LSA", 828413), ("FAR", 826427), ("GIV", 826400), ("PIC", 825459), ("CEP", 825186), ("TOE", 824070), ("DPR", 822558), ("RIM", 822547), ("EAB", 822472), ("PAC", 821850), ("LTI", 816837), ("HOF", 815652), ("ASU", 814744), ("SAF", 814636), ("EWS", 814323), ("STW", 812774), ("EEX", 812632), ("ATM", 812391), ("MPE", 809957), ("TBA", 808271), ("TEE", 807868), ("INB", 807768), ("EAV", 807633), ("DWH", 806469), ("NOM", 803907), ("MUN", 803602), ("ENH", 802824), ("RRO", 801038), ("PET", 800747), ("NSP", 800525), ("MTO", 800464), ("AGR", 800409), ("LEW", 799958), ("RHA", 799892), ("LVE", 799393), ("ALB", 797031), ("ODO", 796908), ("TUN", 793099), ("LWA", 792872), ("GUE", 792851), ("DCA", 791031), ("RAR", 790991), ("RWH", 790470), ("PAI", 789880), ("HOP", 789691), ("ROG", 789669), ("NFR", 789285), ("FAL", 788506), ("ONN", 788333), ("INL", 785826), ("SEP", 785709), ("BAT", 784957), ("SMI", 784836), ("VEM", 783222), ("CUS", 781942), ("EPI", 781039), ("WAL", 780890), ("DSH", 780123), ("LAB", 780098), ("THC", 779681), ("APO", 779192), ("AAN", 778034), ("ODI", 778023), ("FOL", 777834), ("GOF", 777113), ("SQU", 775089), ("SFA", 774151), ("BUR", 773363), ("NAC", 772048), ("RGA", 771129), ("VIL", 768622), ("NGD", 768292), ("OCI", 767682), ("HIR", 767491), ("RHE", 767325), ("USS", 766882), ("EFU", 766869), ("YWI", 766717), ("ESM", 766378), ("YWA", 765965), ("NPR", 765697), ("UME", 764858), ("ODA", 764180), ("OSA", 761513), ("DRO", 760176), ("GHE", 759642), ("GHI", 758796), ("OPR", 758671), ("VAN", 758117), ("LDS", 758046), ("KAN", 757432), ("BEG", 756632), ("RPO", 756089), ("ORW", 755584), ("ISD", 755138), ("DMI", 754985), ("GOI", 754257), ("FUN", 753435), ("OAR", 753004), ("OFR", 752128), ("ONP", 751018), ("RIB", 750630), ("IDI", 750544), ("RWI", 750504), ("LOP", 749405), ("HTO", 749075), ("EDD", 748966), ("STP", 747680), ("MAG", 747120), ("SNE", 747053), ("SEM", 746824), ("ERU", 745597), ("ADT", 745427), ("BUI", 743523), ("MMI", 743346), ("ALK", 741403), ("GAL", 741281), ("IBL", 740604), ("OPU", 739787), ("ALD", 739561), ("OAL", 739052), ("YSA", 738863), ("TSC", 738296), ("IDT", 737288), ("PLI", 736543), ("MUC", 734243), ("NUM", 733495), ("SBA", 733488), ("NEL", 732493), ("NIA", 731949), ("ENU", 731273), ("RUC", 730658), ("LYO", 729096), ("STM", 729012), ("BRE", 728972), ("TOI", 728263), ("ESD", 727442), ("DMO", 727349), ("RYI", 726845), ("OTS", 726751), ("SDA", 726137), ("VOL", 725080), ("DAM", 725025), ("ACA", 723596), ("RBE", 723228), ("PUL", 722952), ("WON", 722713), ("EXA", 722289), ("YED", 722156), ("LSE", 721672), ("ACI", 721498), ("STC", 721341), ("OFW", 721017), ("LIM", 720600), ("ATL", 720504), ("AIS", 720394), ("FLO", 719836), ("CEL", 719551), ("RNO", 719357), ("CHT", 718107), ("STY", 716897), ("BOO", 716442), ("AUG", 716308), ("RYS", 716185), ("UPT", 715152), ("SEX", 713764), ("SPL", 713561), ("RTY", 713321), ("EVA", 712427), ("YSI", 711593), ("OFB", 710199), ("LDR", 708872), ("UIT", 708569), ("CLI", 708407), ("MEI", 708327), ("IOR", 708025), ("DOE", 707379), ("IRA", 706829), ("LYW", 706710), ("IGI", 706526), ("SIV", 706163), ("NAB", 704679), ("LAW", 703214), ("TPR", 702904), ("LDA", 702508), ("AYO", 699492), ("RKI", 699433), ("IDN", 698899), ("NIO", 698381), ("IVA", 698321), ("TYA", 697860), ("PHO", 697238), ("COA", 697032), ("ILT", 697018), ("CHR", 696938), ("NDG", 696524), ("PHI", 694638), ("EFF", 694298), ("EYW", 694094), ("RAF", 693840), ("YIS", 693485), ("ASR", 692889), ("NOV", 692671), ("LYB", 692635), ("AUT", 692495), ("NAP", 692352), ("FEE", 691884), ("NDN", 691649), ("GFO", 691219), ("SUB", 687314), ("SKI", 687268), ("NTY", 686772), ("ASF", 685871), ("OOR", 685384), ("AFF", 684405), ("ENN", 684319), ("SDI", 683865), ("HUR", 683790), ("STL", 682423), ("LYC", 682030), ("DIR", 681719), ("CUT", 680248), ("WEN", 678834), ("AFE", 677985), ("DNE", 677379), ("KTH", 677290), ("PLO", 676417), ("RAB", 675092), ("NFI", 674720), ("YMA", 674417), ("OFL", 673526), ("UNG", 673098), ("ANW", 671305), ("TMO", 670892), ("ENW", 669856), ("GAS", 669056), ("TSS", 668030), ("JEC", 666952), ("FOO", 666339), ("GIS", 666021), ("VAT", 665784), ("LEY", 665497), ("TNE", 665303), ("USH", 664646), ("RNM", 664276), ("TSP", 664116), ("NSC", 663870), ("GEA", 663465), ("DIV", 663392), ("SAD", 662849), ("DSI", 662681), ("FCO", 662572), ("OPO", 661292), ("FHI", 660939), ("EDL", 660146), ("YOR", 659656), ("YCA", 659168), ("IEV", 657853), ("YWE", 657204), ("OMB", 657110), ("IRD", 656794), ("BIG", 656158), ("TIF", 655864), ("DLI", 655395), ("RHI", 654575), ("RCA", 654499), ("GHA", 653609), ("PTH", 651995), ("SGO", 651623), ("YWH", 651447), ("AVA", 650371), ("SIB", 649324), ("GWI", 648238), ("SUM", 648210), ("ATP", 647883), ("LEB", 647227), ("TSU", 646947), ("CKI", 646171), ("FEC", 645871), ("NCR", 645359), ("RLE", 645167), ("SME", 643840), ("CIS", 643554), ("TDO", 643395), ("OLU", 643228), ("KEA", 642826), ("IEW", 642230), ("YSE", 642198), ("MOD", 641999), ("UCE", 641986), ("FAI", 641095), ("NIG", 640768), ("TYE", 639722), ("TLI", 638560), ("TSF", 638419), ("RBA", 637207), ("DOR", 637114), ("ABA", 636023), ("ENB", 635879), ("BLA", 635788), ("RSC", 635650), ("THH", 635356), ("MPI", 634841), ("ADS", 633339), ("MMU", 633203), ("POW", 633181), ("LFO", 632552), ("GST", 631234), ("ASD", 630807), ("EGU", 629493), ("SNT", 627623), ("TNO", 626469), ("ADV", 625751), ("IET", 625730), ("BYA", 625497), ("NVI", 625320), ("AHA", 624623), ("OFD", 622723), ("COV", 622007), ("POP", 621776), ("RRA", 621221), ("NLI", 620769), ("LTE", 620647), ("UCA", 620588), ("DWE", 620118), ("TEI", 620001), ("NUE", 619320), ("FLA", 619320), ("SDO", 618505), ("RIL", 618424), ("IRO", 618372), ("IAM", 617315), ("TEV", 617226), ("ESL", 617035), ("MPR", 616160), ("EDG", 614818), ("MEW", 614610), ("ICO", 613938), ("YAL", 613547), ("YLE", 612247), ("NTF", 610686), ("STB", 610684), ("LYD", 610225), ("EFT", 609753), ("ORB", 609578), ("HTE", 609463), ("CEM", 609095), ("BEN", 608693), ("YAS", 608227), ("KEE", 608204), ("NTC", 607811), ("NTB", 606735), ("UNE", 606148), ("NEM", 605878), ("EOU", 604857), ("OUC", 603583), ("PPL", 603167), ("THU", 602655), ("TEX", 601212), ("ICU", 600343), ("RDO", 600167), ("SEW", 600057), ("SUL", 599610), ("OSP", 599565), ("EXC", 598704), ("OTB", 597457), ("GNE", 597340), ("IDS", 597319), ("KIL", 596517), ("LOV", 596167), ("SYS", 595842), ("IMS", 594877), ("NIV", 594561), ("OOM", 594423), ("STF", 593875), ("IRC", 593467), ("OHI", 593271), ("NMO", 593043), ("ASL", 592890), ("ONV", 592688), ("TDE", 591919), ("OCE", 589867), ("EBI", 589639), ("PTO", 589182), ("LDH", 588186), ("YPE", 586973), ("NIE", 585394), ("NSF", 584634), ("ELT", 584302), ("IBE", 584035), ("FIG", 583619), ("NPA", 583247), ("FAT", 582931), ("LYM", 582806), ("TYT", 582701), ("TYP", 582667), ("DNT", 582639), ("LUE", 582588), ("URO", 581947), ("OWH", 580772), ("OHE", 580308), ("BLO", 579956), ("WRI", 579264), ("HTS", 577913), ("RKS", 576408), ("DEO", 575421), ("HRI", 574942), ("SOT", 574851), ("LYR", 573992), ("DUS", 573106), ("AYB", 572949), ("CHU", 571970), ("TFR", 570894), ("WOM", 570036), ("YDE", 569800), ("BIN", 569494), ("REQ", 569352), ("GGE", 569035), ("MEL", 568097), ("FFO", 567614), ("ARB", 567346), ("SOP", 567101), ("UMA", 566671), ("VIO", 565932), ("INR", 565532), ("RTU", 565492), ("ROR", 565019), ("TAF", 565018), ("DAB", 564586), ("MEE", 564382), ("LEE", 564063), ("INJ", 563954), ("MSE", 563803), ("VEI", 563398), ("BED", 563256), ("BIT", 563243), ("HEK", 563111), ("URY", 563102), ("PPR", 562337), ("TEP", 561626), ("DAC", 560810), ("MAC", 560466), ("ACR", 560392), ("MMA", 560100), ("ENR", 559896), ("UTW", 559890), ("ONR", 559879), ("NJU", 559740), ("EYS", 558978), ("FAS", 558916), ("KTO", 557955), ("ORF", 557739), ("PTE", 557205), ("CID", 557156), ("YSH", 557064), ("VAR", 554992), ("SAW", 554210), ("EAF", 553523), ("TLA", 552885), ("CKA", 552873), ("SIA", 552868), ("OBL", 552685), ("UEN", 552559), ("RSU", 552342), ("OKI", 550803), ("UAT", 550712), ("UET", 550590), ("AJO", 550271), ("COS", 548835), ("CKT", 548249), ("CHW", 547094), ("OAS", 547084), ("LLH", 546923), ("SBO", 546255), ("FEW", 546208), ("MST", 545818), ("SCU", 545747), ("BOA", 545518), ("RRY", 544591), ("EEV", 544371), ("LMA", 543365), ("LYF", 542748), ("VEH", 542516), ("IDO", 542455), ("MID", 542131), ("OIS", 541358), ("TEO", 541333), ("SCI", 540904), ("OWO", 540143), ("UCK", 539189), ("DCH", 539085), ("IRT", 538812), ("OPA", 538667), ("RSS", 538580), ("AGU", 538214), ("RSP", 538077), ("ULE", 537905), ("EKI", 537234), ("BEH", 536853), ("OYE", 536753), ("NWE", 536458), ("DOM", 536014), ("ADY", 535778), ("YPR", 534788), ("NKI", 534130), ("FES", 533859), ("GIT", 533850), ("NFE", 533716), ("SSP", 533611), ("LOU", 532271), ("YMO", 531944), ("URG", 531285), ("PRA", 530776), ("DME", 530452), ("SOW", 530375), ("EDN", 530369), ("SAV", 529041), ("ICL", 527724), ("OPI", 527628), ("LYP", 527472), ("KOF", 527245), ("NLA", 527108), ("LDT", 526989), ("RAV", 526859), ("TFI", 526850), ("DOT", 526027), ("RFA", 525159), ("EAU", 524482), ("NHO", 524339), ("DBA", 524137), ("NIM", 523850), ("CEW", 523836), ("SKE", 523792), ("ENF", 523355), ("RHO", 523322), ("NNA", 523153), ("TPA", 523107), ("WIS", 522583), ("DFI", 521982), ("ANH", 521711), ("API", 521588), ("RPA", 521064), ("LLC", 520280), ("IPA", 520207), ("ADM", 520060), ("GLA", 519295), ("TAP", 519294), ("ABE", 518372), ("ETY", 518266), ("GCO", 517522), ("RMS", 516670), ("LDN", 516405), ("LAM", 515473), ("TAM", 515082), ("YAT", 514887), ("ANP", 513734), ("DLA", 513515), ("IRI", 513467), ("NBU", 513300), ("EMU", 512519), ("NTP", 511651), ("UNS", 510860), ("OLS", 510360), ("DPA", 509809), ("LMO", 509559), ("GUA", 509237), ("IRL", 509126), ("NEF", 508460), ("RBO", 508139), ("PAL", 508003), ("URD", 507800), ("LYH", 507228), ("SCE", 506920), ("ANF", 506607), ("GNI", 506013), ("RIP", 505801), ("URP", 505265), ("IFY", 505167), ("NLE", 504602), ("EPH", 504267), ("EFL", 503910), ("WOO", 503688), ("MMO", 503497), ("IGA", 503497), ("JOH", 502815), ("SRA", 500885), ("ISG", 500728), ("TIR", 499383), ("TTR", 499147), ("THM", 498790), ("YDI", 498661), ("FEL", 498282), ("JOR", 498205), ("DPO", 498043), ("RTR", 497346), ("SUE", 497335), ("YSO", 497210), ("DHO", 497057), ("LPR", 496606), ("RLA", 496560), ("OPT", 496521), ("KSA", 496476), ("CTA", 496458), ("MPT", 496218), ("YHE", 496155), ("DUP", 495800), ("NOL", 495482), ("OSO", 494708), ("HEJ", 494601), ("ALU", 494465), ("GLI", 494378), ("GOA", 494263), ("ITL", 493958), ("CKO", 493446), ("THW", 493160), ("BLY", 493096), ("DSU", 492092), ("HWA", 492002), ("TSB", 491646), ("OFG", 491637), ("RFI", 490437), ("OTR", 490348), ("WNA", 489842), ("OHN", 489451), ("GIO", 488610), ("PUR", 488258), ("MEC", 488180), ("NFL", 487801), ("ZED", 487593), ("ILM", 487242), ("DBU", 486627), ("DUN", 486473), ("OGI", 486249), ("FLI", 486182), ("UCC", 485996), ("NBA", 485692), ("FLE", 485317), ("RAW", 484515), ("EIV", 484190), ("DEB", 484041), ("EOT", 483990), ("UNN", 483956), ("NTM", 483452), ("EVO", 482756), ("MIG", 482184), ("HAI", 482087), ("LDO", 481971), ("OAT", 481479), ("NFA", 481444), ("SSC", 481234), ("LUS", 481140), ("NAF", 480881), ("IWA", 480253), ("EUP", 479710), ("CIP", 478875), ("PAY", 477785), ("CHS", 477768), ("ATF", 477407), ("AMB", 477033), ("ODY", 477028), ("AGI", 476470), ("YME", 476223), ("EXI", 476011), ("TPE", 475755), ("RPE", 475555), ("IMM", 475550), ("LYE", 473623), ("TBU", 473327), ("CTT", 472606), ("LLP", 472117), ("LHA", 471050), ("TDI", 469714), ("ILS", 469685), ("EUR", 469411), ("LBU", 469269), ("TYI", 469136), ("HUN", 468989), ("HIE", 468968), ("GSA", 468704), ("NIF", 468003), ("NKS", 467976), ("WNT", 467949), ("ATB", 467250), ("DDO", 466728), ("GEL", 466030), ("LEP", 465778), ("MSA", 465592), ("ENM", 464945), ("OMS", 464540), ("YWO", 464136), ("RYE", 463932), ("DAP", 463668), ("OSH", 463662), ("HCO", 463355), ("APT", 462589), ("IRM", 462520), ("MAJ", 461996), ("AIT", 461895), ("YFR", 461193), ("OCR", 461087), ("GHO", 460651), ("YLI", 460235), ("TYS", 460071), ("ATD", 459822), ("UPA", 459674), ("FYO", 459119), ("NUN", 457629), ("AFR", 457104), ("AVO", 456873), ("ADB", 456539), ("EIM", 456080), ("USL", 455635), ("TPO", 455600), ("LAD", 454918), ("OWL", 454598), ("HTT", 454342), ("BOD", 452560), ("DWO", 451350), ("FFA", 450974), ("LIZ", 450659), ("OCH", 450499), ("THL", 450466), ("LAU", 450126), ("SCL", 449760), ("ANM", 449470), ("VOT", 449215), ("NPO", 449188), ("VIT", 449115), ("RDT", 448914), ("HTI", 448845), ("DAF", 448676), ("MOF", 447868), ("IEF", 447703), ("FIV", 447519), ("KEL", 446546), ("POT", 446391), ("ISU", 446330), ("OLV", 445680), ("ENP", 444499), ("KEY", 443950), ("RSF", 443639), ("RLO", 443516), ("NCY", 443271), ("RGI", 443210), ("CHN", 442628), ("UNA", 442592), ("ILO", 442392), ("GHS", 442110), ("ODS", 441928), ("ONY", 441676), ("AFO", 441277), ("MEF", 440759), ("OUB", 440554), ("LSI", 440312), ("THP", 438986), ("SNA", 438926), ("LOY", 438888), ("PIR", 438022), ("TLO", 437667), ("HTA", 437321), ("LAG", 437237), ("YCH", 436029), ("DTR", 435315), ("RNS", 433705), ("CEF", 433482), ("HUM", 433377), ("OFN", 432061), ("LEX", 431567), ("SEF", 431541), ("NDY", 431481), ("AMM", 431036), ("GUI", 430959), ("CIL", 430400), ("DPE", 430118), ("VEC", 430041), ("HUS", 429554), ("KST", 429427), ("LLW", 428966), ("SGR", 428953), ("ESR", 427192), ("APH", 426684), ("UIR", 426397), ("AWI", 426367), ("TMI", 425602), ("TSM", 425404), ("OCU", 425294), ("DRU", 424601), ("JUN", 424505), ("TEW", 423945), ("NIZ", 423720), ("OSU", 423505), ("UFF", 423370), ("SIX", 423176), ("QUO", 422520), ("NKE", 422208), ("HHI", 421646), ("DUA", 421396), ("CHH", 421300), ("DYO", 420696), ("EJU", 419736), ("SIL", 419658), ("TOK", 418746), ("IHA", 417951), ("PHE", 417489), ("WNE", 417203), ("GSO", 417000), ("DSP", 416929), ("DLO", 416908), ("NSS", 416724), ("RFR", 416640), ("EEC", 416188), ("HMA", 415887), ("OIT", 415749), ("DAD", 415527), ("IPS", 414820), ("NBO", 413865), ("GOR", 413759), ("LTA", 413363), ("RTT", 413032), ("YNO", 413031), ("EYC", 412553), ("TIG", 412111), ("WNS", 411796), ("DAV", 411464), ("RAY", 411325), ("HHE", 410593), ("NMI", 410259), ("UMP", 410180), ("IZA", 410096), ("NOC", 410088), ("LUT", 409945), ("VEO", 409829), ("TEF", 409679), ("CCU", 409262), ("AIM", 408694), ("KAT", 407784), ("ALG", 407643), ("DSC", 407638), ("OCC", 407246), ("LDW", 407044), ("IDD", 406667), ("JOB", 406296), ("ANR", 406209), ("NLO", 406083), ("FIS", 405748), ("NYT", 405463), ("RYW", 405113), ("FHE", 404856), ("EYH", 404669), ("UPE", 404349), ("DOC", 404332), ("ORU", 403992), ("CTR", 403967), ("ADU", 403942), ("NGG", 403393), ("RSD", 403336), ("OPS", 402840), ("TUS", 400850), ("SYO", 399048), ("MUL", 398994), ("OGO", 398883), ("UPS", 398782), ("ECK", 398780), ("FED", 398375), ("RTM", 397829), ("TEG", 397247), ("CHM", 397193), ("SBY", 397116), ("TGO", 396918), ("UPO", 396823), ("TYL", 396784), ("RBU", 396746), ("PIE", 396745), ("CEC", 396394), ("SUA", 396112), ("LEL", 395855), ("DEE", 395471), ("NBY", 395359), ("REX", 395131), ("UED", 395022), ("LCA", 394284), ("YNE", 394059), ("COO", 393670), ("MEB", 392673), ("REY", 391971), ("LEH", 391646), ("CEB", 391583), ("MBI", 391091), ("NUS", 390708), ("PME", 390639), ("GOL", 390136), ("DIO", 389524), ("LDC", 389481), ("UBS", 389070), ("AIG", 388787), ("LUM", 387836), ("LLF", 387683), ("YLO", 387402), ("IBU", 387254), ("RWO", 387076), ("STD", 387057), ("GNA", 386724), ("OCT", 386543), ("LIB", 386499), ("LME", 386196), ("CAD", 385584), ("SEB", 385353), ("UTU", 385161), ("EBY", 385123), ("ASG", 384462), ("YDO", 384283), ("GLO", 384211), ("MSO", 384157), ("AHO", 383988), ("AYW", 383561), ("NWO", 383031), ("EBL", 382752), ("VIR", 382292), ("RYC", 382277), ("OOF", 380878), ("LSH", 380861), ("DOI", 380766), ("UIS", 380610), ("SOV", 379762), ("HCA", 379609), ("TAD", 379118), ("CKL", 378610), ("LUN", 378324), ("OOP", 378304), ("RVA", 378211), ("GEI", 378023), ("NUT", 377989), ("NTD", 377555), ("GRI", 377456), ("GUL", 377294), ("THB", 376739), ("RTW", 376717), ("RSB", 376667), ("NUA", 376666), ("IAS", 376523), ("UGG", 376254), ("RCI", 375973), ("AWH", 375746), ("EEI", 375366), ("MEP", 375252), ("SFU", 374860), ("HNO", 374502), ("DEX", 374462), ("ABR", 374445), ("POF", 374393), ("GEM", 374097), ("FMA", 373812), ("TUT", 373588), ("SBR", 373166), ("AUL", 373043), ("VEP", 372586), ("AYF", 372221), ("USP", 371906), ("DLY", 371553), ("OPH", 370713), ("KSO", 370672), ("ENL", 370425), ("SMU", 369977), ("ABU", 369302), ("UMM", 369113), ("NPE", 368957), ("SOI", 368954), ("SEH", 368804), ("SPU", 366949), ("XAM", 366885), ("YBU", 366531), ("LFA", 366357), ("YCL", 366299), ("AUN", 365967), ("PHA", 365934), ("MBA", 365409), ("NGN", 365403), ("REU", 365060), ("OBS", 364429), ("OKS", 364346), ("NAU", 364117), ("PHY", 363878), ("WID", 363457), ("ALH", 362984), ("LLM", 362653), ("IPP", 361829), ("ADR", 361643), ("CHC", 361423), ("DAG", 361336), ("BYS", 360804), ("JAN", 360782), ("GAB", 360393), ("USC", 359983), ("NOP", 359527), ("DTE", 358896), ("SOA", 358463), ("AFI", 358302), ("PPI", 357099), ("KIS", 356812), ("BAB", 356115), ("DVA", 355939), ("IMT", 355896), ("DEI", 355784), ("ISK", 355763), ("GMA", 355495), ("EKE", 355493), ("ETC", 355458), ("HLE", 355235), ("LYN", 355124), ("LFI", 354875), ("EWY", 354513), ("THF", 353849), ("GUN", 353734), ("SYE", 353655), ("RGO", 353215), ("RIF", 352976), ("PES", 352844), ("XPL", 352793), ("ATY", 352730), ("THD", 352168), ("NVO", 351927), ("LID", 351823), ("EMT", 351821), ("NEG", 351565), ("TSN", 350759), ("RWE", 350094), ("DFA", 350055), ("SFE", 349142), ("TUP", 348926), ("NOS", 348830), ("AFA", 348636), ("OJE", 348601), ("LOA", 347458), ("YPA", 346821), ("LWI", 346721), ("URB", 346705), ("ARP", 346304), ("BON", 346189), ("RUL", 345376), ("SRO", 345235), ("IBI", 345229), ("DSW", 345079), ("PIO", 344822), ("ARW", 344641), ("UTC", 344629), ("PLY", 344505), ("WYO", 344330), ("APS", 344205), ("EJO", 344137), ("IGU", 343798), ("SLY", 343778), ("DVI", 343518), ("HST", 343510), ("RKA", 343204), ("OUD", 342618), ("ROJ", 342471), ("NAV", 342019), ("ALY", 341781), ("OBI", 341772), ("DDR", 340911), ("HOC", 340786), ("YES", 340781), ("ASY", 340665), ("TAX", 340551), ("ICC", 340144), ("YBO", 339938), ("FUR", 339815), ("PIS", 339326), ("WHY", 339089), ("DGO", 339079), ("RPL", 339054), ("TOV", 338910), ("SSF", 338543), ("OFU", 337960), ("MFO", 337892), ("HOI", 337873), ("IRP", 337376), ("SOO", 337082), ("TYC", 337065), ("IGE", 337045), ("GUS", 336945), ("YPO", 336923), ("LPA", 336790), ("SJU", 336152), ("LYL", 336004), ("NEP", 335826), ("NRO", 335797), ("HOH", 335686), ("DPL", 335317), ("OYO", 335255), ("CCA", 335186), ("TPL", 334561), ("ITM", 334431), ("GOU", 334079), ("EYR", 334066), ("KON", 333905), ("XTE", 333813), ("NSB", 333455), ("GIC", 333418), ("MPU", 333118), ("YLA", 333096), ("IUM", 332924), ("AWE", 332845), ("RYB", 332300), ("FUS", 332254), ("NDJ", 332220), ("NSL", 331844), ("FTO", 331752), ("OKA", 331287), ("ZIN", 330818), ("AHE", 329815), ("UDG", 329388), ("NEB", 329357), ("RUM", 329298), ("DOL", 329249), ("OPM", 328997), ("LLR", 328807), ("ROY", 328345), ("ITR", 328294), ("RBI", 327852), ("KEI", 327742), ("TBY", 327544), ("LUB", 327484), ("IPL", 327390), ("OIL", 326212), ("USU", 325863), ("NCT", 325842), ("TAY", 325655), ("YSU", 325578), ("OGY", 325324), ("BAM", 325163), ("YHI", 324144), ("OVA", 324097), ("HAB", 324021), ("UPI", 323850), ("DUE", 323499), ("COP", 323123), ("LPE", 323007), ("EXE", 322986), ("OWW", 322922), ("NYA", 322627), ("AEL", 322410), ("DVE", 322254), ("ESY", 321712), ("DUL", 321577), ("JOI", 321531), ("YSC", 321466), ("OEN", 321088), ("IMO", 320360), ("CRU", 320228), ("YGO", 319863), ("RUG", 318979), ("UIN", 318748), ("RCU", 318585), ("TYW", 318459), ("VEW", 318401), ("BRU", 317853), ("HHA", 317828), ("SVI", 317083), ("PEE", 317031), ("FST", 317005), ("DBO", 316943), ("ANL", 316876), ("VEF", 316855), ("NTG", 316648), ("NSM", 316461), ("VEG", 315733), ("JAC", 315364), ("TSL", 315058), ("LAP", 314766), ("SOB", 314719), ("THY", 314538), ("OHO", 314489), ("GPR", 314480), ("GAG", 314381), ("ATN", 314283), ("RSM", 314118), ("ZAT", 313199), ("EOL", 313168), ("RFE", 313095), ("NPL", 313021), ("MEH", 312972), ("HSC", 312781), ("WEH", 312484), ("IDH", 311963), ("IAA", 311767), ("DTA", 311326), ("NJO", 310885), ("APL", 310686), ("DBR", 310663), ("UTF", 310506), ("ENV", 310126), ("RGR", 309617), ("LTU", 309002), ("HOD", 308808), ("GFR", 308652), ("LLN", 308507), ("NJA", 308491), ("MBL", 308400), ("NBR", 308282), ("COT", 307967), ("DDA", 307511), ("YSP", 307366), ("ICR", 307300), ("ISY", 306799), ("NEU", 306674), ("ADC", 306514), ("ENY", 306371), ("OBO", 306146), ("RSQ", 306075), ("GNO", 305873), ("SOD", 305129), ("EYD", 305062), ("SSW", 304755), ("TEH", 304729), ("GSI", 304696), ("LHE", 304666), ("DAU", 304300), ("FWH", 304092), ("ETB", 303860), ("OMH", 303544), ("VAI", 303342), ("EYT", 303192), ("LLD", 302766), ("NAI", 301670), ("AUD", 301476), ("LIP", 301243), ("YFI", 300564), ("OMY", 300207), ("WRO", 300070), ("HFO", 299776), ("RSL", 299286), ("IDG", 299282), ("EAW", 299137), ("LSC", 298755), ("NAW", 298217), ("IRF", 298108), ("YAC", 297843), ("ERK", 297785), ("YIT", 297525), ("AYN", 297164), ("TGE", 297116), ("OGA", 296965), ("YBA", 296299), ("DGR", 296067), ("ONJ", 295928), ("RYF", 295660), ("RYP", 295319), ("EMY", 295298), ("XIS", 294694), ("HME", 294429), ("TSR", 294313), ("UAN", 293591), ("ITB", 293583), ("PST", 293548), ("NYS", 293539), ("LCH", 293157), ("BAD", 293108), ("SOS", 293015), ("BOY", 292956), ("OOS", 292825), ("VOR", 292820), ("OIC", 292597), ("UEL", 292256), ("AHI", 292159), ("TFA", 292153), ("EWR", 291913), ("OBU", 291789), ("ELV", 291536), ("EOV", 291259), ("TBO", 291234), ("FLU", 291098), ("CEH", 291090), ("SSM", 290807), ("DJU", 290414), ("RIZ", 290402), ("IFO", 289814), ("TAU", 289720), ("AYH", 289506), ("CEE", 289418), ("URF", 289273), ("WAI", 289155), ("UTM", 289130), ("USO", 288822), ("XTR", 288666), ("STG", 288666), ("URV", 288661), ("SVE", 288521), ("BUL", 287914), ("TSD", 287665), ("ACL", 287469), ("YHO", 287396), ("EEF", 287187), ("MOC", 287054), ("TDA", 286603), ("IPT", 286572), ("LTS", 286321), ("PAP", 284893), ("GIR", 284771), ("USB", 284688), ("VEY", 284533), ("UIC", 284426), ("EKN", 284370), ("YET", 284330), ("PSA", 284082), ("LBA", 283530), ("RGU", 282842), ("FSE", 282634), ("IOD", 282405), ("OWD", 282283), ("WEB", 282010), ("DAI", 281828), ("DIM", 281776), ("SAU", 281513), ("YAF", 281302), ("AZI", 281187), ("IGG", 281173), ("NOO", 280974), ("ITF", 280560), ("TGA", 280550), ("ULI", 280359), ("LTR", 280346), ("OSC", 280260), ("LNE", 280039), ("CHD", 279920), ("XCE", 279816), ("OUA", 279342), ("EAI", 279158), ("STN", 278971), ("IOL", 278483), ("GWA", 277998), ("RCR", 277499), ("GUR", 277443), ("UTR", 277311), ("LAL", 277203), ("EKS", 276998), ("AYM", 276981), ("SOH", 276953), ("LLU", 276854), ("JUL", 276623), ("IQU", 276530), ("WEW", 276386), ("LSW", 276091), ("UTB", 276041), ("KNE", 276009), ("SHU", 275923), ("VOI", 275833), ("TEB", 274945), ("PEL", 274923), ("ULY", 274628), ("KID", 274097), ("BSE", 273916), ("IAR", 273805), ("HBO", 273651), ("LPO", 273428), ("RBR", 272831), ("HMO", 272791), ("FFT", 272515), ("DDL", 272182), ("DQU", 272172), ("HWE", 272150), ("WST", 272060), ("YTR", 271806), ("YUN", 271491), ("OMU", 271377), ("HSO", 271257), ("PTA", 270021), ("SRI", 269829), ("OYA", 269772), ("SUI", 269713), ("SGE", 269245), ("UTP", 269105), ("YFA", 268856), ("RCL", 268514), ("GSE", 268343), ("ADL", 268330), ("SEY", 267942), ("UGE", 267916), ("KFO", 267848), ("RYD", 267813), ("RDW", 267516), ("POO", 267243), ("JUR", 267186), ("GWH", 267185), ("RFU", 266684), ("PUS", 266537), ("RNT", 266513), ("ITD", 266115), ("ATG", 265245), ("LAK", 265236), ("FTI", 265217), ("DOP", 265121), ("LYG", 264718), ("ESK", 264414), ("FPR", 264266), ("PWI", 264056), ("LWH", 263688), ("UPL", 263672), ("DOO", 263489), ("FCA", 263272), ("AWO", 263178), ("ICP", 263016), ("TFE", 262964), ("NDV", 262854), ("ARF", 262794), ("GCA", 262657), ("EID", 262584), ("ERJ", 262492), ("ONU", 262427), ("EHU", 262020), ("NKA", 261521), ("GEW", 261388), ("YMI", 261320), ("PIL", 261319), ("CUM", 261213), ("EDY", 261164), ("UGU", 261043), ("VEE", 261040), ("NRA", 260993), ("MYS", 260722), ("RMY", 260646), ("IRR", 260596), ("TGR", 260419), ("RUP", 260209), ("KEP", 260176), ("GMO", 260114), ("GUP", 259773), ("CUP", 259565), ("LDM", 259515), ("HSA", 259121), ("CTL", 258977), ("NDK", 258269), ("FSO", 258205), ("OUW", 258170), ("TBR", 258131), ("KEO", 257910), ("KAR", 257726), ("UTL", 257310), ("SDU", 257297), ("OEX", 257208), ("IMB", 256721), ("GBE", 256536), ("OBR", 256513), ("NYE", 255818), ("TTW", 255574), ("EWT", 255572), ("FFS", 255550), ("HWI", 255283), ("NEH", 255086), ("CHB", 254914), ("LKI", 254862), ("GEF", 254737), ("FAV", 254328), ("OID", 254034), ("RDR", 253403), ("GME", 253214), ("YDA", 252594), ("SGA", 252355), ("GAC", 252154), ("AMT", 252041), ("GIA", 252012), ("GHL", 251155), ("RYL", 251008), ("KHA", 250943), ("JAM", 250714), ("BIR", 250662), ("DOV", 250600), ("HTW", 250522), ("HAW", 250437), ("MWI", 250297), ("NOI", 250208), ("CHF", 250098), ("AUR", 249822), ("GBA", 249427), ("FET", 249306), ("BJE", 249274), ("FUT", 249248), ("LLG", 249160), ("OTW", 248831), ("KIT", 248806), ("ENJ", 248187), ("GSH", 248150), ("THN", 248005), ("WIF", 247579), ("LOB", 247579), ("WEI", 247400), ("ESG", 246681), ("FDE", 246592), ("BLU", 246464), ("GAV", 246450), ("HYS", 246071), ("CKW", 245924), ("FPE", 245873), ("CHP", 245854), ("KLE", 245734), ("AMU", 245633), ("ZON", 245547), ("NGY", 245381), ("LLL", 245335), ("SHT", 245041), ("SEQ", 244968), ("BYC", 244847), ("JUD", 244815), ("GOD", 244706), ("TYF", 244703), ("RAH", 244695), ("GUY", 244642), ("WTO", 244506), ("DNA", 244453), ("NKT", 244245), ("UHA", 243995), ("DAW", 243266), ("SDR", 243212), ("BYM", 243015), ("YTE", 243002), ("BEP", 242939), ("RBY", 242612), ("UTD", 242568), ("NVA", 241966), ("OLY", 241541), ("FTW", 241075), ("NOB", 240992), ("RYM", 240814), ("GDO", 240711), ("LFR", 240415), ("ACU", 240201), ("DEG", 240171), ("OLT", 239835), ("CIF", 239717), ("TTY", 239662), ("PAG", 239569), ("DTW", 239446), ("FCH", 239150), ("BYH", 239017), ("VIA", 238968), ("LPH", 237968), ("YAB", 237435), ("GAP", 237432), ("BYP", 236865), ("OTC", 236708), ("PSE", 236487), ("MCO", 236416), ("HPR", 236389), ("SSS", 236179), ("HOA", 236067), ("TCL", 235854), ("ZEN", 235828), ("OWM", 235748), ("DCR", 235679), ("POU", 235668), ("HAC", 235574), ("BUY", 235001), ("HSE", 234835), ("RTF", 234685), ("NYW", 234398), ("OAP", 234371), ("SHM", 234253), ("BUM", 233913), ("UMS", 233829), ("ALV", 233703), ("CHL", 233681), ("EJA", 233336), ("TJU", 232540), ("WLE", 232110), ("IEC", 231942), ("DCL", 231737), ("DGA", 231566), ("LYU", 231380), ("ABS", 231314), ("OMF", 231275), ("NRI", 231210), ("RYH", 231178), ("BOW", 230929), ("YRA", 230711), ("OFJ", 230703), ("BST", 230645), ("UMI", 230385), ("YEN", 230026), ("ROK", 229807), ("MUR", 229737), ("GLY", 229733), ("MWA", 229644), ("WOF", 229452), ("SIF", 229352), ("RUI", 229226), ("YRO", 228773), ("IMU", 228239), ("IAG", 228212), ("LBO", 228136), ("LSU", 228120), ("LSP", 228078), ("MPS", 227450), ("GEC", 227243), ("FMO", 227041), ("ELC", 226793), ("MSI", 226515), ("SBI", 226270), ("HNI", 226202), ("UNL", 226124), ("YEX", 226019), ("UTY", 225436), ("SEU", 225190), ("UTN", 225070), ("OUH", 224962), ("LNO", 224905), ("HTB", 224853), ("LMI", 224848), ("ALN", 224778), ("OFV", 224337), ("IDU", 224333), ("SKA", 224227), ("BUD", 224160), ("SUG", 224122), ("MWH", 223934), ("EEW", 223814), ("ODR", 223685), ("THG", 223518), ("KSH", 223308), ("LDL", 223283), ("RTL", 223254), ("WRE", 222992), ("TKN", 222776), ("PSO", 222714), ("ACY", 222507), ("BSI", 222431), ("GDE", 222394), ("IAB", 222393), ("DIG", 222195), ("YPL", 221849), ("OYS", 221739), ("AKA", 221395), ("FOC", 221239), ("LGA", 220781), ("GHB", 220528), ("ADW", 220528), ("RKO", 220424), ("LDP", 220259), ("DSF", 220157), ("INY", 219786), ("UPW", 219591), ("EKA", 219542), ("OMC", 219469), ("KSI", 218880), ("FEB", 218669), ("SSL", 218313), ("CAB", 218110), ("LHI", 217840), ("ISV", 217574), ("HEQ", 217500), ("SEG", 217349), ("LTY", 217317), ("ILW", 217293), ("FFR", 217147), ("HCE", 217107), ("MBO", 217032), ("NNY", 215903), ("WNI", 215140), ("HWH", 214995), ("OXI", 214978), ("AOF", 214937), ("MIR", 214811), ("FOF", 214779), ("LGO", 214723), ("NYM", 214279), ("CIR", 213813), ("SRU", 213789), ("WEC", 213677), ("UNK", 213577), ("RSR", 213051), ("LKE", 212737), ("WSA", 212347), ("AYL", 212048), ("GPO", 211951), ("YBR", 211535), ("HLI", 211287), ("GEB", 211108), ("MOM", 211091), ("YNA", 210655), ("EDV", 210626), ("SAH", 210565), ("AWS", 210533), ("EYB", 210530), ("DEW", 210139), ("WIC", 209942), ("LHO", 209628), ("KEM", 209202), ("FMI", 209156), ("LDF", 208960), ("YAP", 208948), ("TAW", 208892), ("CTH", 208712), ("RGY", 208543), ("DTI", 208435), ("GTE", 208390), ("VIV", 208012), ("YPI", 207841), ("ARV", 207752), ("IPE", 207514), ("YTA", 207326), ("KLY", 207292), ("KWI", 207252), ("LAV", 207223), ("UMO", 207140), ("OFY", 207083), ("RMU", 207044), ("PUN", 207039), ("EYM", 206987), ("LUC", 206952), ("OTL", 206887), ("FTA", 206663), ("TNA", 206516), ("NYC", 206153), ("MNO", 206067), ("TSG", 205658), ("CYC", 205614), ("OLF", 205584), ("FWA", 205580), ("PSI", 205430), ("BOL", 205326), ("DDU", 205131), ("DPU", 205128), ("DSL", 205059), ("ADN", 204851), ("SIZ", 204694), ("DJO", 204562), ("LWO", 204244), ("VAS", 204100), ("BIS", 203990), ("JAP", 203934), ("BEM", 203822), ("NQU", 203329), ("GBU", 203154), ("YRI", 203083), ("DFE", 203075), ("HAF", 202767), ("EPS", 202630), ("NYP", 202609), ("SIE", 202387), ("TUE", 202366), ("ELM", 202285), ("NNU", 202225), ("NPU", 202224), ("DOS", 202027), ("FON", 201918), ("AMW", 201893), ("DYE", 201834), ("TIP", 201622), ("ARH", 201528), ("WNO", 201509), ("FPO", 201357), ("SUF", 201316), ("TTS", 201257), ("XPA", 201004), ("KWA", 200810), ("AGG", 200713), ("LVI", 200690), ("TOY", 200489), ("NAH", 200489), ("MHA", 200203), ("MBU", 200042), ("DMU", 199711), ("HAE", 199517), ("OCL", 199388), ("DOG", 199375), ("MEG", 199264), ("BOX", 199091), ("USW", 198656), ("EIL", 198544), ("RIK", 198136), ("LSS", 198081), ("DSS", 197478), ("BIA", 197139), ("RUE", 197067), ("CKB", 197059), ("PLU", 196990), ("YAD", 196878), ("EWC", 196641), ("ARU", 196561), ("REJ", 196504), ("BOS", 196426), ("UEA", 196332), ("NSD", 196053), ("RJO", 195953), ("PPA", 195904), ("HLA", 195713), ("EYF", 195528), ("NFU", 195436), ("MOO", 195051), ("HBE", 195045), ("HRA", 194991), ("DSM", 194977), ("OMW", 194924), ("CSA", 194893), ("FPA", 194484), ("IDW", 194128), ("FSA", 194087), ("GAD", 193657), ("YSS", 193566), ("EWM", 193479), ("MPH", 193405), ("TOJ", 192842), ("OFK", 192840), ("ZER", 192775), ("AYC", 192745), ("YGR", 192720), ("KAB", 192594), ("RTN", 192530), ("TCR", 192477), ("YGE", 192111), ("OWC", 192102), ("MHE", 192025), ("TVI", 192022), ("YUS", 191888), ("YSW", 191808), ("SGI", 191544), ("UDO", 191464), ("IGR", 191355), ("TYB", 191312), ("TPU", 191282), ("EJE", 190300), ("RDF", 190255), ("ODT", 190139), ("GPA", 190091), ("RUT", 189839), ("XEC", 189687), ("KAS", 189673), ("IFA", 189660), ("URM", 189395), ("YAM", 189214), ("OWB", 189084), ("LRO", 188660), ("RDL", 188549), ("ROI", 188517), ("KEH", 188499), ("YOT", 188472), ("FLY", 188436), ("YTI", 188406), ("YBY", 188299), ("ADH", 188275), ("IWO", 188048), ("LPL", 188038), ("URL", 187946), ("IBR", 187812), ("DAH", 187633), ("CTW", 187621), ("EIF", 187616), ("CIO", 187473), ("IOS", 187321), ("OTP", 187172), ("RYR", 186859), ("FEM", 186823), ("MAP", 186542), ("HLY", 186536), ("TYH", 186496), ("IOT", 186413), ("UID", 186129), ("UAG", 185667), ("ICY", 185550), ("UNF", 185532), ("RAU", 185495), ("LWE", 185384), ("NKO", 185271), ("LDG", 185152), ("EAH", 185145), ("MSW", 184607), ("MIE", 184573), ("EYI", 184244), ("HUG", 183952), ("USF", 183723), ("TMU", 183374), ("SIR", 183184), ("HSI", 183026), ("FBE", 182965), ("RAE", 182811), ("GYO", 182742), ("MCC", 182712), ("HSH", 182243), ("DYA", 181839), ("FME", 181826), ("JOY", 181756), ("YDR", 181716), ("WSO", 181553), ("PAU", 181387), ("NSR", 180805), ("CAI", 180695), ("GPE", 180678), ("JER", 180657), ("JOU", 180589), ("CIV", 180537), ("IRB", 180492), ("FAB", 180274), ("NCU", 180124), ("GEP", 180111), ("YMP", 180085), ("HIO", 180085), ("EEO", 179594), ("OBB", 179537), ("OWR", 179509), ("FTR", 179504), ("POK", 179205), ("ETF", 179028), ("RKT", 178894), ("UDY", 178815), ("FHO", 178744), ("DCU", 178646), ("KOR", 178633), ("YAG", 178599), ("ABB", 178472), ("ETM", 178339), ("FNE", 177841), ("ELB", 177808), ("HDO", 177712), ("SKN", 177621), ("TYM", 177611), ("AQU", 177486), ("OTM", 177474), ("NYI", 177423), ("IRW", 177394), ("MSH", 177299), ("RRU", 177022), ("GCH", 176885), ("LSF", 176733), ("SPH", 176397), ("WWH", 176123), ("KSW", 175981), ("FNO", 175791), ("MBR", 175511), ("SJO", 175484), ("YEL", 175455), ("UDD", 175203), ("NTN", 175108), ("ODD", 174850), ("GOE", 174842), ("BEO", 174805), ("CKH", 174641), ("HTR", 174591), ("ITN", 174548), ("COG", 174521), ("UER", 174478), ("NAA", 174477), ("OGN", 174298), ("HNS", 174036), ("HAU", 173969), ("IRG", 173962), ("EYL", 173949), ("MRE", 173881), ("BAY", 173738), ("COF", 173615), ("JON", 173421), ("BYR", 173044), ("ADF", 173008), ("PTU", 172994), ("KIE", 172928), ("HIA", 172754), ("FSU", 172710), ("GSW", 172369), ("IXT", 172138), ("TYR", 172065), ("YNI", 172024), ("DGI", 171807), ("GGL", 171783), ("OUI", 171739), ("OKN", 171674), ("HDE", 171657), ("ICF", 171582), ("MCA", 171408), ("NUP", 170928), ("HPO", 170892), ("LDD", 170860), ("COD", 170737), ("AVY", 170431), ("GSU", 170294), ("DEH", 170239), ("ICD", 170195), ("WNF", 170102), ("UOS", 170075), ("OTF", 170001), ("WMA", 169956), ("EOB", 169901), ("LTT", 169726), ("YFE", 169571), ("FAP", 169486), ("BYB", 169169), ("NGV", 169056), ("PFO", 168941), ("HPA", 168888), ("ULS", 168342), ("CKF", 168254), ("MHI", 168246), ("ULO", 168208), ("FWE", 168167), ("OTU", 167850), ("HAG", 167622), ("PTT", 167606), ("WCO", 167594), ("CST", 167463), ("EMW", 167434), ("GGR", 167415), ("AGN", 167094), ("DYS", 165978), ("IPO", 165799), ("EDJ", 165759), ("ELU", 165749), ("KLA", 165704), ("IPI", 165658), ("CKY", 165439), ("HOE", 165299), ("BBE", 165252), ("RDC", 164992), ("YSL", 164727), ("WOS", 164527), ("OKO", 164335), ("NMY", 164074), ("ADP", 163657), ("FHA", 163642), ("TIZ", 163486), ("EYP", 163351), ("GHW", 163026), ("HYO", 162976), ("EBS", 162931), ("FSH", 162858), ("LGR", 162856), ("TJO", 162389), ("UGA", 162255), ("SSR", 162194), ("YEV", 162059), ("GFI", 161935), ("IAI", 161830), ("USM", 161800), ("OKT", 161711), ("REK", 161614), ("TFU", 161461), ("NGJ", 161449), ("RDU", 161403), ("KEW", 161231), ("GGI", 161127), ("EGL", 161122), ("AON", 161095), ("BIO", 161026), ("SHR", 161021), ("GDI", 160987), ("OEA", 160887), ("DKI", 160541), ("HMI", 160369), ("LKS", 160309), ("BOV", 160148), ("KMA", 160088), ("XIN", 160067), ("ASV", 159996), ("GSC", 159854), ("YSB", 159719), ("UCI", 159715), ("RUA", 159703), ("TID", 159674), ("SHS", 159572), ("ICB", 159480), ("XAN", 159457), ("RKW", 159366), ("ONK", 159249), ("EEH", 159196), ("IAC", 159157), ("LVA", 158941), ("DFU", 158895), ("BSO", 158841), ("ANJ", 158737), ("DJA", 158663), ("IDL", 158623), ("LPI", 158558), ("EWP", 158538), ("AFU", 158254), ("EWW", 158111), ("FIF", 158033), ("NMU", 158022), ("HNE", 157525), ("TNI", 157470), ("GWE", 157447), ("UPF", 157388), ("NSY", 157342), ("KOU", 157335), ("BYD", 157098), ("CCI", 157054), ("YSM", 156909), ("YMU", 156566), ("ETP", 156272), ("YCR", 156031), ("YYE", 155847), ("IUS", 155825), ("TAH", 155773), ("LOM", 155590), ("JOS", 155303), ("GWO", 155103), ("SYM", 154924), ("AHU", 154855), ("RLS", 154844), ("AYP", 154833), ("FDI", 154792), ("AAR", 154699), ("FID", 154324), ("GTR", 154184), ("CQU", 154146), ("RDP", 154011), ("BEB", 153621), ("PTS", 153520), ("PID", 153227), ("MEX", 153126), ("COC", 153009), ("FWI", 152954), ("MYO", 152951), ("USD", 152944), ("DIU", 152872), ("KEC", 152843), ("SKY", 152821), ("GTI", 152789), ("FRU", 152694), ("HTF", 152651), ("KUP", 152647), ("XIM", 152592), ("HDI", 152517), ("ELW", 152333), ("KAL", 151884), ("IRH", 151803), ("BYF", 151750), ("OAM", 151691), ("HIB", 151679), ("KIC", 151608), ("RDB", 151492), ("HTL", 151425), ("TQU", 151291), ("OTG", 151172), ("EUT", 151050), ("FTT", 150694), ("UBE", 150528), ("BUN", 150470), ("ISJ", 150411), ("NIQ", 150392), ("IGO", 150176), ("ICM", 150171), ("BYI", 149834), ("UEO", 149755), ("DYI", 149614), ("SHC", 149518), ("SSB", 149468), ("TKI", 149365), ("XPO", 148925), ("DSB", 148849), ("XPR", 148810), ("MOB", 148805), ("WYE", 148589), ("NRU", 148404), ("VAC", 148352), ("NTK", 148351), ("WSP", 148320), ("GAZ", 148075), ("KCO", 147990), ("TCE", 147806), ("DYT", 147765), ("LAH", 147666), ("ITP", 147607), ("GNS", 147289), ("GHH", 147206), ("BEY", 147195), ("TDR", 147017), ("LFT", 146844), ("AKS", 146792), ("HCH", 146708), ("HDA", 146702), ("NGK", 146534), ("GEH", 146527), ("EWB", 146388), ("UPR", 146371), ("FBA", 146370), ("GSP", 146311), ("BEU", 146202), ("DBL", 146187), ("SBL", 146064), ("FTS", 146020), ("TUM", 145985), ("LUR", 145936), ("RQU", 145917), ("AWN", 145846), ("EUM", 145792), ("DBI", 145762), ("MYA", 145673), ("ICW", 145538), ("CKN", 145517), ("DIL", 145429), ("GOS", 145295), ("DUT", 145257), ("GIL", 145217), ("APU", 145093), ("DPI", 145082), ("DOA", 145014), ("RHU", 144806), ("URH", 144780), ("FAD", 144700), ("CAG", 144283), ("RTB", 144245), ("ORV", 144036), ("GBO", 143954), ("MAM", 143952), ("COW", 143941), ("MOL", 143888), ("GAF", 143861), ("AXI", 143785), ("RAZ", 143518), ("MIK", 143510), ("DVO", 143466), ("DFL", 142818), ("ATK", 142816), ("LGE", 142806), ("MSU", 142720), ("PCO", 142708), ("KWH", 142708), ("RPH", 142706), ("NOA", 142664), ("EOC", 142653), ("FAU", 142374), ("UAD", 142268), ("ASJ", 142170), ("SGU", 142130), ("ABY", 141892), ("FGO", 141869), ("ENK", 141742), ("HTN", 141511), ("RPU", 141501), ("BAI", 141478), ("XIC", 141462), ("RTC", 141366), ("HUT", 141366), ("MAH", 141298), ("EEY", 140791), ("SSY", 140649), ("CKM", 140581), ("RSN", 140406), ("IDB", 140359), ("YIM", 140231), ("BYE", 140228), ("LFE", 140186), ("OIM", 140132), ("VOC", 140123), ("SFL", 140034), ("OML", 139960), ("KLI", 139852), ("LEU", 139763), ("ACQ", 139721), ("HID", 139637), ("BAG", 139509), ("SWR", 139465), ("UNO", 139430), ("MAB", 138898), ("BYL", 138771), ("UVE", 138649), ("FEI", 138607), ("YGA", 138419), ("UEE", 138419), ("YVE", 138396), ("HWO", 138226), ("XAS", 138087), ("HLO", 137894), ("MSC", 137826), ("JEW", 137725), ("MIX", 137684), ("NYB", 137594), ("PPY", 137425), ("IKI", 137401), ("IDF", 137372), ("ORJ", 137319), ("UYS", 137312), ("UEI", 137214), ("VEU", 137092), ("CKC", 137047), ("MFR", 136773), ("WNW", 136707), ("PAB", 136680), ("ADJ", 136636), ("RPI", 136396), ("HBA", 136295), ("TEU", 136106), ("UBT", 136103), ("GIE", 136027), ("YYO", 135914), ("CKP", 135826), ("OWF", 135574), ("YPU", 135336), ("LKA", 135295), ("AMC", 135204), ("NIR", 135029), ("IAW", 134933), ("WSH", 134405), ("WOL", 134326), ("OTD", 134175), ("FWO", 134023), ("KAG", 133949), ("IXE", 133863), ("LMS", 133840), ("NKN", 133715), ("RYG", 133713), ("UKE", 133668), ("TBI", 133304), ("EAO", 133150), ("LSB", 133139), ("UBA", 133075), ("YEE", 132994), ("ODF", 132823), ("AYD", 132650), ("BYW", 132633), ("XES", 132160), ("AYR", 132146), ("IPH", 132080), ("MIA", 132009), ("PSH", 131913), ("AGL", 131673), ("KHE", 131667), ("GGA", 131540), ("BEW", 131458), ("GEE", 131265), ("NOD", 131230), ("AAS", 131090), ("LAF", 131060), ("OGU", 131006), ("URK", 130873), ("GPL", 130660), ("ZES", 130527), ("EDK", 130484), ("DOY", 130393), ("STV", 130379), ("IFH", 130085), ("FFL", 129983), ("ODW", 129981), ("FIX", 129823), ("RDM", 129627), ("LDU", 129304), ("WOT", 129101), ("HGR", 129096), ("TPM", 129038), ("MEU", 128800), ("OUM", 128744), ("RAA", 128254), ("YJU", 128173), ("HFR", 128110), ("MYF", 128036), ("EWL", 128024), ("GYA", 127994), ("FSI", 127917), ("OAB", 127872), ("SNI", 127867), ("XTH", 127741), ("HBU", 127696), ("WNB", 127547), ("UBJ", 127497), ("IDM", 127288), ("NID", 127087), ("WCA", 126951), ("USR", 126889), ("BOM", 126767), ("OAF", 126628), ("OEV", 126410), ("XED", 126389), ("MYT", 126335), ("OBJ", 126133), ("HSP", 125998), ("URW", 125966), ("WOY", 125944), ("KRE", 125817), ("NBI", 125697), ("ULF", 125637), ("HPE", 125561), ("GEV", 125528), ("JUM", 125214), ("UOT", 125164), ("EMC", 125151), ("HTC", 125115), ("EYG", 125040), ("TPI", 125007), ("UMN", 124988), ("SHW", 124955), ("RMT", 124796), ("TVE", 124739), ("EPP", 124641), ("TSY", 124633), ("RDH", 124615), ("NSN", 124609), ("EGY", 124543), ("TDU", 124494), ("ZET", 124389), ("ETL", 124374), ("GIM", 124363), ("KYO", 124357), ("FBO", 124348), ("SVA", 124321), ("FSP", 124123), ("IDC", 124039), ("RSY", 123873), ("IEA", 123683), ("EOW", 123601), ("JIM", 123600), ("BYO", 123318), ("GFA", 123218), ("MSS", 123090), ("YVI", 122830), ("OMD", 122824), ("HHO", 122818), ("UBB", 122777), ("OLK", 122529), ("NUR", 122385), ("YCE", 122277), ("TVA", 122237), ("AFL", 122054), ("BID", 121751), ("DCE", 121671), ("PMA", 121628), ("TAV", 121453), ("WOW", 121376), ("YSF", 121301), ("IBA", 121101), ("ROX", 121097), ("OGS", 121096), ("OOU", 121058), ("HSU", 121039), ("HYD", 120950), ("ZAR", 120914), ("OMN", 120865), ("ODG", 120862), ("YKN", 120824), ("OMR", 120778), ("FBU", 120713), ("RSG", 120557), ("FEX", 120530), ("UFA", 120461), ("CKU", 120423), ("NIL", 120363), ("TYD", 120358), ("HYA", 120326), ("CAA", 120173), ("PBE", 120105), ("LRA", 120084), ("DOB", 120044), ("ZEA", 119992), ("LCL", 119732), ("UWA", 119588), ("JOE", 119400), ("GHP", 119378), ("WET", 119239), ("AZA", 119155), ("BUC", 119123), ("YOP", 119106), ("AMH", 118967), ("WNP", 118962), ("BOB", 118938), ("LRI", 118907), ("AKO", 118901), ("HAK", 118889), ("HOB", 118829), ("IPM", 118734), ("OWP", 118647), ("EEU", 118553), ("HEX", 118526), ("HFI", 118367), ("AUC", 118337), ("WOP", 118307), ("NYD", 117859), ("DKE", 117810), ("FSC", 117684), ("FAG", 117423), ("LBR", 117347), ("ILH", 117298), ("RAK", 117227), ("WWE", 117216), ("EWF", 117172), ("SKS", 117157), ("EEB", 117123), ("PAD", 117096), ("MAX", 117030), ("PSW", 116968), ("IZI", 116858), ("KSF", 116849), ("GOP", 116816), ("RNC", 116768), ("DGU", 116736), ("PSY", 116727), ("UIP", 116709), ("EGG", 116664), ("TGI", 116498), ("OQU", 116245), ("NTV", 116095), ("DEU", 116084), ("RAQ", 116025), ("AXE", 116000), ("KRA", 115958), ("MAA", 115722), ("IIN", 115566), ("FGR", 115520), ("DHU", 115459), ("NPI", 115454), ("EXH", 115445), ("OSL", 115387), ("CAC", 115300), ("RJU", 115298), ("FBR", 115222), ("IPW", 115106), ("ADG", 115073), ("EAA", 115041), ("IEG", 114958), ("IVO", 114895), ("MLI", 114828), ("ITZ", 114780), ("CHY", 114736), ("OSW", 114685), ("RKC", 114626), ("EYN", 114594), ("XAC", 114568), ("CAV", 114430), ("KNI", 114309), ("YJO", 114271), ("OSM", 114249), ("WAG", 114218), ("MDE", 114058), ("MYC", 113916), ("RVO", 113667), ("YDU", 113638), ("ETN", 113504), ("IZO", 113493), ("ESV", 113484), ("EWD", 113375), ("NBL", 113347), ("MNE", 113319), ("LLK", 113289), ("WSI", 112649), ("GAW", 112421), ("SYN", 112290), ("WNC", 112270), ("YOV", 112238), ("KEF", 112235), ("TFL", 112193), ("MWE", 112129), ("GOB", 111965), ("IWI", 111849), ("SHL", 111816), ("TUC", 111801), ("CTF", 111738), ("SSD", 111637), ("GMI", 111327), ("TTU", 111318), ("EIC", 111259), ("NNS", 111211), ("SHF", 111087), ("DMY", 111004), ("HYT", 110979), ("MUT", 110964), ("TGU", 110935), ("MSF", 110911), ("HPL", 110849), ("UPH", 110821), ("RFL", 110630), ("MDA", 110570), ("HIF", 110564), ("NSK", 110477), ("AZE", 110426), ("WDE", 110320), ("DNI", 110320), ("FDO", 110269), ("KBE", 110054), ("IDR", 110047), ("LCR", 109995), ("IMW", 109991), ("MMY", 109956), ("RBL", 109692), ("NKL", 109626), ("MSP", 109609), ("IKN", 109500), ("CYA", 109497), ("GRU", 109482), ("KEB", 109472), ("CKD", 109421), ("NUF", 109343), ("OVO", 109328), ("WFO", 109235), ("TMY", 109044), ("ELH", 109015), ("WAV", 108969), ("ODC", 108862), ("SVO", 108777), ("XCH", 108776), ("LSM", 108724), ("CSO", 108718), ("ILB", 108710), ("KEV", 108693), ("DTU", 108525), ("BYG", 108479), ("EMM", 108453), ("MUM", 108426), ("TCU", 108386), ("IIS", 108367), ("HTM", 108276), ("OJO", 108187), ("RTP", 107970), ("WSE", 107778), ("GDA", 107757), ("OEM", 107672), ("POE", 107631), ("MEV", 107458), ("UCO", 107448), ("SHB", 107393), ("TIB", 107290), ("DYW", 107276), ("TBL", 107270), ("BYN", 107053), ("GOW", 107041), ("AAT", 106995), ("KSE", 106946), ("GBY", 106945), ("NYF", 106839), ("ATV", 106765), ("OUV", 106634), ("IAH", 106516), ("RTG", 106473), ("BBI", 106251), ("COI", 106225), ("OLB", 106072), ("UPB", 106063), ("NYR", 106030), ("VOU", 105980), ("FAF", 105908), ("FUE", 105736), ("THK", 105680), ("ZAN", 105649), ("OKL", 105497), ("NYH", 105339), ("OGL", 105036), ("UTG", 104986), ("RYN", 104984), ("BSA", 104948), ("AWT", 104849), ("WOC", 104848), ("TAA", 104840), ("NHU", 104731), ("UEB", 104550), ("OUK", 104512), ("LYK", 104364), ("KSS", 104310), ("CPR", 104269), ("CSC", 104080), ("GEX", 103997), ("MLE", 103920), ("CTC", 103908), ("GGO", 103881), ("OAV", 103880), ("RDD", 103809), ("KHO", 103755), ("BVI", 103722), ("IDP", 103589), ("SYC", 103563), ("HOV", 103555), ("RKN", 103514), ("SAK", 103482), ("ODB", 103350), ("COH", 103271), ("ANV", 103258), ("FDA", 103198), ("RUD", 103095), ("EBT", 103045), ("EKO", 102908), ("UPD", 102902), ("STJ", 102886), ("ATJ", 102836), ("AOR", 102836), ("WNH", 102833), ("CHG", 102726), ("ILR", 102677), ("WWI", 102665), ("AAL", 102622), ("LCU", 102603), ("IRN", 102380), ("JES", 102324), ("HNA", 102320), ("MEY", 102237), ("PWA", 102208), ("STK", 102207), ("AMF", 102174), ("OBT", 102146), ("YTW", 102077), ("DCI", 102057), ("ILV", 102013), ("KSC", 101977), ("YBI", 101847), ("RJA", 101772), ("OBV", 101754), ("SHP", 101649), ("EEG", 101565), ("UDA", 101558), ("DAA", 101528), ("KEU", 101470)]
-- The full list has 26^3 = 17576 trigrams: we take 4000.

trigramLLs n = gramCountsToMap $ take n trigramFs
 
trigramProbability :: Gram -> Double
trigramProbability trigram =
    case M.lookup trigram (trigramLLs (26^3)) of Just l -> exp l
                                                 _      -> error "Trigram not in list"

-------------------------------------------------------------------------------
-- Score: score a string (no spaces) using a Haskell map sending some of the 26^m 
-- m-grams to their log-likelihood, by adding log-likelihoods, using b if not present
-- We give special names to some common types so that typing e.g. :info scoreString
-- at the Haskell prompt gives a more informative type signature.

type Gram          = String
type LogLikelihood = Double
type GramMap       = M.Map Gram LogLikelihood

scoreGram :: GramMap -> Double -> Gram -> Double
scoreGram gramMap b gram = case M.lookup gram gramMap of Just ll -> ll
                                                         Nothing -> b

type GramLength    = Int
type Score         = Double

type ScoreFunction = String -> Score

type ScalingFactor = Double

scoreString :: ScalingFactor -> GramMap -> ScoreFunction
scoreString sf gramMap = \string -> sum [scoreGram gramMap b gram | gram <- grams m string]
    where b = (minimum $ M.elems gramMap) * sf
        --if gram not in map, give it log-likelihood minimum of all grams in map * sf
          m = length $ head $ M.keys gramMap

grams :: GramLength -> String -> [Gram]
grams m string | length gram >= m = gram : grams m (tail string)
               | otherwise        = []
    where gram = take m string    

-------------------------------------------------------------------------------
-- Decrypt permutation represented as map

type CiphertextLetter = Char
type PlaintextLetter  = Char

type Plaintext        = String
type Ciphertext       = String

type DecryptBijection = M.Map CiphertextLetter PlaintextLetter

identityMap :: DecryptBijection
identityMap = M.fromList $ (' ', ' ') : [(c, c) | c <- ['a'..'z']]

decrypt :: DecryptBijection -> Ciphertext -> Plaintext
decrypt pMap y = [pMap M.! c | c <- y]
    
-------------------------------------------------------------------------------
-- Nearby decrypt maps obtained by swapping the *decryptions* of two ciphertext letters

swap :: CiphertextLetter -> CiphertextLetter -> DecryptBijection -> DecryptBijection
swap c c' pMap = M.insert c' d $ M.insert c d' $ M.delete c' $ M.delete c pMap
    where d     = pMap M.! c
          d'    = pMap M.! c'

swaps :: DecryptBijection -> [(DecryptBijection, CiphertextLetter, CiphertextLetter)]
swaps pMap = [(swap c c' pMap, c, c') | c <- ['a'..'z'], c' <- [succ c..'z']]
           
steps :: ScoreFunction -> Ciphertext -> DecryptBijection -> 
    [(Score, GuessedPlaintext, DecryptBijection, [CiphertextLetter], [CiphertextLetter])]           
steps scoreDecrypt y pMap = [(scoreDecrypt x, x, pMap', [c], [c']) | (pMap', c, c') <- swaps pMap, let x = decrypt pMap' y]

-- Optionally also allow 'big-steps' where swap two pairs at once

moreSteps :: ScoreFunction -> Ciphertext -> DecryptBijection ->
    [(Score, GuessedPlaintext, DecryptBijection, [CiphertextLetter], [CiphertextLetter])]           
moreSteps scoreDecrypt y pMap = oneSteps ++ 
    [(scoreDecrypt x, x, pMap'', [c, d], [c', d']) 
            | (_, _, pMap', [c], [c']) <- oneSteps,
              (pMap'', d, d') <- swaps pMap',                                                                   
              let x = decrypt pMap'' y]
    where oneSteps = steps scoreDecrypt y pMap               

-------------------------------------------------------------------------------
-- Hill climb with multiple single-swap steps, until none gives an improvement,
-- then optionally try the double-swaps

type TryDoubleSwaps = Bool

stepOnce :: TryDoubleSwaps -> ScoreFunction -> Ciphertext -> DecryptBijection -> Maybe DecryptBijection
stepOnce tryDoubleSwaps scoreDecrypt y pMap | tqs' == [] = Nothing
                                            | otherwise  = Just qMap
    where s            = scoreDecrypt (decrypt pMap y)
          tqs          | tryDoubleSwaps = moreSteps scoreDecrypt y pMap
                       | otherwise      = steps scoreDecrypt y pMap
          tqs'         = [(t, qMap) | (t, _, qMap, _, _) <- tqs, t > s]
          (t, qMap)    = head tqs'

climb :: TryDoubleSwaps -> ScoreFunction -> Ciphertext -> DecryptBijection -> [DecryptBijection]
climb tryDoubleSwaps scoreDecrypt y pMap = 
    case stepOnce tryDoubleSwaps scoreDecrypt y pMap of
        Nothing    -> [pMap]
        Just pMap' -> pMap' : climb tryDoubleSwaps scoreDecrypt y pMap'

type GuessedPlaintext = String

showClimb :: TryDoubleSwaps -> ScoreFunction -> Ciphertext -> DecryptBijection -> [(Score, DecryptBijection, GuessedPlaintext)]
showClimb tryDoubleSwaps scoreDecrypt y pMapStart = 
    [(scoreDecrypt xGuess, pMap, xGuess) | pMap <- climb tryDoubleSwaps scoreDecrypt y pMapStart, let xGuess = decrypt pMap y]

printClimb :: TryDoubleSwaps -> ScoreFunction -> Ciphertext -> DecryptBijection -> IO ()
printClimb tryDoubleSwaps scoreDecrypt y pMapStart = sequence_ [printOp r | r <- showClimb tryDoubleSwaps scoreDecrypt y pMapStart]
    where printOp (score, pMap, xGuess) = do putStrLn $ show score
                                             putStrLn $ "abcdefghijklmnopqrstuvwxyz"
                                             putStrLn $ decryptBijectionToKey pMap
                                             putStrLn $ xGuess ++ "\n"
    

decryptBijectionToEncryptionPairs :: DecryptBijection -> [(PlaintextLetter, CiphertextLetter)]
decryptBijectionToEncryptionPairs pMap = [(p, toUpper c) | (p, c) <- sort $ [(plain, cipher) | (cipher, plain) <- M.toList pMap, cipher /= ' ']]

decryptBijectionToKey :: DecryptBijection -> String
decryptBijectionToKey pMap = map snd $ decryptBijectionToEncryptionPairs pMap

solveGen :: TryDoubleSwaps -> ScoreFunction -> Ciphertext -> IO ()
solveGen tryDoubleSwaps scoreDecrypt y = printClimb tryDoubleSwaps scoreDecrypt y' (frequencyGuess y')
    where y' = map toLower $ filter isLetter y 

solveGenRev :: TryDoubleSwaps -> ScoreFunction -> Ciphertext -> IO ()
solveGenRev tryDoubleSwaps scoreDecrypt y = printClimb tryDoubleSwaps scoreDecrypt y' (M.fromList $ zip ['a'..'z'] (reverse ['a'..'z']))
    where y' = map toLower $ filter isLetter y 

solve :: ScoreFunction -> Ciphertext -> IO ()
solve scoreDecrypt y = solveGen False scoreDecrypt y

solveRev :: ScoreFunction -> Ciphertext -> IO ()
solveRev scoreDecrypt y = solveGenRev False scoreDecrypt y

solveWithDoubleSwaps :: ScoreFunction -> Ciphertext -> IO ()
solveWithDoubleSwaps scoreDecrypt y = solveGen True scoreDecrypt y

-------------------------------------------------------------------------------
-- More convenient interface where don't have to specify the map

type NumberOfGrams = Int

gramSolveGen :: TryDoubleSwaps -> GramLength -> NumberOfGrams -> Ciphertext -> IO ()
gramSolveGen tryDoubleSwaps m n y = solveGen tryDoubleSwaps (scoreDecryptFunction m n) y

gramSolveGenRev :: TryDoubleSwaps -> GramLength -> NumberOfGrams -> Ciphertext -> IO ()
gramSolveGenRev tryDoubleSwaps m n y = solveGenRev tryDoubleSwaps (scoreDecryptFunction m n) y
    
scoreDecryptFunction :: GramLength -> NumberOfGrams -> ScoreFunction
scoreDecryptFunction m n
    | m == 3 = scoreString (sf n) (trigramLLs n)
    | m == 2 = scoreString 1 (digramLLs n)    
    where sf n | n <= 2000 = 1.25
               | n <= 2500 = 1.4
               | n <= 3000 = 2
               | otherwise = 2


gramSolve :: GramLength -> NumberOfGrams -> Ciphertext -> IO ()    
gramSolve = gramSolveGen False    

trigramSolve :: NumberOfGrams -> Ciphertext -> IO ()
trigramSolve = gramSolve 3

trigramSolveRev :: NumberOfGrams -> Ciphertext -> IO ()
trigramSolveRev = gramSolveGenRev False 3

trigramSolveRevMoreSteps :: NumberOfGrams -> Ciphertext -> IO ()
trigramSolveRevMoreSteps = gramSolveGenRev True 3

trigramSolveMoreSteps :: NumberOfGrams -> Ciphertext -> IO ()
trigramSolveMoreSteps = gramSolveGen True 3

digramSolve :: Ciphertext -> IO ()
digramSolve = gramSolve 2 (26^2)

digramSolveMoreSteps :: Ciphertext -> IO ()
digramSolveMoreSteps = gramSolveGen True 2 (26^2)

-------------------------------------------------------------------------------
-- Testing

testCiphertext = filter (/= ' ') testCiphertextWithSpaces

testCiphertextWithSpaces = map toLower $
    "KQX WJZRUHXZKUY GTOXSKPIX GW SMBFKGVMUFQB PL KG XZUTYX KDG FXGFYX JLJUYYB MXWXMMXR\  
     \ KG UL UYPSX UZR TGT KG SGHHJZPSUKX GIXM UZ PZLXSJMX SQUZZXY PZ LJSQ U DUB KQUK UZ\ 
     \ GFFGZXZK XIX SUZZGK JZRXMLKUZR DQUK PL TXPZV LUPR KQX SQUZZXY SGJYR TX U KXYXFQGZX\  
     \ YPZX GM KQX PZKXMZXK WGM XCUHFYX"

testCiphertextAlt = map toLower $ filter (/= ' ') "IFJAJ DAJ BNXKBWM UADLIKLDE AJDMBTM PBA MIWOCKTQ LACUIBQADUFC IFJ MWNRJLI KM DEMB PWEE BP HDIFJHDIKLDE KTIJAJMI IFJAJ DAJ LBTTJLIKBTM IB EKTJDA DEQJNAD TWHNJA IFJBAC MIDIKMIKLM DTO UABNDNKEKIC IFJBAC DM GJEE DM IFJBAJIKLDE LBHUWIJA MLKJTLJ"

testTrigramSolve n = trigramSolve n testCiphertext

testTrigramSolveAlt n = trigramSolve n testCiphertextAlt

-------------------------------------------------------------------------------
-- Initial guess by frequencies

englishFrequencies = zip
  ['e', 't', 'a', 'o', 'i', 'n', 's', 'h', 'r', 'd', 'l', 'u', 'c', 'm', 'w', 'f', 'g', 'y', 'p', 'b', 'v', 'k', 'j', 'x', 'q', 'z']
  [12.7, 9.1, 8.2, 7.5, 7.0, 6.7, 6.3, 6.1, 6.0, 4.3, 4.0, 2.8, 2.8,
         2.4, 2.3, 2.2, 2.0, 2.0, 1.9, 1.5, 1.0, 0.8, 0.2, 0.1, 0.1, 0.1]

sortedFrequencies y = reverse $ sort [(length (filter (== c) y), c) | c <- ['a'..'z']]
    
frequencyGuess y = M.fromList $ (' ', ' ') : zip (map snd $ sortedFrequencies y) (map fst $ englishFrequencies) 


-------------------------------------------------------------------------------
-- Utility functions

printList xs = putStrLn $ unlines $ map show xs

nubSorted []  = []
nubSorted [x] = [x]
nubSorted (x : y : zs) | x == y = nubSorted (y : zs)
                       | otherwise = x : nubSorted (y : zs)
                       
subwords w = concat [initialWords (drop l w) | l <- [0..length w - 1]]

initialWords w = [take m w | m <- [1..length w]]

compose fs = foldr (.) id fs
GHCi, version 8.6.3