-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlevels.js
More file actions
342 lines (314 loc) · 9.92 KB
/
levels.js
File metadata and controls
342 lines (314 loc) · 9.92 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
function empty(rows, cols) {
return new Array(rows).fill().map(() => new Array(cols).fill());
}
export const levels = [
{
text: `
Welcome!
<b>Cellbound</b> is a logic puzzle game that takes place entirely within a spreadsheet.
Your goal is to edit each formula so that the input cell values match the output. Formulas go in the top box within each cell. The computed value is in the bottom box within each cell.
For the first few levels, the formula for the output will be shown. For the actual puzzles, the formulas will be hidden.
You will learn the spreadsheet formula language as you go.
<hr />
Cells can contain numbers.
`,
level: empty(4, 1),
solution: [
[{ formula: "420", hidden: false }],
[{ formula: "-69", hidden: false }],
[{ formula: "1.337", hidden: false }],
["=256 ** 2"],
],
endText: `
When everything matches, you can proceed to the next level...
`,
},
{
text: `
In addition to numbers, cells may contain formulas.
Formulas begin with the <code>=</code> symbol. They can contain math, numbers, and functions. Many standard math functions will work.
`,
level: empty(4, 1),
solution: [
[{ formula: "=1 + 1", hidden: false, valueHidden: true }],
[{ formula: "=2 * 3 + 4", hidden: false, valueHidden: true }],
[{ formula: "=(1+2) * (3 + 2**2)", hidden: false, valueHidden: true }],
[{ formula: "=LOG(2 ** 16) / LOG(2)", hidden: false, valueHidden: true }],
],
endText: `
Expand the list below to see all of the available formula functions.
`,
},
{
text: `
Formulas can operate on numbers, booleans, and strings. Strings and booleans must use a formula beginning with <code>=</code>.
`,
level: empty(3, 1),
solution: [
[
{
formula: "=OR(NOT(true), AND(NOT(false), NOT(NOT(true))))",
hidden: false,
valueHidden: true,
},
],
[{ formula: `="Cat " + "hat"`, hidden: false, valueHidden: true }],
[
{
formula: `=IF(!true, "hat", "mat")`,
hidden: false,
valueHidden: true,
},
],
],
},
{
text: `
Formulas can contain references. References have the form <code>R1C1</code> where <code>1</code> can be replaced with a row or column number. Indices start at 0. Negative indices go from the final row or column.
The row and/or column can be omitted to refer to the current row or column. <code>RC</code> can be used for self-reference.
A variation of this notation is available in other spreadsheets like Microsoft Excel and Google Sheets. (It is typically how formulas are represented internally in these engines, and can optionally be exposed to the user.) It is known as <a href="https://en.wikipedia.org/wiki/Spreadsheet#Cell_reference" target="_blank">R1C1 reference style</a>.
`,
level: empty(3, 2),
solution: [
[
{ formula: "1", hidden: false },
{ formula: "2", hidden: false },
],
[
{ formula: "=R0C-1", hidden: false, valueHidden: true },
{ formula: "=R0C0", hidden: false, valueHidden: true },
],
[
{ formula: "=R0C0 + R0C1", hidden: false, valueHidden: true },
{ formula: "=RC0 * R0C1 + 1", hidden: false, valueHidden: true },
],
],
},
{
text: `
The previous level introduced absolute references like <code>R10C2</code>.
Formula references can also be relative, rather than absolute. Relative references are encosed in square brackets. So one cell to the right in the same row is <code>RC[1]</code> and one cell in the current column and row above is <code>R[-1]C</code>.
`,
level: empty(3, 2),
solution: [
[
{ formula: "1", hidden: false },
{ formula: "2", hidden: false },
],
[
{ formula: "=R[-1]C1", hidden: false, valueHidden: true },
{ formula: "=R[-1]C[-1]", hidden: false, valueHidden: true },
],
[
{ formula: "=R[-2]C + R[-2]C[1]", hidden: false, valueHidden: true },
{ formula: "=RC[-1] ** R-1C-2 + 1", hidden: false, valueHidden: true },
],
],
},
{
text: `
Now that you know how basic formulas and references work, it's time for the first challenge.
Guess the mystery function based on its outputs.
<details><summary>Hint</summary>
Does the shape of the curve remind you of anything? Perhaps a common trigonometric function?
</details>
`,
level: [
[{ formula: "=TICK(100) / 10", hidden: true, nocheck: true }],
[undefined],
[
{
formula: "=SPARKBARS(CACHE(20, R[-1]C))",
style: "font-family: monospace, monospace",
hidden: true,
nocheck: true,
},
],
],
solution: [
[{ formula: "=TICK(100) / 10", nocheck: true }],
["=SIN(R[-1]C)"],
[
{
formula: "=SPARKBARS(CACHE(20, R[-1]C))",
style: "font-family: monospace, monospace",
nocheck: true,
},
],
],
endText: `
Amaing job! This one may have been tricky if you don't remember trigonometry.
`,
},
{
text: `
The final spreadsheet formula lanugage feature to introduce is range selection.
Ranges are designated by a start reference and end reference separated by a colon, like <code>RC0:RC[-1]</code>. The start and end are inclusive.
To complete this level, sum the preceding rows in the final cell.
`,
level: [
[{ formula: "=XORSHIFT(TICK(2000) + 1) % 100 + 1", hidden: true }],
[{ formula: "=XORSHIFT(R[-1]C) % 100 + 1", hidden: true }],
[{ formula: "=XORSHIFT(R[-1]C) % 100 + 1", hidden: true }],
[{ formula: "=XORSHIFT(R[-1]C) % 100 + 1", hidden: true }],
[{ formula: "=XORSHIFT(R[-1]C) % 100 + 1", hidden: true }],
[{ formula: "=XORSHIFT(R[-1]C) % 100 + 1", hidden: true }],
[undefined],
],
solution: [
["=XORSHIFT(TICK(2000) + 1) % 100 + 1"],
["=XORSHIFT(R[-1]C) % 100 + 1"],
["=XORSHIFT(R[-1]C) % 100 + 1"],
["=XORSHIFT(R[-1]C) % 100 + 1"],
["=XORSHIFT(R[-1]C) % 100 + 1"],
["=XORSHIFT(R[-1]C) % 100 + 1"],
["=SUM(R0C:R[-1]C)"],
],
},
{
text: `
Now that you know how formulas work, we can get to more interesting puzzles.
For this and most of the upcoming puzzles, formulas will automatically be copied between some of the cells. Duplicated cells are marked with an asterisk in their top right corner.
You will need to come up with a single formula that will work for <i>all</i> of the duplicate cells.
`,
level: [
[undefined],
[{ reference: { row: 0 } }],
[{ reference: { row: 0 } }],
[{ reference: { row: 0 } }],
[{ reference: { row: 0 } }],
[{ reference: { row: 0 } }],
[{ formula: "=SUM(R0C:R[-1]C)", locked: true }],
],
solution: [
[{ formula: "7", valueHidden: true }],
[{ formula: "7", valueHidden: true }],
[{ formula: "7", valueHidden: true }],
[{ formula: "7", valueHidden: true }],
[{ formula: "7", valueHidden: true }],
[{ formula: "7", valueHidden: true }],
[{ formula: "=SUM(R0C:R[-1]C)", hidden: false }],
],
},
{
text: `
Not all of the duplicated cell puzzles will be as easy as the last one.
`,
level: [
[undefined],
[undefined],
[{ reference: { row: 1 } }],
[{ reference: { row: 1 } }],
[{ reference: { row: 1 } }],
[{ reference: { row: 1 } }],
[{ reference: { row: 1 } }],
[{ formula: "=SUM(R0C:R[-1]C)", locked: true }],
],
solution: [
["2"],
["3"],
["4"],
["5"],
["6"],
["7"],
["8"],
[{ formula: "=SUM(R0C:R[-1]C)", hidden: false }],
],
},
{
text: `
<details><summary>Hint</summary>
It might be worth reading up on the most famous contributions of the Italian mathematician <a href="https://en.wikipedia.org/wiki/Fibonacci">Fibonacci</a>.
</details>
`,
level: [
[undefined],
[undefined],
[undefined],
[{ reference: { row: 2 } }],
[{ reference: { row: 2 } }],
[{ reference: { row: 2 } }],
[{ reference: { row: 2 } }],
[{ reference: { row: 2 } }],
[{ reference: { row: 2 } }],
[{ reference: { row: 2 } }],
],
solution: [
["0"],
["1"],
["=R[-1]C + R[-2]C"],
["=R[-1]C + R[-2]C"],
["=R[-1]C + R[-2]C"],
["=R[-1]C + R[-2]C"],
["=R[-1]C + R[-2]C"],
["=R[-1]C + R[-2]C"],
["=R[-1]C + R[-2]C"],
["=R[-1]C + R[-2]C"],
],
},
{
level: [
[undefined],
[{ reference: { row: 0 } }],
[{ reference: { row: 0 } }],
[{ reference: { row: 0 } }],
[{ reference: { row: 0 } }],
[{ reference: { row: 0 } }],
[{ reference: { row: 0 } }],
[{ formula: "=SUM(R0C:R[-1]C)", locked: true }],
],
solution: [
["=ROW() * 2 + 1"],
["=ROW() * 2 + 1"],
["=ROW() * 2 + 1"],
["=ROW() * 2 + 1"],
["=ROW() * 2 + 1"],
["=ROW() * 2 + 1"],
["=ROW() * 2 + 1"],
[{ formula: "=SUM(R0C:R[-1]C)", hidden: false }],
],
},
{
text: `
You may need to refresh the page to restart the sequence after you enter your solution.
<details><summary>Hint</summary>
Cellbound formulas support self-reference.
</details>
`,
level: [
[
{
formula: "=TICK(1000)",
hidden: true,
valueHidden: true,
nocheck: true,
},
],
[
{
formula:
"=FLOOR((XORSHIFT(R[-1]C + 1) % 1000 - 500) * R[-1]C / 1000)",
hidden: true,
nocheck: true,
},
],
[undefined],
[undefined],
],
solution: [
[{ formula: "=TICK(1000)", valueHidden: true, nocheck: true }],
[
{
formula:
"=FLOOR((XORSHIFT(R[-1]C + 1) % 1000 - 500) * R[-1]C / 1000)",
nocheck: true,
},
],
["=MIN(R1C, RC)"],
["=MAX(R1C, RC)"],
],
endText: `
Maybe later I'll add some more levels with <a href="https://en.wikipedia.org/wiki/Semilattice" target="_blank">semilattices</a>.
`,
},
];