-
Notifications
You must be signed in to change notification settings - Fork 70
Expand file tree
/
Copy path04-DataStructures.coffee
More file actions
486 lines (396 loc) · 11.4 KB
/
04-DataStructures.coffee
File metadata and controls
486 lines (396 loc) · 11.4 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
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
require './prelude'
# Properties
show '--- Properties ---'
text = 'purple haze'
show text['length']
show text.length
# No property
show '--- No property ---'
# try/catch is explained in `Error Handling`,
# it lets the script continue after an error.
try
nothing = null
show nothing.length
catch error
show error.message
# Object properties
show '--- Object properties ---'
cat =
colour: 'grey'
name: 'Spot'
size: 46
# Or: cat = {colour: 'grey', name: 'Spot', size: 46}
cat.size = 47
show cat.size
delete cat.size
show cat.size
show cat
# Property properties
show '--- Property properties ---'
empty = {}
empty.notReally = 1000
show empty.notReally
thing = {'gabba gabba': 'hey', '5': 10}
show thing['5']
thing['5'] = 20
show thing[2 + 3]
delete thing['gabba gabba']
show thing
propertyName = 'length'
text = 'mainline'
show text[propertyName]
# The `of` operator
show '--- The of operator ---'
chineseBox = {}
chineseBox.content = chineseBox
show 'content' of chineseBox
show 'content' of chineseBox.content
show chineseBox, 4
# Showing properties
show '--- Showing properties ---'
abyss = {let:1, us:go:deep:down:7}
show abyss
show abyss, 5
# Exercise 10
show '--- Exercise 10 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# Mutability
show '--- Mutability ---'
object1 = {value: 10}
object2 = object1
object3 = {value: 10}
show object1 == object2
show object1 == object3
object1.value = 15
show object2.value
show object3.value
# Data representation
show '--- Data representation ---'
mailArchive = {
'the first e-mail': 'Dear nephew, ...'
'the second e-mail': '...'
# and so on ...
}
mailArchive = {
0: 'Dear nephew, ... (mail number 1)'
1: '(mail number 2)'
2: '(mail number 3)'
}
for current of mailArchive
show 'Processing e-mail #' + current +
': ' + mailArchive[current]
# Arrays
show '--- Arrays ---'
mailArchive = ['mail one', 'mail two', 'mail three']
for current in [0...mailArchive.length]
show 'Processing e-mail #' + current +
': ' + mailArchive[current]
# Exercise 11
show '--- Exercise 11 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# For expression
show '--- For expression ---'
numbers = (number for number in [0..12] by 2)
show numbers
# Methods on objects
show '--- Methods on objects ---'
doh = 'Doh'
show typeof doh.toUpperCase
show doh.toUpperCase()
mack = []
mack.push 'Mack'
mack.push 'the'
mack.push 'Knife'
show mack.join ' '
show mack.pop()
show mack
# Emails
show '--- Emails ---'
mailArchive = (require "./04-emails").retrieveMails()
for email, i in mailArchive
show "Processing e-mail ##{i} #{email[0..15]}..."
# Do more things...
# Split
show '--- Split ---'
words = 'Cities of the Interior'
show words.split ' '
# Exercise 12
show '--- Exercise 12 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# Splitting strings
show '--- Splitting strings ---'
paragraph = 'born 15-11-2003 (mother Spot): White Fang'
show paragraph.charAt(0) == 'b' &&
paragraph.charAt(1) == 'o' &&
paragraph.charAt(2) == 'r' &&
paragraph.charAt(3) == 'n'
show paragraph.slice(0, 4) == 'born'
show paragraph[0...4] == 'born'
# Exercise 13
show '--- Exercise 13 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# String boundaries
show '--- String boundaries ---'
show 'Pip'.charAt 250
show 'Nop'.slice 1, 10
show 'Pin'[1...10]
show startsWith('Idiots', 'Most honoured colleagues')
# Test of startsWith
show '--- Test of startsWith ---'
# Reference implementation
startsWithRef = (str, pat) ->
if !str? or !pat? then return
ref = true
for ch, ix in pat
if not ref = str[ix] is ch
break
ref
qc.declare 'startsWith matches reference',
[qc.arbString, qc.arbString],
(c, str, pat) ->
c.collect ref = startsWithRef str, pat
c.assert ref == startsWith str, pat
qc.declare 'startsWith matches substrings',
[qc.arbString, qc.arbWholeNum],
(c, str, len) ->
pat = str[0...len]
c.collect ref = startsWithRef str, pat
c.assert ref == startsWith str, pat
# Add `if !string? or !pattern? then return`
# to `startsWith` to make it succeed this test
qc.declare 'startsWith handles null/undefined',
[qc.arbNullOr(qc.arbUndefOr(qc.arbString)),
qc.arbNullOr(qc.arbUndefOr(qc.arbString))],
qc.failOnException (c, str, pat) ->
c.collect ref = startsWithRef str, pat
c.assert ref == startsWith str, pat
qc.test()
# Quick hack to avoid garbling of output
# when async test cases are reported.
# A better idea is one test suite in one file.
setTimeout ( ->
# Exercise 14
show '--- Exercise 14 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# Find living cats
show '--- Find living cats ---'
mailArchive = (require './04-emails').retrieveMails()
livingCats = 'Spot': true
for email in mailArchive
paragraphs = email.split '\n'
for paragraph in paragraphs
if startsWith paragraph, 'born'
names = catNames paragraph
for name in names
livingCats[name] = true
else if startsWith paragraph, 'died'
names = catNames paragraph
for name in names
delete livingCats[name]
show livingCats
if 'Spot' in livingCats
show 'Spot lives!'
else
show 'Good old Spot, may she rest in peace.'
for cat of livingCats
show cat
# Set functions
show '--- Set functions ---'
addToSet = (set, values) ->
for value in values
set[value] = true
removeFromSet = (set, values) ->
for value in values
delete set[value]
livingCats = Spot: true
for email in mailArchive
paragraphs = email.split '\n'
for paragraph in paragraphs
if startsWith paragraph, 'born'
addToSet livingCats, catNames paragraph
else if startsWith paragraph, 'died'
removeFromSet livingCats, catNames paragraph
show livingCats
# Cat functions
show '--- Cat functions ---'
findLivingCats = ->
mailArchive = (require './04-emails').retrieveMails()
livingCats = 'Spot': true
handleParagraph = (paragraph) ->
if startsWith paragraph, 'born'
addToSet livingCats, catNames paragraph
else if startsWith paragraph, 'died'
removeFromSet livingCats, catNames paragraph
for email in mailArchive
paragraphs = email.split '\n'
for paragraph in paragraphs
handleParagraph paragraph
livingCats
howMany = 0
for cat of findLivingCats()
howMany++
show 'There are ' + howMany + ' cats.'
# Dates
show '--- Dates ---'
whenWasIt = year: 1980, month: 2, day: 1
show whenWasIt
whenWasIt = new Date 1980, 1, 1
show whenWasIt
show new Date
show new Date 1980, 1, 1
show new Date 2007, 2, 30, 8, 20, 30
# Date getters
show '--- Date getters ---'
today = new Date();
show "Year: #{today.getFullYear()}
month: #{today.getMonth()}
day: #{today.getDate()}"
show "Hour: #{today.getHours()}
minutes: #{today.getMinutes()}
seconds: #{today.getSeconds()}"
show "Day of week: #{today.getDay()}"
today = new Date()
show today.getTime()
# Comparing dates
show '--- Comparing dates ---'
wallFall = new Date 1989, 10, 9
gulfWarOne = new Date 1990, 6, 2
show wallFall < gulfWarOne
show wallFall == wallFall
# but
show wallFall == new Date 1989, 10, 9
wallFall1 = new Date 1989, 10, 9
wallFall2 = new Date 1989, 10, 9
show wallFall1.getTime() == wallFall2.getTime()
# Timezones
show '--- Timezones ---'
now = new Date()
show now.getTimezoneOffset()
# Exercise 15
show '--- Exercise 15 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# Record functions
show '--- Record functions ---'
catRecord = (name, birthdate, mother) ->
name: name
birth: birthdate
mother: mother
addCats = (set, names, birthdate, mother) ->
for name in names
set[name] = catRecord name, birthdate, mother
deadCats = (set, names, deathdate) ->
for name in names
set[name].death = deathdate
# Extract function
show '--- Extract function ---'
extractMother = (paragraph) ->
start = paragraph.indexOf '(mother '
start += '(mother '.length
end = paragraph.indexOf ')'
paragraph[start...end]
show extractMother \
'born 15/11/2003 (mother Spot): White Fang'
# Exercise 16
show '--- Exercise 16 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# Shorter extract function
show '--- Shorter extract function ---'
extractMother = (paragraph) ->
between paragraph, '(mother ', ')'
show extractMother \
'born 15/11/2003 (mother Spot): White Fang'
# Improved cat-algorithm
show '--- Improved cat-algorithm ---'
findCats = ->
mailArchive = (require './04-emails').retrieveMails()
cats = {'Spot': catRecord 'Spot',
new Date(1997, 2, 5), 'unknown'}
handleParagraph = (paragraph) ->
if startsWith paragraph, 'born'
addCats cats, catNames(paragraph),
extractDate(paragraph),
extractMother(paragraph)
else if startsWith paragraph, 'died'
deadCats cats, catNames(paragraph),
extractDate(paragraph)
for email in mailArchive
paragraphs = email.split '\n'
for paragraph in paragraphs
handleParagraph paragraph
cats
catData = findCats()
show catData
# Information functions
show '--- Information functions ---'
formatDate = (date) -> "#{date.getDate()}/" +
"#{date.getMonth() + 1}/" +
"#{date.getFullYear()}"
catInfo = (data, name) ->
unless name of data
return "No cat by the name of #{name} is known."
cat = data[name]
message = "#{name}," +
" born #{formatDate cat.birth}" +
" from mother #{cat.mother}"
if "death" of cat
message += ", died #{formatDate cat.death}"
"#{message}."
show catInfo catData, "Fat Igor"
# Exercise 17
show '--- Exercise 17 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# Exercise 18
show '--- Exercise 18 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# Variable arguments
show '--- Variable arguments ---'
argumentCounter = ->
show "You gave me #{arguments.length} arguments."
argumentCounter 'Death', 'Famine', 'Pestilence'
# Print variable arguments
show '--- Print variable arguments ---'
print = -> show arg for arg in arguments
print 'From here to', 1/0
# Optional arguments
show '--- Optional arguments ---'
add = (number, howmuch) ->
if arguments.length < 2
howmuch = 1
number + howmuch
show add 6
show add 6, 4
# Exercise 19
show '--- Exercise 19 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# Exercise 20
show '--- Exercise 20 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# Hidden built-in properties
show '--- Hidden properties ---'
for name of Math
show name
# Hidden array properties
show '--- Hidden array properties ---'
for name of ['Huey', 'Dewey', 'Loui']
show name
# Show hidden properties
show '--- Show hidden properties ---'
show Math, 2, true
show ['Huey', 'Dewey', 'Loui'], 2, true
# Watched properties
show '--- Watched properties ---'
array = ['Heaven', 'Earth', 'Man']
array.length = 2
show array
),300