summaryrefslogtreecommitdiffstats
path: root/2023/captions/emacsconf-2023-cubing--speedcubing-in-emacs--vasilij-wasamasa-schneidermann--main.vtt
blob: db303c956d6f791ffadeda9b90fc1c17e555ad35 (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:05:15.239
I actually use this to solve a cube and to time my solve.

NOTE Challenges: Representing the cube

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

00:05:18.509 --> 00:05:20.508
The first one was how do I even represent

00:05:20.509 --> 00:05:22.468
the state of a Rubik's cube.

00:05:22.469 --> 00:05:25.508
For this there are many possible representations,

00:05:25.509 --> 00:05:27.708
no obvious best solution.

00:05:27.709 --> 00:05:29.628
I did not, well, what helped me was that

00:05:29.629 --> 00:05:31.988
I did not have to programmatically solve this thing,

00:05:31.989 --> 00:05:35.188
so I picked the easiest possible representation

00:05:35.189 --> 00:05:38.268
which is just an array of every single facelet.

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

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

00:05:47.269 --> 00:05:49.708
So with this representation, it's very simple,

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

00:05:52.389 --> 00:05:54.908
But otherwise, it worked very, very well.

00:05:54.909 --> 00:05:57.268
In the future, I plan to learn some group theory,

00:05:57.269 --> 00:05:58.748
pick a better representation

00:05:58.749 --> 00:06:01.188
and do this in a much, much more elegant way

00:06:01.189 --> 00:06:07.868
without compromising speed too much.

00:06:07.869 --> 00:06:10.708
Yes. Once I had the representation,

00:06:10.709 --> 00:06:13.628
the scrambling itself should not be too hard.

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

00:06:17.749 --> 00:06:19.148
if you do a face turn

00:06:19.149 --> 00:06:22.428
you end up swapping some facelets with other facelets,

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

00:06:26.029 --> 00:06:29.268
To determine which one goes into which one's position,

00:06:29.269 --> 00:06:32.470
it was pretty confusing to figure this out.

00:06:32.471 --> 00:06:34.308
For this I went through a few papers,

00:06:34.309 --> 00:06:36.028
and I found one which suggested

00:06:36.029 --> 00:06:37.948
to just build a cube out of paper,

00:06:37.949 --> 00:06:40.028
number every facelet, and turn it

00:06:40.029 --> 00:06:44.348
and keep track of which facelet moved into which position.

00:06:44.349 --> 00:06:47.508
And programmatically, the `cl-rotatef` macro

00:06:47.509 --> 00:06:49.388
was very, very useful for doing this kind of

00:06:49.389 --> 00:06:51.628
in-place swapping you need for this operation.

00:06:51.629 --> 00:06:54.868
So in the future, group theory would hopefully

00:06:54.869 --> 00:06:57.988
make this a bit less awkward.

00:06:57.989 --> 00:07:00.108
Here's a photo of this paper cube I made

00:07:00.109 --> 00:07:03.868
along with a real cube. As you can see

00:07:03.869 --> 00:07:07.348
mathematically speaking, they are the same thing,

00:07:07.349 --> 00:07:09.268
they just look very, very different.

NOTE Scrambling

00:07:09.269 --> 00:07:14.308
So the scramble algorithm itself,

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

00:07:19.429 --> 00:07:21.588
They do this in a very, very elaborate way.

00:07:21.589 --> 00:07:22.748
They generate a random cube,

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

00:07:25.389 --> 00:07:28.548
they use these solution moves

00:07:28.549 --> 00:07:30.828
to turn into a scramble basically.

00:07:30.829 --> 00:07:34.948
And they also make sure to canonicalize the moves,

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

00:07:38.549 --> 00:07:40.588
they do simplify these as much as possible.

00:07:40.589 --> 00:07:41.228
For example,

00:07:41.229 --> 00:07:43.748
if you have two subsequent rotations in one direction,

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

00:07:46.669 --> 00:07:49.388
so 90 and 90 equals 180.

00:07:49.389 --> 00:07:53.308
And the other Elisp scramblers I looked at,

00:07:53.309 --> 00:07:55.108
they generate random moves.

00:07:55.109 --> 00:07:57.508
Some of them do canonicalize. Not all of them.

00:07:57.509 --> 00:08:00.908
This one tries to do the best low-fi thing,

00:08:00.909 --> 00:08:02.388
that is, generating random moves,

00:08:02.389 --> 00:08:04.028
canonicalizing and repeating

00:08:04.029 --> 00:08:09.548
until enough have been generated.

NOTE Visualization

00:08:09.549 --> 00:08:13.148
For the visualization I had to figure out

00:08:13.149 --> 00:08:14.508
something else too complicated.

00:08:14.509 --> 00:08:17.228
For this, I tried to figure out

00:08:17.229 --> 00:08:19.868
where every facelift would end up in the puzzle view

00:08:19.869 --> 00:08:21.428
when you would unfold it.

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

00:08:25.669 --> 00:08:29.268
This may be important later for some other puzzles

00:08:29.269 --> 00:08:31.148
where you can end up with very twisted faces,

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

00:08:33.029 --> 00:08:36.308
My initial prototype used colored text,

00:08:36.309 --> 00:08:38.748
but later, I used the SVG library.

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

00:08:41.589 --> 00:08:46.108
Currently, I have hard-coded face-color mappings,

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

00:08:49.109 --> 00:08:51.588
For example, if you happen to have a cube

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

00:08:54.690 --> 00:08:56.468
then you should be able to fix this.

NOTE UI with Transient

00:08:56.469 --> 00:09:01.428
Next challenge was to build

00:09:01.429 --> 00:09:03.948
a beautiful intuitive UI with Transient.

00:09:03.949 --> 00:09:06.868
The reason why I chose this is

00:09:06.869 --> 00:09:10.348
because it would be self-documenting and Magit-style,

00:09:10.349 --> 00:09:12.348
and everyone knows how Magit works basically.

00:09:12.349 --> 00:09:15.308
Since Transient has become part of Emacs,

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

00:09:17.229 --> 00:09:21.668
The problem was documentation is difficult to understand.

00:09:21.669 --> 00:09:23.388
It's very abstract and high level,

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

00:09:25.869 --> 00:09:26.788
I want to do something,

00:09:26.789 --> 00:09:28.908
how am I supposed to do this?"

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

00:09:33.349 --> 00:09:35.628
but they don't really feel finished

00:09:35.629 --> 00:09:39.068
and not realistic enough.

00:09:39.069 --> 00:09:40.748
When I tried to use the package,

00:09:40.749 --> 00:09:42.908
I got plenty of unhelpful error messages

00:09:42.909 --> 00:09:44.108
when using it incorrectly.

00:09:44.109 --> 00:09:45.948
I did manage to figure it out,

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

00:09:50.589 --> 00:09:53.428
to have an executable reference basically

00:09:53.429 --> 00:09:55.628
and try to improve my use of it.

NOTE Book-keeping with SQLite

00:09:55.629 --> 00:10:01.548
For the book-keeping, I used SQLite.

00:10:01.549 --> 00:10:04.548
This is a very recent addition to Emacs,

00:10:04.549 --> 00:10:07.308
it only appeared in the current major version.

00:10:07.309 --> 00:10:09.388
It's still very early days.

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

00:10:13.029 --> 00:10:14.828
a bug in the transaction macro.

00:10:14.829 --> 00:10:17.588
Like basically, if you do an SQL transaction

00:10:17.589 --> 00:10:20.188
and an error happens, then every helper I found

00:10:20.189 --> 00:10:20.948
does a rollback on an error.

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

00:10:26.749 --> 00:10:29.868
and this was very weird to figure out.

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

00:10:34.309 --> 00:10:35.428
We did some patch review,

00:10:35.429 --> 00:10:37.988
and he ended up fixing it properly.

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

00:10:45.669 --> 00:10:46.908
the API is very basic.

00:10:46.909 --> 00:10:48.908
You don't have convenience helpers

00:10:48.909 --> 00:10:51.308
like fetch the first row or fetch the first value

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

00:10:54.430 --> 00:10:56.369
And the biggest challenge with this bookkeeping part

00:10:56.370 --> 00:10:58.028
was figuring out a decent schema,

00:10:58.029 --> 00:11:00.148
like how to organize data correctly

00:11:00.149 --> 00:11:02.348
so that it would not be awkward to manipulate.

00:11:02.349 --> 00:11:05.748
And with this, you can finally build a package

00:11:05.749 --> 00:11:07.388
that remembers its state properly

00:11:07.389 --> 00:11:10.468
and don't have to run into foot guns

00:11:10.469 --> 00:11:12.628
with Lisp-style serialization, deserialization.

NOTE Conclusion

00:11:12.629 --> 00:11:18.188
So yes, that concludes it so far.

00:11:18.189 --> 00:11:22.188
So what did I learn from this exercise?

00:11:22.189 --> 00:11:24.508
Well, there are still plenty of packages

00:11:24.509 --> 00:11:25.588
for Emacs to be written.

00:11:25.589 --> 00:11:28.908
If you think everything you can think of

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

00:11:31.349 --> 00:11:31.788
No.

00:11:31.789 --> 00:11:34.044
These are still plenty of specialized things

00:11:34.045 --> 00:11:36.788
that could need your help.

00:11:36.789 --> 00:11:39.788
These cubes do not require advanced mathematics,

00:11:39.789 --> 00:11:41.148
contrary to what you may think.

00:11:41.149 --> 00:11:44.708
Yes, you can apply advanced mathematics to them

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

00:11:47.469 --> 00:11:50.988
What surprised me about this is basically group theory.

00:11:50.989 --> 00:11:52.068
I've heard of it before.

00:11:52.069 --> 00:11:53.828
It seemed to be a meme, basically,

00:11:53.829 --> 00:11:56.468
because it has been like mostly Haskell people

00:11:56.469 --> 00:11:58.188
being very excited about this

00:11:58.189 --> 00:12:02.508
and it seemed kind of, like, divorced from reality, basically.

00:12:02.509 --> 00:12:05.948
But this puzzle, it actually proves that yes,

00:12:05.949 --> 00:12:06.948
it has its use.

00:12:06.949 --> 00:12:08.428
It definitely has.

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

00:12:11.389 --> 00:12:13.468
and yeah.

00:12:13.469 --> 00:12:15.388
So yeah, once I understand it better,

00:12:15.389 --> 00:12:18.548
the topic, I expect to write better code.

00:12:18.549 --> 00:12:24.468
These new Emacs features, they work well enough.

00:12:24.469 --> 00:12:25.908
There are some rough edges.

00:12:25.909 --> 00:12:27.428
They definitely need more testing.

00:12:27.429 --> 00:12:30.668
So please, please, everyone,

00:12:30.669 --> 00:12:34.548
if you write Elisp, please try SQLite or Transient

00:12:34.549 --> 00:12:36.708
or anything else that looks cool and shiny.

00:12:36.709 --> 00:12:38.468
Report bugs.

00:12:38.469 --> 00:12:41.588
Find ways to improve them, anything. And yeah,

00:12:41.589 --> 00:12:44.868
I'm sure that if we do this,

00:12:44.869 --> 00:12:47.668
then Emacs will continue to get even better.

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

00:12:51.789 --> 00:12:55.988
Well, I could... There are lots of obvious UI improvements

00:12:55.989 --> 00:12:57.348
and testing to be done.

00:12:57.349 --> 00:12:59.708
I basically want to reach feature parity

00:12:59.709 --> 00:13:02.428
with the twisty-timer app, which this is very much inspired by.

00:13:02.429 --> 00:13:06.668
I want nice-looking stats like graphical ones

00:13:06.669 --> 00:13:08.788
instead of just a simple list of times.

00:13:08.789 --> 00:13:11.228
And I want support for more puzzles, of course,

00:13:11.229 --> 00:13:12.548
not just the simple cubes,

00:13:12.549 --> 00:13:14.588
but as I progress learning these puzzles,

00:13:14.589 --> 00:13:18.068
I want to have Emacs supporting me for this.

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

00:13:22.429 --> 00:13:26.628
And this concludes the talk.

00:13:26.629 --> 00:13:30.909
Thank you very much.