summaryrefslogtreecommitdiffstats
path: root/2023/captions/emacsconf-2023-cubing--speedcubing-in-emacs--vasilij-wasamasa-schneidermann--main.vtt
blob: 2ae22295a3ab5f8485ade9d7010908aafb8d67c4 (plain) (blame)
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
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
WEBVTT captioned by sachac, checked by sachac

NOTE Introduction

00:00:00.000 --> 00:00:08.359
Hello, everyone, and welcome to Speedcubing in Emacs.

00:00:08.360 --> 00:00:10.119
First of all, a little bit about myself.

00:00:10.120 --> 00:00:13.679
My name is Vasilij Schneidermann. Online, I go by wasamasa.

00:00:13.680 --> 00:00:18.039
I'm 31 years old. I work in information security,

00:00:18.040 --> 00:00:20.479
and I do consulting and hacking

00:00:20.480 --> 00:00:22.479
and stuff like figuring out

00:00:22.480 --> 00:00:25.279
how to break into other people's computers

00:00:25.280 --> 00:00:29.359
and how to secure their systems basically.

00:00:29.360 --> 00:00:31.439
You can reach me by email.

00:00:31.440 --> 00:00:36.639
I do have a self-hosted code repository thingy going on.

00:00:36.640 --> 00:00:40.399
I have a blog, and you can find me

00:00:40.400 --> 00:00:45.919
in some other places online, like IRC for example.

00:00:45.920 --> 00:00:48.679
So about the talk itself,

00:00:48.680 --> 00:00:52.839
I used to be into the Rubik's cube when I was in school.

00:00:52.840 --> 00:00:54.039
I forgot about it, though,

00:00:54.040 --> 00:00:56.279
because these cubes were not very good.

00:00:56.280 --> 00:01:02.279
Recently I did find some cheap looking cube at a shop.

00:01:02.280 --> 00:01:04.119
Did not pay terribly much for it.

00:01:04.120 --> 00:01:07.039
It was so, so much better than my old cube,

00:01:07.040 --> 00:01:08.639
it was unreal.

00:01:08.640 --> 00:01:11.479
This motivated me to get back into

00:01:11.480 --> 00:01:13.559
this really weird kind of hobby.

00:01:13.560 --> 00:01:17.999
For this, you need to be good at producing

00:01:18.000 --> 00:01:19.399
a truly random scramble

00:01:19.400 --> 00:01:22.319
and timing your attempts to get any better at it.

00:01:22.320 --> 00:01:23.719
There is, of course, existing software

00:01:23.720 --> 00:01:26.239
to do the scrambling for you and the recording

00:01:26.240 --> 00:01:28.079
and the timekeeping and such,

00:01:28.080 --> 00:01:31.239
but all the good options seem to be either web or mobile,

00:01:31.240 --> 00:01:33.239
for example the cstimer software

00:01:33.240 --> 00:01:35.399
or the twisty-timer app on Android.


NOTE Cubing in Emacs

00:01:35.400 --> 00:01:39.319
To my surprise, I did not find a single decent option

00:01:39.320 --> 00:01:41.959
inside Emacs, so this is basically a case study

00:01:41.960 --> 00:01:44.999
how to do better. For this, I wanted to make use of

00:01:45.000 --> 00:01:47.799
all the cool new Emacs features that appeared,

00:01:47.800 --> 00:01:50.879
like the SVG library; Transient,

00:01:50.880 --> 00:01:53.599
the library used for the Magit-style interfaces;

00:01:53.600 --> 00:01:56.439
and the recently added sqlite-mode.

00:01:56.440 --> 00:02:01.159
And most importantly it was about having fun.

NOTE Prior art

00:02:01.160 --> 00:02:02.759
So here's a full list of prior art,

00:02:02.760 --> 00:02:04.279
I will not go into detail about this,

00:02:04.280 --> 00:02:06.239
but basically we have things solving

00:02:06.240 --> 00:02:08.039
very different parts of this,

00:02:08.040 --> 00:02:10.759
but not all of it. For example: we have several,

00:02:10.760 --> 00:02:14.239
we have a timer. We have several solvers.

00:02:14.240 --> 00:02:16.039
We have some scramblers.

00:02:16.040 --> 00:02:19.359
We have some whole-cube simulators, including a 3D one.

00:02:19.360 --> 00:02:20.759
We have something for making it easier

00:02:20.760 --> 00:02:23.119
to enter your algorithms in the notation.

00:02:23.120 --> 00:02:25.919
But nothing that does all of those things in one package,

00:02:25.920 --> 00:02:28.119
which kind of surprised me.

00:02:28.120 --> 00:02:32.039
So I present the `wca-prep` package.

NOTE The name

00:02:32.040 --> 00:02:35.559
So the name, I found it difficult

00:02:35.560 --> 00:02:39.959
to come up with a good name and so I looked

00:02:39.960 --> 00:02:42.559
and I saw, well there's this World Cube Association

00:02:42.560 --> 00:02:46.039
that holds these competitions where you compete.

00:02:46.040 --> 00:02:47.759
They do this for the Rubik's cube

00:02:47.760 --> 00:02:48.919
but also a few others,

00:02:48.920 --> 00:02:50.799
so there's like a standardized list

00:02:50.800 --> 00:02:52.639
of events they have for this.

00:02:52.640 --> 00:02:55.159
There is a standard notation for this

00:02:55.160 --> 00:02:56.519
and rules and everything.

00:02:56.520 --> 00:02:58.199
And the goal of my package is basically

00:02:58.200 --> 00:03:01.279
to help prepare myself for such a competition

00:03:01.280 --> 00:03:03.679
and in fact a week ago I went to my first one

00:03:03.680 --> 00:03:06.719
which was wild, but pretty cool.

00:03:06.720 --> 00:03:10.919
So for this reason I chose this name wca-prep,

00:03:10.920 --> 00:03:13.639
because it helps me prepare for this kind of competition

00:03:13.640 --> 00:03:16.519
and this limited the scope significantly,

NOTE What's in wca-prep

00:03:16.520 --> 00:03:18.999
I have a scrambler, visualization of the scramble,

00:03:19.000 --> 00:03:23.319
timer, and statistics.

00:03:23.320 --> 00:03:25.559
I excluded pretty much everything else I've seen.

00:03:25.560 --> 00:03:28.788
For this reason, I only tried to focus on

00:03:28.789 --> 00:03:32.199
some very basic puzzles I can solve comfortably,

00:03:32.200 --> 00:03:34.839
and did not want to do anything else

00:03:34.840 --> 00:03:36.439
that may complicate things significantly.

00:03:36.440 --> 00:03:40.479
No other kinds of puzzles, no simulation, no solving,

00:03:40.480 --> 00:03:43.919
no exotic events, and no specialized scrambles

00:03:43.920 --> 00:03:49.239
that are only good for practicing specific algorithms.

NOTE Demo

00:03:49.240 --> 00:03:54.199
So at this point the organizer should hopefully show

00:03:54.200 --> 00:03:57.999
a small video I've prepared, a one minute video showing how

00:03:58.000 --> 00:04:03.080
I actually use this to solve a cube and to time my solve.

NOTE Challenges: Representing the cube

00:05:19.840 --> 00:05:22.959
Okay, so building this thing, there were several challenges.

00:05:22.960 --> 00:05:24.959
The first one was how do I even represent

00:05:24.960 --> 00:05:26.919
the state of a Rubik's cube.

00:05:26.920 --> 00:05:29.959
For this there are many possible representations,

00:05:29.960 --> 00:05:32.159
no obvious best solution.

00:05:32.160 --> 00:05:34.079
I did not, well, what helped me was that

00:05:34.080 --> 00:05:36.439
I did not have to programmatically solve this thing,

00:05:36.440 --> 00:05:39.639
so I picked the easiest possible representation

00:05:39.640 --> 00:05:42.719
which is just an array of every single facelet.

00:05:42.720 --> 00:05:46.959
For a 3x3 cube you have 9 facelets on one side,

00:05:46.960 --> 00:05:51.719
so times 6 sides you would have 54 elements in this array.

00:05:51.720 --> 00:05:54.159
So with this representation, it's very simple,

00:05:54.160 --> 00:05:56.839
but it's kind of weird to do scrambles with this.

00:05:56.840 --> 00:05:59.359
But otherwise, it worked very, very well.

00:05:59.360 --> 00:06:01.719
In the future, I plan to learn some group theory,

00:06:01.720 --> 00:06:03.199
pick a better representation

00:06:03.200 --> 00:06:05.639
and do this in a much, much more elegant way

00:06:05.640 --> 00:06:12.319
without compromising speed too much.

00:06:12.320 --> 00:06:15.159
Yes. Once I had the representation,

00:06:15.160 --> 00:06:18.079
the scrambling itself should not be too hard.

00:06:18.080 --> 00:06:22.199
For this, it's important to consider that basically

00:06:22.200 --> 00:06:23.599
if you do a face turn

00:06:23.600 --> 00:06:26.879
you end up swapping some facelets with other facelets,

00:06:26.880 --> 00:06:30.479
that's the easiest way to think about this.

00:06:30.480 --> 00:06:33.719
To determine which one goes into which one's position,

00:06:33.720 --> 00:06:36.921
it was pretty confusing to figure this out.

00:06:36.922 --> 00:06:38.759
For this I went through a few papers,

00:06:38.760 --> 00:06:40.479
and I found one which suggested

00:06:40.480 --> 00:06:42.399
to just build a cube out of paper,

00:06:42.400 --> 00:06:44.479
number every facelet, and turn it

00:06:44.480 --> 00:06:48.799
and keep track of which facelet moved into which position.

00:06:48.800 --> 00:06:51.959
And programmatically, the `cl-rotatef` macro

00:06:51.960 --> 00:06:53.839
was very, very useful for doing this kind of

00:06:53.840 --> 00:06:56.079
in-place swapping you need for this operation.

00:06:56.080 --> 00:06:59.319
So in the future, group theory would hopefully

00:06:59.320 --> 00:07:02.439
make this a bit less awkward.

00:07:02.440 --> 00:07:04.559
Here's a photo of this paper cube I made

00:07:04.560 --> 00:07:08.319
along with a real cube. As you can see

00:07:08.320 --> 00:07:11.799
mathematically speaking, they are the same thing,

00:07:11.800 --> 00:07:13.719
they just look very, very different.

NOTE Scrambling

00:07:13.720 --> 00:07:18.759
So the scramble algorithm itself,

00:07:18.760 --> 00:07:23.879
I pondered how this would even be done. In the competitions,

00:07:23.880 --> 00:07:26.039
They do this in a very, very elaborate way.

00:07:26.040 --> 00:07:27.199
They generate a random cube,

00:07:27.200 --> 00:07:29.839
they try to solve it, and if it's solvable

00:07:29.840 --> 00:07:32.999
they use these solution moves

00:07:33.000 --> 00:07:35.279
to turn into a scramble basically.

00:07:35.280 --> 00:07:39.399
And they also make sure to canonicalize the moves,

00:07:39.400 --> 00:07:42.999
so if you have subsequent moves that can be simplified,

00:07:43.000 --> 00:07:45.039
they do simplify these as much as possible.

00:07:45.040 --> 00:07:45.679
For example,

00:07:45.680 --> 00:07:48.199
if you have two subsequent rotations in one direction,

00:07:48.200 --> 00:07:51.119
it's turned into a different kind of rotation,

00:07:51.120 --> 00:07:53.839
so 90 and 90 equals 180.

00:07:53.840 --> 00:07:57.759
And the other Elisp scramblers I looked at,

00:07:57.760 --> 00:07:59.559
they generate random moves.

00:07:59.560 --> 00:08:01.959
Some of them do canonicalize. Not all of them.

00:08:01.960 --> 00:08:05.359
This one tries to do the best low-fi thing,

00:08:05.360 --> 00:08:06.839
that is, generating random moves,

00:08:06.840 --> 00:08:08.479
canonicalizing and repeating

00:08:08.480 --> 00:08:13.999
until enough have been generated.

NOTE Visualization

00:08:14.000 --> 00:08:17.599
For the visualization I had to figure out

00:08:17.600 --> 00:08:18.959
something else too complicated.

00:08:18.960 --> 00:08:21.679
For this, I tried to figure out

00:08:21.680 --> 00:08:24.319
where every facelift would end up in the puzzle view

00:08:24.320 --> 00:08:25.879
when you would unfold it.

00:08:25.880 --> 00:08:30.119
And for this, I did not consider the facelet orientation.

00:08:30.120 --> 00:08:33.719
This may be important later for some other puzzles

00:08:33.720 --> 00:08:35.599
where you can end up with very twisted faces,

00:08:35.600 --> 00:08:37.479
but for simple cubes, it's not a problem.

00:08:37.480 --> 00:08:40.759
My initial prototype used colored text,

00:08:40.760 --> 00:08:43.199
but later, I used the SVG library.

00:08:43.200 --> 00:08:46.039
It turned out to be easy enough to use, actually.

00:08:46.040 --> 00:08:50.559
Currently, I have hard-coded face-color mappings,

00:08:50.560 --> 00:08:53.559
but I plan to replace this so that theming is possible.

00:08:53.560 --> 00:08:56.039
For example, if you happen to have a cube

00:08:56.040 --> 00:08:59.140
that does not have the same color mappings as I do,

00:08:59.141 --> 00:09:00.919
then you should be able to fix this.

NOTE UI with Transient

00:09:00.920 --> 00:09:05.879
Next challenge was to build

00:09:05.880 --> 00:09:08.399
a beautiful intuitive UI with Transient.

00:09:08.400 --> 00:09:11.319
The reason why I chose this is

00:09:11.320 --> 00:09:14.799
because it would be self-documenting and Magit-style,

00:09:14.800 --> 00:09:16.799
and everyone knows how Magit works basically.

00:09:16.800 --> 00:09:19.759
Since Transient has become part of Emacs,

00:09:19.760 --> 00:09:21.679
there is really no reason to not try it out.

00:09:21.680 --> 00:09:26.119
The problem was documentation is difficult to understand.

00:09:26.120 --> 00:09:27.839
It's very abstract and high level,

00:09:27.840 --> 00:09:30.319
and it's hard to figure out. "Okay,

00:09:30.320 --> 00:09:31.239
I want to do something,

00:09:31.240 --> 00:09:33.359
how am I supposed to do this?"

00:09:33.360 --> 00:09:37.799
I did find transient-showcase, which has lots of examples,

00:09:37.800 --> 00:09:40.079
but they don't really feel finished

00:09:40.080 --> 00:09:43.519
and not realistic enough.

00:09:43.520 --> 00:09:45.199
When I tried to use the package,

00:09:45.200 --> 00:09:47.359
I got plenty of unhelpful error messages

00:09:47.360 --> 00:09:48.559
when using it incorrectly.

00:09:48.560 --> 00:09:50.399
I did manage to figure it out,

00:09:50.400 --> 00:09:55.039
but I plan to find more actual examples of it,

00:09:55.040 --> 00:09:57.879
to have an executable reference basically

00:09:57.880 --> 00:10:00.079
and try to improve my use of it.

NOTE Book-keeping with SQLite

00:10:00.080 --> 00:10:05.999
For the book-keeping, I used SQLite.

00:10:06.000 --> 00:10:08.999
This is a very recent addition to Emacs,

00:10:09.000 --> 00:10:11.759
it only appeared in the current major version.

00:10:11.760 --> 00:10:13.839
It's still very early days.

00:10:13.840 --> 00:10:17.479
I found some oddities, one of them turned out to be

00:10:17.480 --> 00:10:19.279
a bug in the transaction macro.

00:10:19.280 --> 00:10:22.039
Like basically, if you do an SQL transaction

00:10:22.040 --> 00:10:24.639
and an error happens, then every helper I found

00:10:24.640 --> 00:10:25.399
does a rollback on an error.

00:10:25.400 --> 00:10:31.199
But this one did not. It actually committed on an error,

00:10:31.200 --> 00:10:34.319
and this was very weird to figure out.

00:10:34.320 --> 00:10:38.759
I reported a bug. Eli was nice enough to send me a patch.

00:10:38.760 --> 00:10:39.879
We did some patch review,

00:10:39.880 --> 00:10:42.439
and he ended up fixing it properly.

00:10:42.440 --> 00:10:50.119
So yes, there's still a lot to be done there, and yeah,

00:10:50.120 --> 00:10:51.359
the API is very basic.

00:10:51.360 --> 00:10:53.359
You don't have convenience helpers

00:10:53.360 --> 00:10:55.759
like fetch the first row or fetch the first value

00:10:55.760 --> 00:10:58.880
or anything, but they're easy enough to write yourself.

00:10:58.881 --> 00:11:00.820
And the biggest challenge with this bookkeeping part

00:11:00.821 --> 00:11:02.479
was figuring out a decent schema,

00:11:02.480 --> 00:11:04.599
like how to organize data correctly

00:11:04.600 --> 00:11:06.799
so that it would not be awkward to manipulate.

00:11:06.800 --> 00:11:10.199
And with this, you can finally build a package

00:11:10.200 --> 00:11:11.839
that remembers its state properly

00:11:11.840 --> 00:11:14.919
and don't have to run into foot guns

00:11:14.920 --> 00:11:17.079
with Lisp-style serialization, deserialization.

NOTE Conclusion

00:11:17.080 --> 00:11:22.639
So yes, that concludes it so far.

00:11:22.640 --> 00:11:26.639
So what did I learn from this exercise?

00:11:26.640 --> 00:11:28.959
Well, there are still plenty of packages

00:11:28.960 --> 00:11:30.039
for Emacs to be written.

00:11:30.040 --> 00:11:33.359
If you think everything you can think of

00:11:33.360 --> 00:11:35.799
or you need has already been written, well, guess what?

00:11:35.800 --> 00:11:36.239
No.

00:11:36.240 --> 00:11:38.495
These are still plenty of specialized things

00:11:38.496 --> 00:11:41.239
that could need your help.

00:11:41.240 --> 00:11:44.239
These cubes do not require advanced mathematics,

00:11:44.240 --> 00:11:45.599
contrary to what you may think.

00:11:45.600 --> 00:11:49.159
Yes, you can apply advanced mathematics to them

00:11:49.160 --> 00:11:51.919
if you want to, but you don't have to.

00:11:51.920 --> 00:11:55.439
What surprised me about this is basically group theory.

00:11:55.440 --> 00:11:56.519
I've heard of it before.

00:11:56.520 --> 00:11:58.279
It seemed to be a meme, basically,

00:11:58.280 --> 00:12:00.919
because it has been like mostly Haskell people

00:12:00.920 --> 00:12:02.639
being very excited about this

00:12:02.640 --> 00:12:06.959
and it seemed kind of, like, divorced from reality, basically.

00:12:06.960 --> 00:12:10.399
But this puzzle, it actually proves that yes,

00:12:10.400 --> 00:12:11.399
it has its use.

00:12:11.400 --> 00:12:12.879
It definitely has.

00:12:12.880 --> 00:12:15.839
You just have to find the right problem matching it,

00:12:15.840 --> 00:12:17.919
and yeah.

00:12:17.920 --> 00:12:19.839
So yeah, once I understand it better,

00:12:19.840 --> 00:12:22.999
the topic, I expect to write better code.

00:12:23.000 --> 00:12:28.919
These new Emacs features, they work well enough.

00:12:28.920 --> 00:12:30.359
There are some rough edges.

00:12:30.360 --> 00:12:31.879
They definitely need more testing.

00:12:31.880 --> 00:12:35.119
So please, please, everyone,

00:12:35.120 --> 00:12:38.999
if you write Elisp, please try SQLite or Transient

00:12:39.000 --> 00:12:41.159
or anything else that looks cool and shiny.

00:12:41.160 --> 00:12:42.919
Report bugs.

00:12:42.920 --> 00:12:46.039
Find ways to improve them, anything. And yeah,

00:12:46.040 --> 00:12:49.319
I'm sure that if we do this,

00:12:49.320 --> 00:12:52.119
then Emacs will continue to get even better.

00:12:52.120 --> 00:12:56.239
So yeah, what's next for this package?

00:12:56.240 --> 00:13:00.439
Well, I could... There are lots of obvious UI improvements

00:13:00.440 --> 00:13:01.799
and testing to be done.

00:13:01.800 --> 00:13:04.159
I basically want to reach feature parity

00:13:04.160 --> 00:13:06.879
with the twisty-timer app, which this is very much inspired by.

00:13:06.880 --> 00:13:11.119
I want nice-looking stats like graphical ones

00:13:11.120 --> 00:13:13.239
instead of just a simple list of times.

00:13:13.240 --> 00:13:15.679
And I want support for more puzzles, of course,

00:13:15.680 --> 00:13:16.999
not just the simple cubes,

00:13:17.000 --> 00:13:19.039
but as I progress learning these puzzles,

00:13:19.040 --> 00:13:22.519
I want to have Emacs supporting me for this.

00:13:22.520 --> 00:13:26.879
But generally, it's a very open-ended package.

00:13:26.880 --> 00:13:31.079
And this concludes the talk.

00:13:31.080 --> 00:13:35.360
Thank you very much.