-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathneuralnetwork.p8
More file actions
385 lines (351 loc) · 20.3 KB
/
neuralnetwork.p8
File metadata and controls
385 lines (351 loc) · 20.3 KB
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
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
pico-8 cartridge // http://www.pico-8.com
version 42
__lua__
-- picomnist
-- by bigsexydaddy
scalew = 0.06498428453590946
scaleb = 0.059529313912947204
function dequantize(qw, scale)
return qw * scale
end
function exp(x)
return 2.71828^x
end
function sigmoid(x)
return x / (1 + abs(x))
end
-- Super simple dot product function
-- Only works if a is a matrix and b is a vector
function dot(a, b)
local result = {}
if #a[1] != #b then
stop("Matrix and vector sizes do not match")
end
for i=1, #a do
result[i] = 0
for j=1, #b do
result[i] += a[i][j] * b[j]
end
end
return result
end
function softmax(x)
local max = x[1]
for i=2, #x do
if x[i] > max then
max = x[i]
end
end
local exps = {}
local sum = 0
for i=1, #x do
exps[i] = exp(x[i] - max)
sum += exps[i]
end
local result = {}
for i=1, #x do
result[i] = exps[i] / sum
end
return result
end
-- Nearest neighbor interpolation
-- Doesn't actually mimic the way the MNIST dataset is created but it seems to work fine? Lmk if there's a better way that doesn't compromise performance
function interpolate(input)
local out = {}
for y=1,28 do
out[y] = {}
for x=1,28 do
local src_x = flr(x*4)
local src_y = flr(y*4)
out[y][x] = input[src_y][src_x]
end
end
return out
end
function init_weights()
weights = {}
local c = 0
for i=1, #size-1 do
weights[i] = {}
for row=1, size[i+1] do
weights[i][row] = {}
for col=1, size[i] do
local num = @c
-- dequantize
local real_num = (num << 4 & 0xf0) | (num >> 4 & 0x0f)
real_num = (real_num < 128) and real_num or (real_num - 256)
weights[i][row][col] = dequantize(real_num, scalew)
c += 1
end
end
end
end
function init_biases()
biases = {}
local c = 8120
for i=1, #size-1 do
biases[i] = {}
for row=1, size[i+1] do
local num = @c
local real_num = (num << 4 & 0xf0) | (num >> 4 & 0x0f)
real_num = (real_num < 128) and real_num or (real_num - 256)
biases[i][row] = dequantize(real_num, scaleb)
c += 1
end
end
end
-- a should be a vector of size 784
function feedforward(a)
local sm = {}
for i=1, #size-1 do
local z = dot(weights[i], a)
for j=1, #z do
z[j] += biases[i][j]
end
if i == #size-1 then
sm = softmax(z)
end
for j=1, #z do
z[j] = sigmoid(z[j])
end
a = z
end
return {a, sm}
end
function _init()
size = {784, 10, 14, 10}
cols = {0,5,6,7}
init_weights()
init_biases()
a = {}
drawn = {}
result = {}
click = false
btnpos = {0,0}
poss = {}
poke(0x5f2d, 1)
guess = nil
sm = {0,0,0,0,0,0,0,0,0,0}
a = {0,0,0,0,0,0,0,0,0,0}
cur_time = 0
time_spent = 0
g = {'g','u','e','s','s'}
flat = {}
printh("\n#### INIT ####\n")
end
function _update()
btnpos[1] = stat(32)
btnpos[2] = stat(33)
if stat(34) == 1 then
add(poss, {btnpos[1], btnpos[2]})
click = true
end
if btnp(4) then
poss = {}
end
if btnp(5) then
printh("\nnew guess\n")
local drawn = get_drawn()
local interpolated = interpolate(drawn)
for i=1, #interpolated do
for j=1, #interpolated[i] do
flat[(i-1)*28+j] = interpolated[i][j] / 7
end
end
local result = feedforward(flat)
a = result[1]
sm = result[2]
guess = get_idx_of_max(sm) - 1
end
end
function _draw()
cls()
for i=1, #g do
print(g[i],116,(i-1)*6,7)
end
-- colon
pset(116,31,7)
pset(118,31,7)
print(guess or 0,116,34,7)
for i=1, #sm/2 do
local v = round_to_2(sm[i]*100)
print(i-1,(i-1)*26,115,8)
print(v.."%",(i-1)*26+5,115,7)
end
for i=#sm/2, #sm do
local v = round_to_2(sm[i]*100)
print(i-1,(i-6)*26,122,8)
print(v.."%",(i-6)*26+5,122,7)
end
rect(0,0,112,112,1)
clip(0,0,112,112)
for p in all(poss) do
circfill(p[1], p[2], 4, 7)
end
clip()
pset(btnpos[1], btnpos[2], 2)
end
-- function print_image(x)
-- for i,v in ipairs(x) do
-- local index = flr(#cols*v)
-- local color = cols[index]
-- local x = (i % 28)*4
-- local y = flr(i / 28)*4
-- for j=x,x+3 do
-- for k=y,y+3 do
-- pset(j, k, color)
-- end
-- end
-- end
-- end
function get_idx_of_max(x)
local max = 1
for i,v in ipairs(x) do
if v > x[max] then
max = i
end
end
return max
end
function get_drawn()
local arr = {}
for y=1, 28*4 do
arr[y] = {}
for x=1, 28*4 do
arr[y][x] = pget(x,y)
end
end
return arr
end
function round_to_2(x)
return flr(x*10)/10
end
__gfx__
000000000100ffff00000101ff0000ff0001000001ff00ff00000100ff0100000001000000000101feffff020101000000000001000000000001000001000202
04090b0d0f1013110d0b0d0704030001ff010000000001000204070b101c1b1a23141e150d17200e12150c03fd0200000000ff00040807120b03fbfe0ef7ff09
08fc1004fd0701fa0104010100ff01ff0306030300ff07faf6eb04fff5eff8f50f06010d0e0a020100ff00000504040903150a11140d01fcfef3e8ed00fd000a
210f07000000ffff06fe00020902fbf902e7fc0304f6f0f108f7fc0826100800ff00feff040800fd090e010e0509fefcf1ecf60206fffcfa1c1b0b01ff0100fe
03090a0b0505f5fa09fdf1fef9e4f0ec06faf7fd081a0a0000000000090b0d05050510000110050afde7e6e500f7fefb02170b00ffff00020d0a0707070a070d
0e1620281f150aedf6e5fcf4f90e0801000100020c08070b08150a0c000319251a02020701f6fcf9fe050301ff010107040a030403fdf80a031c0919320b0912
09fcf0eefe05ff0000000109f3f6f0dbf9fcf9f0ff0a1a13291706f8fffcfef8f805ff01ff000008ebe0f3e4f3fdea14f723262512feed03f8010804ff050000
0000ff08f3f0f9fdeff2eaf7fb29220c00effd04f5fe04050a04ff00ff00fd0e01fceff4f000e3e9f72515fbf2eff7feeff5f3f0000102000000001001f8f7f9
fbf5d7f8131b07fefaf9f6fbfefaf0f9feff010000000115fe0af6fbe7fcf2f5051efefe000d0700fbf3fafa0101ff0001ff021104f6fc02f7fcf3f90d0a080a
ff090906f8f106f704fd0000000003100ffef4050205f6e9070c03ff00000202fcfdfc0604feff00000103091402fbf3eefa02f0fafe0c00f7ff09f9f7f6f900
000001000001000405120302f704fcf1f90cfd09000106060f05fb0300ff00ff0000ffffff03060f0bf60706fcfe060d0e100811140f080904010000000000ff
fefe0307060b110a1614171f140c09080d08040404000001ff0000010001000001060907050a0b0b08040302040300000000010101000000000000ff00000000
010201030101010001ff000101ff00ff00000000000000ff0001ff000000ff0000ffff000000ff000001000000000002000100000001000000000000ff010100
010000000000ff00000000000000000000fffe00fffefcfc01020203010101000000ffff010000ff00000100fefdfaf6f80a141818150d1407fefcfdffff0000
0000ff010003fffcf8efe7ebf504f9000f2a212e150c0a09fffbff000000ff000202fffafffaedfb03eef8f40b03fbfe02040d0a01fc0000000100fd020b050a
0cf8e8e6e7dfd7ded8e1dffaf2fe171b08fd02fe000001fcff04ff0a03f7e7e4c7ead6ded2ede8efdfe90c1604ff01ff000003fefbfefe00f4fe04dae1e4cddd
cee8eff7fbf7fa140107000001ff03f8f5f2edf9f9ededece6d7d0dcf3fdf304fa04fe0e07070301000003f7f1ebd6eee6f4f5ecebd5c618fa09fd03f9fffbfe
0b0300ff00ff02fcf5e6f1f5ef0111f2f9d8eef3f9f5dffedbf3e8edeef5fb0000ff0101eeed1111f7031c2e4707dfff05e7eaedebf8fcfdf8f9f8ff00ff00fd
f60e2611151d254238eadc12fe09ff00f7060d1206fafafe010000fe011b0b111d2a131b35f5ffff0512f71109fc14110f01fd0100000208060c051320110f0d
25fb14fa10f5f51afc041a0a0a03000001ff0003fafe1714150b05030a132023190d0110291d0f0c0b010000000001fe0606150c06fb07fff40b1f15060d11fd
1b11081108fe00ffff0100fb030f13150df5fd04160b150714070b040104f606fcffff0000fffffb031409fbfdf508150f1608161016fdfaf4fdeee9f8fcfe00
0000fef8f604fce8ea0000050f020002100406eaedf3e8f1f4f8ff01ff0000fcf5eeeae9ef04071012210c020011110cf4f3f4fefaff0000000000fdf7efe6eb
e3edfa00f50c021e0700171705ff00f9fb010000ff0000fdfbf1edefedf0ddf0eff2fdf8f9f806050c02fcf6f6010100ffff0000fdfcfbf3e8f2eef3e9ece5f5
fafbfd01f5ecfafaf90000ff010001fffff9f7eedfe2e4e1dfeae9f3daded9eae8eef5f8fb00010100000000fdfcf9f7efe8e5e4d5e0bac9e5e6d6ecedf0f8fe
00000000ff0000ffff000000fffffdfff9fcf600fffffbf8ffff000100ff000100010000ffffff00ff000000ff000000000000ff010000000000ff0001000000
0000ff0000000100ff02020003010000ff0000000000ff000000000100ff00000409020406060901020607ffffff00ff0000010000000000000001000510161f
1c211e01080404fffff6030b06ff0100ff0100000001020104130f1b210c0904171a04030301070209040100000000fefe0104040f220c13130c0b0a041b1017
01faf7f8fc090200000000fefe070d121e23040817110813fc0efc04090807f10104fc000000020001080c151c170e11f9110e15101116f9fd06f7f405fff700
0000010103060c1418190b15110417060c050606020101fd03eef7ff000101ff010105121c2705f70bfbeefafa0a030e16080a0bfaecfafdff0200fcfdff0406
1015f4fcf8eedfe1f50609f30e020cf9e5e7f7ff010100fcfa0304050300020c03f0ecd6f8180510220912fbf3eefbfe0000fefefc020703fbf6031af7f5e6e9
0e0f1b241a1419130801fdff0100fdfffdff03fef4ffff02ee05ec09ecf8081a1c0e170f0500ff0300fffffeffffff01f70708060000f6f2f2f6fc0a0e090b08
01010001ffff01000002ff06fb050306f602f100f1040b0b1212100d0401ff0100ffff00ff00090c1504130315faf104021212100b04080c090404ff00ff0000
fef5fe111413fffe07f1f900080606060a090410100902ff00ff0003fcf8fa03000b04fbf4fbe10b090bfc050e0d0e0e0c07000000ff0305060611f707f6fff8
f6ed060cf509fff91316100a060500ff0000030c10120b11f3eef0f505f9edf3f700fc05141d17090000ff000000050b07ff0006fc0af7f9f402eb010afff70a
191f1a080000ff00ff000304ffe8f4fa01060b181113f808ffeae4fd15180d0301ff000001ffff03fdf0f9060206fb0a0709120af8f3fe09161608020000fe01
0000ff02040905070b0b091918150b121f0900fe04060600010100ffff00ff010209070e12111c17130b06110f02fc01ffff000201000000ff00000002040306
050408090a0e0b0706030302010100010000010000000000ff000001ffffff000100000000ff0001ff010000ff00ff00000000000100ff00000000ff00000000
0001ffff0000010000000000ff0100000000ff0000000002000000ff00ff00000100000100000000000000000000ff0000020506030502010203030202020302
0001000000ffff0000000102070b14181818120c140b0d09080903030400010100000001010300060b11140a081107ff05060b0d090602040201010100ff0001
0200050204fafdfefa02060504fb020101fafbf8fdfcff000000010102faf5f5f8fd07faf5041d1a03041cfe0600f5efebf8fcfe00fffdf8fdfbf5f7fbf2f2fe
090313230d13fffdfdffede4e5f4f8ff00fdfaf7f2effceef0f4faf6f90a08160d0104f2f409fbdce2e8f6ff0100f8f5f0e9f5ecf2f401fef402100b07e40605
f7fafdf2eae6f6000000f5f9f5ebfef6f4e5e8e3e4dbeae3f6eff6fef1d7f6e5e8ebf3ff00fffcfbf2fa09eb01f0fd0403050d090501f3f3fbfa03f6f7f3f900
fffefcf9f7fd08f8f9060e06012510ff0815020c05180f160dfcf90000fff704fd010a0309010c06141a0b0e0d0e13161113081102fbf8fe0000fd0afc1b1c16
120e101c160b0306f5040af9fcfd0510fff9fc000000000aff261f2131272d0bf8fb0b030b03fa03eefbfe04fb02fe00ff0101070b221d2521130400f4f40bfd
fef1fd00060305f40002ff000000000610120c0e160cfbf7f6f9fc0005fe050a0d0e0a0207040000ff00ff08141305f705e8f6ece8f1fc0e130809131611100e
0b0600000001fc08100c0cfbe6e4f6f1e4ebf7fefc1b201318130d1308000000000001050e0d1306f9f8fde8eef80afb0c0f14131a0d070c0b020000ff000407
120e01fdfeeffaf90101ec0508ed020c06ff0607080000ff0000020a0cfefaf404feff0becf3e7fb0c0000ff01090605030000ffff000205080bfbfb09f4edf8
efeff3e7f90a0804070a030003ff00ff0100ff020c0d010b0d12f6ff02fbfbfafbfaf2f2010100ff00ffff010001010106150b0c100d0b0b000206fbe4f4fdf2
ff0000020000ff00000101010c0b0708050a1006090d0f0001fefcf50102ffff0000000100000001010000000000fffffffe050401fefdfd0103ffffff000100
000100000101010100000000000001010000ff00ff0100000100ffff0000000000000207030000020001000201010101010101000000000000000001ff01040a
0c0a0c1016161a1c201919060409040201ff00000100000001ff010c0f100503060f010407fbff020c0405110d01000000010000fdfafc03020500e803f305e7
f9f3ecfa0701fafef4fbff0000ff00fff9f2f5f50bf809f9fa081405f807010302f201e8e9f7ff00ff00fffbf4e90303f8f003f7fffc04f9f10601fdf6f4f3d4
e2f3fc00000001f8f0ee0f0709f5ff11f0f906fef0fcf7f5e7f7ffddedf5fd00000000f8eef900f8f3f90203fbe908f6f903ddf0f2ebf8dce3f4fe01000000f3
f2fbfdfdf100feff06fd00f7f4ece8eee5e7e0d9e2f7fc020000feebf50eff0207f60304100ff90708f4f5f7f8eee0e7e8f4fdff0000fff0ff14f7fc01fbfceb
e7dedadef0ecf204fa06fdf9f8fffe000000fff8fb03ede6e3ded5d3e0d8d8d8e8f308eb070905010500ff0100fffffbeee9e2ddddf0edfcf60600fbebf1f7f3
f307fe151b070501000000fdeed8e9ff0605fc07fbfcfff5fceb03fcecf50a19160806ffffff02fdf4f50d1104090413fa0a0afef5fbef03fbf9fc0112170503
000001faf9092210f10e0b11061207faff08f502f30203030a22110300fffffbff04080909090e15020b1205faffffff04f8f1ff1e200a00ff00f8f60a0ff70d
220c1709291610000cfafd0306ff02222c130100ff00fbfa0905fd03fc130b17181b0b020f0908010f0c0920260c030000ff01041b0a0a0e11110e1c0d060cff
1a0415120ffe06211e090300000000030e04f305fc020bfc07131012070c060c03091b24110c02ff00ff01070b10fd0afb0a0efafcfafef7070a0d111320110e
05070100ff000000ff010a03010cfcfa06fefcf4ffe5f5fff90a04f5040300ff000000fbf7f9f60001eadef2ede0f1e4dae0ecebff01f6f5050501ff010000ff
fefaf3e9ddd7e7e0efe3e6ebe9eee4ec0500faf9ff02000000ffff0101fffef9f9fbfcf6fefafbfbfafffefffeffff00ff00010000000100000000010001fdff
0001ff00000001ff000000010000ff01ff010100010000000001ff0001ffffff000001000000000000000000010000000100ff000101000000000000ffff0000
0000ff010001ff0001000000000000000002ffff02080702fdfc0003040607020100020000000000000100010108060906fc061b18141719111c1c1911040000
0001feff010407050604fdf7f2f9f6fc000a0b1413160f1a0f030000ff0000fdfefefcf1101805dff502f4f5e5effbfa05f9fc0c07fefd00000100fbff01fb08
0900fa04fff0e50a0402f7e8f1fcfaf0f9fd01fe0001060600f9fa0bfffc00fb100405090405120111f5f6eff8fffeff000308fff0ff04030d09f60c04eb0703
06f6f0f2f8eff4f6e5edf5fb00010502000b070201f704021e08fc02f2f5fbf803f2f1d8daeaf2ffff010505060bfffd0310060304140006090afb10fd0300dd
dcf1f7ff0001040406fdfc01080ef70703fc011a1a17f8fd040f02e7d8edfa00ff01030007010607fe02f5100cfbe2100fff20fd00f806f3e5eef6fdff0000fd
04090c030dff1101fdf1f8070313f910fffd000300fafa00ff010201070413090a050efdfefbec030a0f06131d0921141207ff00000101000806170e0cff1909
f3e9f018131e16081e1a1f1b1906ff000001fefe05fd1812ff0208fceef3fcf201160e13141712070c02000000000101fced0711140f1309f4fefb150b010809
060cf4fdfc02feffff000102f2ecf4ffff000a02f8f7070506030200f107e4edecfafdfe00000006f0ddefecf1e6020902eff8f5eeeef801f701dbe5f0fc0000
00ff0001f6dbd5dbe8fbf5070a040307f9e9ecf4eaeed9ea0005ff00ff00fef5f8e2d5f0f7f2eb0403f700ee05f3dedfdde2e9f4fe04fe010000fef5faf7e9f8
fbe3eddbeeeaf4dcf7e8fbe3e8ebf0f6010100000100fff7020a0905fff1f5e4dce7eddad0e4f402eff3f3f80000ff000000ff000d1b130f0e000704f3efe3f7
f90af7fd0308fefffcfeff00000000040e120c1c0f00ed0f021001100bf5eefb0b0805030000ff0000010000000306090f160e130e112716fef9ff0302ff0000
ff0000ff00ff0001ff0100010000fefafd000101000000000301010000010000ff0001000001000100ff00ff0000010100ff000001ff0000000000ffff0000ff
00ff00ffffff00fefdfffefdfffe00fefeff000000000001000000000100fffbfdff00fffdfcfbfcfdfbf8f5f7f9feff00ff0001000000000000fefdfe010910
0a070402060900fffff6f5f7fe000000010102ff0101fe001b14060b0a1304fbf2f703eef6f2eaf1fc00000001ff00030e0a140f150601ff060d061cf9fe0df9
fcf0dfdcf8020000000000091013140708fd070a100feef60a0107e4fa0aeae6effafe000000010b1c1208f4ff06f7050d0af8100604f2fa0af3e7e8def5fbff
ff00020f2912f50708ef00ed02170807f5ff03eff3ede5d3c5ebfb000000021323150612f6ebf9daf608372b0c0616060ff2ebc6bedff7ff00ff030c110d0504
efebf1f0e60328172125333a4b4328fbdadff8010001070e0cfcfae7edf1fe1200e2f6090409000b303e441afef3fc0000030509faf6eaefff0dfdf5f0de1b0a
f90709f0e8fa181008fdff0100010305f9fcf8ea03fef0e4eb0622020a0f09f7fef7f1fe020402010000020502070802f9edfbf70700f400fe0901f8ff0af1f7
f50403ff000000050c1a14faf5edfcf2f4000a100a02fefdfdf80304fa020402000000080c04fc0a070f0103fffff8f50df108fc08010901fb07090400000105
fcf0eb08040302030204f6f80807f400fc0100f9fd11050100000101fcf5f600fd000cfaef040c110300fc0cfd130dfb020f02010000030708fcfa02f0010505
07f9faf7f610110910fb04f0051103000100000905f90809fdfafff6ff0014f30b030401ff0afcf10a0b000000000201f6010cfcfcf5f7fbeef6f2f70007fb0b
03f0eef50606000001000205f8fe10fb05fff4f8fbfdf5fa0104090105fa03fd020200000000000406fcfb05f30cf0fffb05ec01f10108fa060906000200ff01
00010002060c070afaf90207fa00fdfe05fbeaf1fbfeff000102010000000000030807050405fffafa0300f5fc01ff00fbfefefe000001ff00000000fffffd02
0c0c070500040b0108090303fefc0100000100ff010000010001ff00000201ffff0103010102ffff0100000100ff0000010000ff000000ff000000ff0100ff01
0000000100ff0000000000000000fe00ff01fefdfcfffdf8f4fb000001fefefdfdfdff000000010000ff00000000fef8f5f7ecedebf1f5f8f7f6f0f2f7f5fafd
fe01000001ff00ff01fefbeee1e4d5dbd0c3c8dce9f3f204f6fbfefb01000101ff0100ff03fffbf2ede8dde9e8e1e1e7fbf5f5130b0b120d07ff030100010000
020503faf9f7edfef8f8f401ebedfef9fc0c22140c06fd00ff0000fe0200030df0f7f9fdf1f3030406fafef9f1fbfe05fbfa00ff00fffe0305fd0304fdfefb05
fbff0100fffdfd09020101f3f1ef0300ff0100fa01fafcf4f80608f5fcfff7fef7fd03020dfc00f7f2f7fbffff00050102fa00f7edfdff0007fefefd111410f4
f8f902f6ebeef5fbff000301fdf6030e040a0d04fe03f40a04ee0d08f70800e6e9e9f701ff010002ff0a0d100e0a08f8fef1f61001fd0e030aff01ece8effd00
010100ff01170600fcff05eb0aeee90aff0e1c0d040c0ef2ea070501000001000a0afb0308fd08faf3eb0707080e0002180dfdebed0f0801ff0000030a000c09
00f8fbf8f90800f70c07101d09f9f800ef0b0100ffffff0814fe12f90908f4f0ff000b050a0e09f9ecfbfbfef9fdfc010000ff060dff040d06eef3f20406110e
01fc0002030e0101fd00fe0000fffffc00f4f71008faecfd202d1f230d00f3ea02f8f600010300000100fff8f8f5f1f5f7fe0105fd0b09fd00f2f4f406ffe2ed
f702ff000000ff04fbf9f8efdbd3e1faed080dfded01f3eedfecd7e6f90001000000fe00f7eef4f1f0f2e7e3ecf304f70801f3e8edefdff00001000001fffcf8
f6f2e6e4f6f700fdfcebfc0107fd09000c00fb05070200000001fbf8f400f2f00405f6fc07f3f903040f1d0b180806070701000001fffcf6eefbf3edfcf3f9f5
03f90e000c0ffb050e070809070001000100fbf8f70c03f6f0eef9eff300fff1efeef0f704060507010000000000ffff060b040b1000e500f8f4faeee7f3fafd
0403fc0300000100000001000102070f14120708fdfa00fef9ff00040200ff0000ff00000001ff00010001000200fffcff030303ff01fcff0100ff0000000001
000101000101000100000101ff0200000000ff0001000000ff0001000001ff0000000101020001040404fffbfaff0002030600000001ffffff01010000ff0206
09010b060a0804fff8f7ff040a0d0700fbfb0000ff00ff0000ff020505fdfaf3f5e6ebeef1fc040c0e11150bfcfbff0000ffff00fffdfaf7f7f6eff2fb04fbea
f8fdf000fc06050efcfbff000000ff00fefefb00fffafbfef5fc09fdfafffbfa0606fa0301fd00ff010100fff9f6f802fdf6f3fefdfef9fef40efc010005ff0d
160301ffffff01feeceff0f9fcfffefff4e9f703f6fc00f20201f7141908000000ff01fae0e7fbf0f601fc00f802f2fd0900fafcfc00f820290a0201000100f1
e1f1f3f0fbe2e8f1f90d11e4f0fef504fe0af80f230502000000fffdff00f701f50217494b4224f0f6f3f405020905140b00ff00000004061d22253840677048
11160bf7f4fdfbfaf10a220afcfc0100000004142d34556f58380cfe0bfa0900f30d00000506210ff7f2ff0000010012283b4826070307fa040b0208fb09ff00
0afb2113f0edfd000100020d0e1d11f8fafbf504f805f40ff7ffedf8f9040f02f5edf701ff01ff0603fcf1fdfbf50cf2fdfbfdf603080801fbf90afdeaebeffd
0001fefbfcfdeef612000704fc02fd04faf1f8fdf6edf6f2e0dae7fc0000fef1e1faf7060e0b120efff8fcfffffef4fdfbf0f6eaece4f200000001f1e6f6fe06
0f04fd0e04f9f8f4fbeb05e9fcf8f8f4ebe4fdff010000efeb00f0f10cf809f50ef7130df6fef9f6f7fcf9f4ece2faff0001ffe8dc00e90606f607f81209f9fd
fd010606ff09fdfef0f0fd000100fce5eef60401f809f80b050604030a0402f90e080000fbf6ffff000100f5fce7fcfaf2fefcff0800fefe05f503f5031101f7
fcfd00ff000001ff06f6f6e70c0a090907f90b020c05f8f60408f800ffff00ff000100fbf9f6f9020203fa05f401fb02fb09070b0009010500ffffffffff0000
fcfefb00f5f4f0f8fbfcfcfb010a0e1a151e090300000001ffff00ff01060500ff000102030b050703020204060905ff0000ff0000ff0000010000010000ffff
000000000000ff000000050000ffffff0100000101000000fe0100ff01000100000000000000ff0000000000000000ff00000001000000000000ff0000ff0000
00000000000000ff0000010000000000fefbfefefbf8f5fb0001fffdfffe0000ff000200000000ff01fffe00fdf7f9ff0a070702f8f6edfcfcfbfbfbfe000000
01000000010102070505040808fef2f4ef0001f8f7f6fd030406020000000001020406070e070f060d0df606140306040dfe0913150e020000010002060503ff
080a0deefc100afa110b04020e06060e2c21060100ff00060b0c120a0a05120f0ff50cf3ff01f705050bfffd1d220601000101090707fffaf6f301030808070e
0c0209010c030118151402010001010d0dfaf3f3f403f91b0c07130a00fc02f9fd0d04111f1a04ff0100041c13fae7010dfbfd04fe201aff05f9fbee0800ef12
151b07000001172009f40ef3f305160a1918e5f7f0fafeeaefe3e4f80a0d0b000001121d100b1d0a1cf0110bfadad0e7eaf1f3dbece2e9eb020305ffff000a14
010c02fafe0b120ce8d7eee0e6ecfae6ebf0fcf80501ffff00000411fe04fa0312050edcd5e8e5edf3dffbee06ff12151100feffff000203f9ed08fffbf1ece7
f0f3d7f4e6dbf305070409110a020000ff0003ff02fa00f8eaf0f8ece3dfd7efeaeafd110d0f130408fafefe000102070f0712eccddbeff4d8c4e7efea0f1820
0b0d100007fbfe01010102060f090bdfdbd2bccebfe5f2f0fb110f16081d060001fcfefe0001020c11131a02f7ece4f0f3fbfe101110060df6090100fffefe00
0000011213111c1711f912211e1306060f0201f4f80107f6f8ffff000000020a1002050816070c080e19161d080f0bfe030307f1f9fe00000000010403fdfa00
051113110d02090bfc0d1a0f080705f9f5fa0001000100020905f60e071b150b1bf90c03fe0afaf4f5f9f8f5fdfe000000000001070b061113160df8060a13fa
f80906f3ee0101f700ff00ff0000ff000406030b131aff0c1104fd1609fd1317f6020cfd000000000001000000040505060b07161504071e0ceb0c12040c0c01
00000100ff0100000100010201030607030706030004090503060a0100ff000003d8fbec30dd1b1227c7dd0f0f42e8431803d912d21e03edf016c8017feff13d
2a05d8dde3bc120af7102dc21927f82bf6f95d01f4f640beeebaec0cf934efa50c0b0e4ab3410e49ceedf6e009102db3fcda1eec10f81560cabaf6b8f1cddae1
010a2614a01647f73f421ef9f20f23e1dcd6de0c2c2bbe4de6edc60e50ddf9fcf1261c039508043cd32f1123f52a1f05dab3ecd4ae2f2cc020c5fdcbb0bbdc17
ec302011cf171a45f4bbd0eb0b1c3acb3fcf43b91bc0d437c2fcd120e2ece203d435bbcde3e71b0c089f173824beedc2dc2bc4ba1e25cc031ed3ce25b7f8ea57
180028e40e3fd618ac9e1fdff215f1ef0dcb23b439d8e2151f40bcfb38cf2b0e140de414240dbdd7bec9162014b6f3ccb5d00100e9e6dd2a6629f1f3e336f024
216ff1cffa15d11f27fb2e7fc9ef321dca9cf606bfb1c4bda7e6