-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcipher76.ex
229 lines (156 loc) · 4.39 KB
/
cipher76.ex
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
--
-- Fallout 76 - How to Decipher the Nuclear Code Yourself, Without Using A Program
-- https://www.reddit.com/r/fo76/comments/9yc0w9/fallout_76_how_to_decipher_the_nuclear_code/ea0vqq8
--
include std/cmdline.e
include std/console.e
include std/convert.e
include std/error.e
include std/io.e
include std/pretty.e
include std/sort.e
include std/text.e
include std/types.e
include words.e
--
-- A text file containing over 466k English words.
-- https://github.com/dwyl/english-words
--
constant WORDS_FILE = "words.txt"
constant ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
function verify_keyword( sequence word )
if length( word ) = 0 then
error:crash( "length(word) = 0" )
end if
if t_alpha( word ) = FALSE then
error:crash( "t_alpha(word) = FALSE" )
end if
return text:upper( word )
end function
function verify_piece( sequence piece )
if length( piece ) != 2 then
error:crash( "length(piece) != 2" )
end if
if t_alpha( piece[1] ) = FALSE then
error:crash( "t_alpha(piece[1]) = FALSE" )
end if
if t_digit( piece[2] ) = FALSE then
error:crash( "t_digit(piece[2]) = FALSE" )
end if
return piece
end function
function verify_pieces( sequence pieces )
if length( pieces ) != 8 then
error:crash( "length(pieces) != 8" )
end if
for i = 1 to length( pieces ) do
pieces[i] = verify_piece( pieces[i] )
end for
return pieces
end function
function get_cipherkey( sequence keyword )
-- start with alphabet
sequence cipherkey = ALPHABET
sequence removed = ""
-- remove letters from keyword
for i = 1 to length( keyword ) do
if find( keyword[i], removed ) then
continue
end if
integer index = find( keyword[i], cipherkey )
if index then
cipherkey = remove( cipherkey, index )
removed = append( removed, keyword[i] )
end if
end for
-- append the removed letters to the remaining alphabet
return removed & cipherkey
end function
function get_anagram( sequence cipherkey, sequence pieces )
sequence anagram = repeat( ' ', 8 )
for i = 1 to 8 do
integer index = find( pieces[i][1], cipherkey )
anagram[i] = ALPHABET[index]
end for
return anagram
end function
function get_codeword( sequence anagram )
sequence foundword = ""
sequence sortedgram = sort( anagram )
/*
integer file = open( WORDS_FILE, "r" )
if not file then
error:crash( "file = 0" )
end if
object line = gets( file )
while sequence( line ) do
sequence codeword = text:trim( line )
sequence sortedword = sort( codeword )
if equal( sortedgram, sortedword ) then
foundword = codeword
exit
end if
line = gets( file )
end while
close( file )
*/
for i = 1 to length( WORDS_LIST ) do
sequence codeword = WORDS_LIST[i]
sequence sortedword = sort( codeword )
if equal( sortedgram, sortedword ) then
foundword = codeword
exit
end if
end for
return foundword
end function
function get_ciphercode( sequence cipherkey, sequence anagram )
sequence ciphercode = repeat( ' ', 8 )
for i = 1 to 8 do
integer index = find( anagram[i], ALPHABET )
ciphercode[i] = cipherkey[index]
end for
return ciphercode
end function
function get_launchcode( sequence ciphercode, sequence pieces )
sequence launchcode = repeat( ' ', 8 )
for i = 1 to 8 do
for j = 1 to 8 do
if ciphercode[i] = pieces[j][1] then
launchcode[i] = pieces[j][2]
break
end if
end for
end for
return launchcode
end function
procedure main()
integer verbose = 0
sequence cmd = command_line()
sequence params = {}
if length( cmd ) < 11 then
puts( STDOUT, "usage:\n" )
puts( STDOUT, " cipher76 keyword piece1..piece8\n" )
return
end if
for i = 3 to length( cmd ) do
if equal( cmd[i], "-v" ) then
verbose = 1
else
params &= { cmd[i] }
end if
end for
sequence keyword = verify_keyword( params[1] )
sequence pieces = verify_pieces( params[2..9] )
sequence cipherkey = get_cipherkey( keyword )
printf( STDOUT, " cipher key: %s\n", {cipherkey} )
sequence anagram = get_anagram( cipherkey, pieces )
printf( STDOUT, " anagram: %s\n", {anagram} )
sequence codeword = get_codeword( anagram )
printf( STDOUT, " code word: %s\n", {codeword} )
sequence ciphercode = get_ciphercode( cipherkey, codeword )
printf( STDOUT, "cipher code: %s\n", {ciphercode} )
sequence launchcode = get_launchcode( ciphercode, pieces )
printf( STDOUT, "launch code: %s\n", {launchcode} )
end procedure
main()