Compare commits

...

389 commits
main ... main

Author SHA1 Message Date
5383aab921
Add Syncthing to software I use
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-05-03 11:38:28 -04:00
36dbf36a55
Charades variant
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-27 13:31:10 -04:00
784c17e53a
Go back to upstream Gokarna now that my Nu HTML checker fixes have landed
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-24 21:36:12 -04:00
5686e987ea
Update theme
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-23 11:30:35 -04:00
4f1982181a
Revert "Move Gokarna fork to exogit"
This reverts commit ded0bc2908.
2024-04-23 11:28:01 -04:00
4c420cc671
Correctly tag it
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-20 02:30:07 -04:00
44a33aa4ff
New story I guess
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-20 02:29:05 -04:00
7d9576b389
Fix typo in footer quote
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-18 19:27:05 -04:00
08b458b803
Feeling embarrassed and defeated, your BMI slinked away, never to be seen again.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-17 23:40:00 -04:00
c6753e9fc4
Don't open shell as postgres user then open psql console but do it in one command
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-13 17:11:01 -04:00
e047a9ee72
Explain that the billions stories used no AI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2024-04-13 09:54:05 -04:00
b8c8341497
Explain billions name
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-13 00:13:40 -04:00
18be396fbe
Billions and billions served
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-13 00:12:53 -04:00
13215b328c
Remove Kevin game mention
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-11 22:50:40 +00:00
264a608d5e
Add xkcd Randall's last name
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-10 15:18:57 -04:00
0c643a09e4
Add Venus and eclipse picture
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-10 15:18:23 -04:00
6d16a74612
Kevin photographed a fox but I won't put the photo on this website
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-09 22:17:08 -04:00
d7167f7481
Rooster and black orb
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-08 22:15:52 -04:00
e5e2cd51c3
Don't use fancy adjectives twice
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-08 21:20:21 -04:00
05175506fe
Mention Venus photo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-08 21:19:43 -04:00
e4b1398e78
ECLIPSE!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-08 21:17:56 -04:00
687b12d49d
Add description to Kung Fu Panda 4 post
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-08 20:44:13 -04:00
ded0bc2908
Move Gokarna fork to exogit
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-07 15:15:06 -04:00
a640ac6afd
Remove image flag from previous puzzle
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-02 20:31:40 -04:00
7d4cddedfe
Add geometry tag
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-02 20:19:34 -04:00
6229189b90
April Fools' Day puzzle and origami solutions
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-02 20:18:54 -04:00
96904a9973
Revert "Make April Fools' Day joke reproducible by adding it to CI"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This reverts commit 66d63a1ff8.
2024-04-01 19:41:11 -04:00
66d63a1ff8
Make April Fools' Day joke reproducible by adding it to CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-01 15:34:49 -04:00
5a52556692
Add blank.exozy.me to websites
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2024-04-01 14:07:27 -04:00
3b2a5fde18
Fix an actual typo like really this is a typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2024-03-29 17:19:34 -05:00
438241b45f
Fix wording of Short Story series notes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-29 17:15:33 -05:00
629c8d5176
Use Forgejo icon from simpleicons.org instead of the one I made shortly after Forgejo was created
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-29 16:40:53 -05:00
773a76ee4e
Remove Codeberg, Peertube from home page, delete icons
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-29 01:53:07 +00:00
cd9c07bca1
Fix typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-28 14:03:33 -05:00
27f7354824
Delete the "fun" tag
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
The reason this tag exists is because I used to have a subdirectory in my website called /fun (now most of it is in /about with a bit in /projects). Unfortunately, this tag got *really* overused, for instance the 汉字 post is tagged "fun" for no good reason. It's now the most common tag of my blog. This tag is very useless and more specific tags like "humor" or "satire" should be used instead.
2024-03-28 13:56:06 -05:00
09ef522549
Short Story 4
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-28 13:49:54 -05:00
b5d32de520
Add guest post tag to SS3
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-28 12:01:10 -05:00
d84d852ce6
Modify checker script for SS3
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-28 11:41:21 -05:00
e5a45460f9
Unkevin
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-27 22:12:57 -05:00
1dc138ca68
Add series tags
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-27 22:04:22 -05:00
ab9494c2ba
Short Story 3
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-27 21:46:04 -05:00
74fe323503
Add author field in RSS feed by setting params.author.email to "Anthony Wang"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Revelant line in Hugo: 54a8f0ce21/tpl/tplimpl/embedded/templates/_default/rss.xml (L65)

Interestingly, the RSS 2.0 spec says the author field should be an email address: https://www.rssboard.org/rss-specification#ltauthorgtSubelementOfLtitemgt
2024-03-27 14:43:29 -05:00
90af9c3623
Deadlines quote
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-26 17:03:33 -05:00
7f89196f4a
Fox stereotypes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-26 14:00:21 -05:00
6571986b3d
Kung Fu Panda 4 review
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-26 13:57:49 -05:00
582b5cf8aa
EA quote
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-26 10:40:40 -05:00
587587733f
Mark Twain truth and fiction quote
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-25 22:29:57 -05:00
ce8ef1aeb5
Add notes about systemd-sleep and docs
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-22 12:25:20 -04:00
6d201e7456
Solve the bug with ONLY a single systemd service!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-22 11:52:57 -04:00
97c53c9fd0
Add note about S2Idle and S3
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-21 19:54:58 -04:00
ddf798fdb4
Weird fprintd errors, fprintd is the one disabling persist
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-21 19:46:02 -04:00
187d538193
Explain 444 perms, fix wording
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-21 19:21:22 -04:00
c7eef030e2
Add slightly better USB persist solution
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-21 19:11:32 -04:00
2be568475b
Might eat your kangaroo.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2024-03-20 14:46:09 -04:00
08e12c8ad3
Fix typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-20 14:22:20 -04:00
358732f4bd
Recompile fprintd to decrease timeout
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-20 14:18:54 -04:00
42992f35e3
The bug is a bit related to Plasma 6 I guess
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-19 22:24:04 -04:00
96244691a2
Ask about if there's a better solution for the fingerprint bug
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-19 21:21:20 -04:00
31fcb9c541
Plasma 6 Fingerprint Bug
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-19 21:15:14 -04:00
d265c902ec
Publish KASPGTW
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2024-03-17 00:19:01 -04:00
a770d2e9dd
Add warning to Killed By Your Mind story
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-12 00:55:06 -04:00
eb44d675a9
More strongly condemn an invasion
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-11 14:23:09 -04:00
b12cb07b6f
More adjectives yay
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-10 16:33:47 -04:00
8bc0cebd7b
Fix typos in KASPGTW
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-10 16:31:29 -04:00
aec03a3360
Fix more broken links
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-10 16:13:19 -04:00
083fc0bb88
Move LadueCS to bottom of projects list since I'm no longer involved
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-10 16:04:56 -04:00
5184fe2a91
Remove broken link to Totally Reprod Arch, add date for xy.xvm.mit.edu based on last
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-10 16:03:45 -04:00
bc3d14039e
Move IRL friends to top of list
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-10 16:01:26 -04:00
df48a1a21a
Software page: Link to dotfiles repo instead of individual links to config files
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-10 15:57:06 -04:00
cb5ef762a0
Update theme
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-09 15:58:31 -05:00
daa094b7fb
Switch to own fork with Nu HTML Checker fixes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-09 20:52:15 +00:00
340413c6e4
Update theme
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-09 15:20:09 -05:00
7829bb3cf3
Revert "Don't wrap {{ .Content }} in p tags"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This reverts commit 09957b7e11.
2024-03-09 15:17:05 -05:00
983f98f2cd
Revert "Manually apply "Fix JS error when ShowBackToTopButton is false" to overrided post.html template"
This reverts commit 22d34b82a7.
2024-03-09 15:17:03 -05:00
482f3d1fc4
Fix typos in KASPGTW, add note about ending
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-09 00:05:36 -05:00
ef9897c786
Comment out junk
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-07 16:21:07 -05:00
69d774d92b
Move shell logic outside of short-story.py
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-07 16:20:00 -05:00
195b9cf859
Improve intro to KASPGTW
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-07 12:15:08 -05:00
a3c3cb1296
Use some more interesting words
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-06 22:37:04 -05:00
605eee0686
Print unused word list
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-06 18:56:44 -05:00
e5f39adbe6
Add Wu
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-06 18:46:09 -05:00
e399274ba7
Improve short-story.py script
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-06 12:26:09 -05:00
967dae2561
Fix typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-06 12:18:10 -05:00
05ed0c54c6
Swap weekend/year
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-06 10:03:01 -05:00
01111c9015
The snow was inside too
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-06 00:02:35 -05:00
b634e6de6e
Fix typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-05 23:56:28 -05:00
5137353623
Fix ending
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-05 23:53:09 -05:00
e2681a60aa
Note author of story
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-05 23:51:51 -05:00
2ff6843a3a
Short story 2
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-05 23:51:24 -05:00
c3030893f3
Origami puzzle
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-04 14:15:13 -05:00
172aca42f5
Link to anime girl soy sauce Chinese Wikipedia page
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-03 14:47:39 -05:00
81cb2085ec
Add Hex Color Clock to websites
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-01 00:08:25 -05:00
142c361cb0
Change "post-credits scene" to "ending"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-29 18:58:34 -05:00
586e855346
A useful command
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-29 18:56:32 -05:00
269f665d9c
Replace nihilist with a more accurate word
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-27 05:58:41 +00:00
eb8ada84f3
Add star sign joke at the very end of story
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-26 23:52:24 -05:00
e31518174b
List more features of PulseAudioDB
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-25 20:15:19 -05:00
06eb5e455f
Blazingly fast 🚀
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-25 19:57:53 -05:00
a524b7e9e0
PulseAudio network transparency
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-25 19:51:47 -05:00
32560ebd9d
PulseAudioDB
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-25 19:49:32 -05:00
060256369b
More wording improvements
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-22 23:49:20 -05:00
e353e51de8
Fix wording
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-22 23:47:52 -05:00
1cd3171721
Kawaii Anime Schoolgirls Play Global Thermonuclear War
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-22 23:12:32 -05:00
b412479a2e
Use \[ \] instead of $$ $$ for KaTeX display math mode
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-22 11:46:03 -05:00
a36c7379d0
"People never quit Emacs"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-21 23:35:03 -05:00
27299fde4d
Fix word count for wasting time line in Pi poem (thanks cnmne!)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-21 14:58:22 -05:00
46f4639d88
Fix phenomena typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-19 22:06:36 -05:00
99be168a8d
Single file quote 2024-02-19 22:06:23 -05:00
109b2213aa
Add periods to end of display math mode equations
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-19 15:14:41 -05:00
218ea7238c
Fix typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-19 17:09:25 +00:00
55ea57dfd2
Force rebuild
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-19 17:05:03 +00:00
afd79a1a1c
Remove extra closing paren
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2024-02-19 17:03:19 +00:00
9a312a48c9
Fix wording
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-18 23:29:35 -05:00
d5e70abf06
The intuitive explanation is misleading
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-18 23:26:00 -05:00
b1bcee4927
Rename post
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-18 23:24:31 -05:00
a57254ea90
Floats are weird
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-18 23:22:33 -05:00
8e9116a7a0
Add tags in Chinese because why not
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-14 14:49:49 -05:00
22d34b82a7
Manually apply "Fix JS error when ShowBackToTopButton is false" to overrided post.html template
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-14 01:33:09 -05:00
45c22b5d9c
Update gokarna theme
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-14 01:29:21 -05:00
95c7bf2e20
More quotes I guess
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-10 22:32:22 -05:00
5b121e2814
DUMB PHYSICS ENGINE
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2024-01-29 19:40:52 -05:00
cc48c48d81
Add GCC limerick to quotes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-25 16:59:55 -05:00
879352dcb4
854 Rap
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-24 22:10:47 -05:00
a61a201d98
Update Gokarna theme
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-24 12:00:00 -05:00
de13cea9c9
Add another resource about beta distributions
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-23 22:51:28 -05:00
0ca25f4241
Asian Bayesian 2
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-23 15:59:04 -05:00
2798847281
Revert "Redraftify Killed by your mind story"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This reverts commit b1694aa3b1.
2024-01-22 01:43:05 -05:00
43d8a33fcb
publish MASEEH
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-22 01:42:43 -05:00
47ad98d353
Vacation photos!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-22 01:40:08 -05:00
2e07d2239d
Typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2024-01-20 20:31:00 -05:00
93b30ae588
Fix wording again because I'm bad at words
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-20 20:30:38 -05:00
326212c689
Fix weird wording in Calumny story
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-20 20:29:42 -05:00
1db5e8c47c
Add some more sarcasm
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-20 14:40:13 -05:00
f4716e4790
CALUMNY
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-20 14:37:04 -05:00
33bf717d86
Small edits to Miasma story, change "a sequel" to "the sequel"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-20 13:53:13 -05:00
bd2793c2f6
Change /srv/http/pages to /srv/http
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-20 11:13:38 -05:00
f875dcf80a
MIASMA
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2024-01-20 02:14:44 -05:00
e6e072955a
Make sure each list has a sentence before it, cleanup
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-19 21:49:13 -05:00
a5cc1e4d07
Note that this is retelling of an existing joke
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-16 21:29:23 -05:00
96b1d8f28a
Change wording for ending
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-16 21:22:06 -05:00
da22fbc757
MASEEH
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-16 21:21:17 -05:00
64330de88b
Wakuwaku dried pork paper coincidence
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-16 20:12:56 -05:00
49b3d2d9e5
Note that the shint extremal graph theory handout contains another proof of the theorem
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-15 18:00:26 -05:00
615a3c88a1
Add link to 18.225/18.217 OCW to extremal graph theory post
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-15 16:07:46 -05:00
493d9a74a1
Add link to short handout about extremal graph theory
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-14 18:31:55 -05:00
0b5970d483
Add link to Alek's post of the same graph theory proof
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-14 17:36:09 -05:00
09957b7e11
Don't wrap {{ .Content }} in p tags
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Revert this once https://github.com/526avijitgupta/gokarna/pull/210 is merged
2024-01-14 13:44:33 -05:00
0f4ea1b794
Extremal graph theory
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-14 12:54:54 -05:00
b7112473d6
Publish the old hangry guide to MIT dining
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-12 21:20:09 -05:00
859b4f8535
Link to repo in about page since it's no longer in the header
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-11 13:59:37 -05:00
13f72e74e6
Add 3 very old drafts from my old blog
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-11 13:58:20 -05:00
9d079a38e0
Add copy of hangry guide to MIT dining
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-11 13:48:40 -05:00
11ba8a93bc
Evil mode dodecahedron GIF
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-11 00:54:59 -05:00
0ba496e4e2
Nexthouseball
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-11 00:14:42 -05:00
43b1b30171
Sentence guessing game
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-10 23:53:53 -05:00
14cfba21eb
Update about page
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-10 16:22:07 -05:00
58ad9378b3
Link to xkcd 137 Dreams on fiction page (it's already on the quotes page)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-09 16:12:39 -05:00
da6cd1e8ec
Attribute quotes to me and ChatGPT instead of characters in Pilogy
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-09 16:10:45 -05:00
2f240764ca
Banish rawhtml shortcode, instead write shortcodes for katex, sagecell
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-06 22:15:42 -05:00
185411bbaa
Fix typo in Asian Bayesian post
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-06 22:06:13 -05:00
b62567ac00
Remove low quality quotes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-05 20:34:12 -06:00
f7188c3912
Purge README.md because why not
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-05 20:20:13 -06:00
4eedc6c0bf
Delete languages page because I don't even know half of those languages at all
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-05 20:13:47 -06:00
6a1bd601bd
Logic puzzle
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-05 20:13:37 -06:00
0a54a08e19
Write details shortcode so Markdown and quotes inside of details tag are rendered correctly
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-05 20:13:08 -06:00
cafbacfd3b
Customize the nav-title using the first portion of the relative URL
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-05 20:12:15 -06:00
8066e4eab3
Remove linux.exozy.me from websites list
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-05 11:59:46 -06:00
6eadaba448
Add default quote, use smart quotes for footer to match rest of site
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-04 22:02:06 -06:00
5f9f1060b0
Put each quote of footer source code on separate line
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-04 21:52:12 -06:00
ac051d0d1d
Replace recommended libre games list with a list of other nice games
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-04 21:45:24 -06:00
177ee249c3
Reword email page 2024-01-04 21:45:15 -06:00
88449df776
I accidentally copied GEB instead of H2G2 to fiction.md in 33c71edaf2, so fix that
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-04 21:39:50 -06:00
898f816960
Add H2G2 and 大话西游 to fiction list
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-04 14:39:58 -06:00
aaede69b90
Use base 2 for refreshing page joke
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-02 11:05:55 -06:00
737278c270
Note that I don't recommend using waypipe for copy/paste over SSH
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-02 10:58:15 -06:00
c6cbe9f23f
Add ham quote
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-31 16:53:56 -06:00
ec082f8ba0
Revert "Testing"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This reverts commit 6c6edd5e11.
2023-12-29 19:29:36 -06:00
6c6edd5e11
Testing 2023-12-29 19:29:02 -06:00
feb19488c4
Remove homebrew stuff from projects because it's not very impressive or interesting
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-29 19:28:16 -06:00
ed92938311
Move "CC BY-SA 4.0" to new line in footer so it doesn't look like the author of the quote
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-29 19:27:56 -06:00
4e9c6dfd2f
Move random quotes to footer, disable next/prev buttons which collide with footer text
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-29 19:22:44 -06:00
0306f86d79
Remove Git link from navbar to declutter it
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-29 18:15:53 -06:00
926099b13e
Fix some broken links
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-29 17:53:11 -06:00
717ff37e0c
Don't make Hugo generate a mailto link
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-29 17:46:36 -06:00
a47c02b8b7
Draftify even more posts
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-29 17:31:23 -06:00
7208eb8ffb
Draftify some more old or outdated posts
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-29 17:28:50 -06:00
b1694aa3b1
Redraftify Killed by your mind story
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-29 16:59:55 -06:00
bae8e4a89c
Note that the ebooks project predates ChatGPT
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-29 16:47:41 -06:00
e9f871a314
Add more quotes I guess 2023-12-29 16:47:41 -06:00
d9ac42424d
Add SIPB projects 2023-12-29 16:47:41 -06:00
c45bb60e7a
Remove some quotes I don't like 2023-12-29 16:47:41 -06:00
33c71edaf2
Split books into nonfiction/fiction, move Antichamber to #1 game 2023-12-29 16:47:41 -06:00
eb5170bbf1
Fix exoring links 2023-12-29 16:47:41 -06:00
258ad1ec93
Add note about OCAPs 2023-12-29 16:47:41 -06:00
318813636a
Add Nathan's website to other websites you should check out 2023-12-29 16:47:41 -06:00
4d462f29c8
Forge federation design discussion 2023-12-29 16:47:41 -06:00
9dc8adc2f4
Returning to forge federation 2023-12-29 16:47:41 -06:00
97c826a792
Use original wording of gauge quote 2023-12-29 16:47:41 -06:00
e75488a9bd
Add more links and purple comet story
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-20 05:16:26 +00:00
665af3a187
Asian Bayesian
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-20 05:07:00 +00:00
4d7b252467
Fix wording for LLMs note in Dead Pixels
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-20 00:28:34 +00:00
8d477fa48b
Add LLMs note, source of problem, to Dead Pixels post
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-20 00:27:54 +00:00
9a534a1c23
Undraftify Killed By Your Mind story
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-19 21:35:41 +00:00
ab2869bde6
Dead pixels
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-19 21:35:09 +00:00
a8124987ac
Fix link to fish dotfiles, add Thunderbird, mpv, and Element to software I use
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-19 00:45:48 +00:00
db4aaefda1
Fix filename typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-18 05:45:12 +00:00
0638b1cae4
Move the Elon Musk AInion article to bonus content, replace with a better bidet instead of Biden article
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-10 04:00:48 +00:00
99c9e54705
Improve some puzzles
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-09 19:20:25 +00:00
a
5bc242687b Add mayonnaise-frosted pie quote
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-09 18:56:57 +00:00
1cfddbdd48
Fix wording in final paragraph of spelling reform
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-06 00:27:59 +00:00
fe5f22bdad
Slightly simplify spelling reform clause gadget, improve wording, add more examples
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-06 00:20:30 +00:00
22634f8a07
Add procrastination quote to quotes list, add better quotes to homepage
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-05 20:34:21 +00:00
d7ca2762ad
Link to utilities page in about page
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-05 20:03:30 +00:00
eb163f6747
Rewrite puzzle
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-12-05 19:59:02 +00:00
86785c80b5
Fix typo in microwave story
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-28 01:48:44 +00:00
8bd87cdbf0
Testing Woodpecker CI yet again
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-23 23:18:48 +00:00
14fcb2fb30
Change deprecated pipeline: to steps: in .woodpecker.yml
Some checks failed
ci/woodpecker/manual/woodpecker Pipeline failed
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-23 22:47:53 +00:00
c15368156b
Remove manual clone stage since woodpecker-agent-sudo caches by default now
Some checks failed
ci/woodpecker/manual/woodpecker Pipeline failed
2023-11-23 22:37:58 +00:00
c79ab35a5e
Update gokarna theme
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-23 22:23:35 +00:00
bd5ccc5703
Some random ramblings about second-round simplified characters
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-15 17:44:29 +00:00
173cdbed92
Fix typo in hardware list
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-11 20:32:57 +00:00
20d5303451
Add MIT VPS and Dell XPS to hardware list
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-11 20:31:46 +00:00
5bc9617dbb
Fix more typos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-09 17:51:04 +00:00
3578324239
Fix another small typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-08 01:19:02 +00:00
ce5ee7f336
Fix more typos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-07 19:19:20 +00:00
12befc6e63
Fix typos in NP hardness post
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-07 19:16:40 +00:00
f44c0255c1
Add note at end about general style of NP-hardness proofs
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-07 18:16:23 +00:00
71129c589f
Undraftify the spelling reform post
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-07 18:12:46 +00:00
ad3279b5c5
Spelling reform is NP-hard
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-07 18:12:07 +00:00
726b47f4b5
最抽象的汉字
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-07 04:43:07 +00:00
eac035fa5e
Minor additions to the windy "Why the Name Saya" post
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-07 01:58:16 +00:00
d94ec7c015
New (long!) draft post about why the main character of the halloween story is named Saya
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-06 20:01:07 +00:00
73c38c18ad
Fix another typo in halloween story
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-02 22:11:55 +00:00
8b556abab7
Unpublish the exozyme tricks post because it sounds too much like a hyped up ad
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-31 02:48:09 +00:00
251de135e3
Fix typo in halloween story
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-27 21:17:31 +00:00
527488e827
Add halloween 2023 story
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-27 21:15:33 +00:00
27b1b9c445
Fix typo in ethics post
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-26 17:46:35 +00:00
325d3c783c
Ethics test for AIs
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-26 17:45:00 +00:00
2f4665172f
Arknights review draft
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-23 01:16:24 +00:00
e842cf3f0a
Add lossy audio post draft
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-22 23:54:18 +00:00
7c46a079b8
Add solve date to leaderboard
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-21 17:51:33 +00:00
9c378e96ba
The puzzle has been solved!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-21 17:50:55 +00:00
dcc24b1d42
Update theme 2023-10-21 17:50:36 +00:00
1615243046
Add CSS Abuse part 3 to websites, update theme
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-10-09 03:05:24 +00:00
1e90092fbd
Add Intricacy to recommend libre games
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-29 15:35:33 +00:00
d908e48976
All Unicode on One Poster (fail)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-13 01:58:11 +00:00
387971ef20
Make the 100 posts post a draft cause it's not true technically
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-03 16:29:31 +00:00
e0c49b7411
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-08-01 02:19:53 +00:00
20a0eb785f
Replace some non-ASCII characters
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-30 23:46:50 +00:00
b732b0bf87
Increase homepage quotes to 16
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-30 23:26:36 +00:00
8b211cd467
Fix links
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-30 23:17:49 +00:00
4063c17654
How I Use LLMs for Writing Fiction
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-30 23:16:31 +00:00
92451948be
Add note that the Wayland scaling post is outdated
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-29 22:47:18 +00:00
ffe24b72aa
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-27 03:03:15 +00:00
3a34599048
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-26 03:11:05 +00:00
c83112eeb6
Update xtexx.ml to xtexx.eu.org
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-20 14:48:28 +00:00
844cd12a35
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-15 00:45:36 +00:00
767b3812cc
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-14 03:59:27 +00:00
c7ff72f596
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-14 03:37:48 +00:00
985d05270c
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-14 03:27:13 +00:00
0212d540a0
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-14 03:27:02 +00:00
b7c80b5ee1
Remove extraneous dash
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-11 17:00:21 +00:00
1611199e4c
Remove link to code-server config
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-10 15:27:09 +00:00
d40e89ac62
Add some quotes from that unpublished story
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-09 04:34:39 +00:00
694f81429a
Remove useless stuff from software page
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-08 20:59:08 +00:00
5e0c4f6195
Add https://awestover.github.io to friends.md
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-08 15:32:07 +00:00
f74b9e3150
Add friends.md
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-08 15:28:27 +00:00
e1b25881da
Add weird quotes to main page
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-08 15:16:04 +00:00
41c0ffde4c
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-08 03:52:57 +00:00
224f2b7132
Publish abusing systemd-nspawn with nested containers post
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-07 14:55:42 +00:00
647482456b
Robert Tarjan the algorithm man
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-06 23:03:27 +00:00
85a7e257c0
I don't like musical instruments
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
2023-07-06 18:33:56 +00:00
0550aa5067
Revert "Specify /tmp/hugo_a as cache dir so build succeeds"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/manual/<no value> Pipeline was successful
This reverts commit 10dc10d8bf.
2023-06-26 17:00:29 +00:00
b499371ab7
Update theme
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-25 20:53:44 +00:00
4ba4c3cf4d
Add link to that fedi post about Pallas's cats in my about page
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-22 19:49:25 +00:00
0f632d676b
Fix description for utilities page
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-22 19:47:02 +00:00
5055ed689d
Add rgbtemp to utilities
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-22 19:45:52 +00:00
18d2835e68
Add some exozyme utilities to utilities page
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-22 19:42:18 +00:00
329136aa24
Add utilities page to projects
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-22 19:40:39 +00:00
e748b1ad2a
Remove httpify from websites because it's not actually a website
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-22 19:34:24 +00:00
046b816195
Add log repo to competitive programming projects, add httpify to websites
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-22 19:33:14 +00:00
eb769dbe30
Update theme
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-22 16:34:44 +00:00
47a13e3349
Add descriptions to all project pages, add weird websites list
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-22 16:29:51 +00:00
60200a0918
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-21 21:52:05 +00:00
a79736d645
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-21 21:26:26 +00:00
08563c72f3
Use archive.org version of Ben Qi Wikipedia link since the article was deleted
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-20 16:37:39 +00:00
5e45f8c0f5
Update theme
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-14 20:30:20 +00:00
cd11808eb3
Update content/about/quotes.md
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-10 01:08:31 +00:00
a2469a7e99
Add threads joke to quotes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-06 18:31:54 +00:00
89d38c9e57
Clean up quotes page, add link to fortune.exozy.me
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-05 19:08:56 +00:00
0fd8a60dea
Add even more bad quotes by me
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-30 18:25:55 +00:00
b94cd190ed
Add some of my greatest quotes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-30 03:47:05 +00:00
10dc10d8bf
Specify /tmp/hugo_a as cache dir so build succeeds
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Looks like Hugo will never fix https://github.com/gohugoio/hugo/issues/7391 😭
2023-05-30 03:36:43 +00:00
feec27ba72
Add longer rail gauge rant quote
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-30 03:33:26 +00:00
8329b1fa2b
Add more stabyourself.net games
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-14 03:57:28 +00:00
462b1b4e84
Add Not Tetris 2 to games
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-09 23:24:09 +00:00
3d38e9cf32
Add Ennui abridged version 2023-04-24 03:51:23 +00:00
9c246aa61f Fix typo on quotes page
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-22 20:34:35 +00:00
e1ddde4cc4 Add copying quote
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-22 20:33:45 +00:00
5405ce88de
Test Woodpecker CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-19 20:33:52 +00:00
619ccb336d
Update Gokarna theme
Some checks are pending
ci/woodpecker/push/woodpecker Pipeline is pending
ci/woodpecker/manual/woodpecker Pipeline was successful
2023-04-19 20:08:09 +00:00
d693ae5859
LLM humor
Some checks are pending
ci/woodpecker/push/woodpecker Pipeline is pending
2023-04-19 20:07:31 +00:00
925e8e8646 Fix pilogy link 2023-04-09 21:39:18 +00:00
3aa1c5076b Add some pilogy quotes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-07 00:50:35 +00:00
1d7ceca84f Ben -> Ben Qi
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-05 03:32:27 +00:00
8b6bc3c38e shorten stuff
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-05 03:25:47 +00:00
2fee582b67 reword some stuff
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-05 03:19:34 +00:00
ccfec99f14 Yay boredom!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-05 03:02:14 +00:00
369488603f
Make Unfactoring a draft
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-03 21:14:13 +00:00
aed2fd76f6
Fix typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-03 16:45:38 +00:00
71bc23d09e
Petroleum
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-03 14:51:57 +00:00
69e84eb88f
Unfactoring numbers
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-19 01:07:58 +00:00
b8d88950cf
Add more tags
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-10 04:13:33 +00:00
70861beeae
Some small fixes and improvements 2023-03-10 04:09:39 +00:00
77aea7f04f
Add link to Ben Qi's Wikipedia page
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-10 03:12:48 +00:00
b12275c290
Ennui!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-10 03:12:19 +00:00
3ffcf2f6ae
Bump theme
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-09 02:51:30 +00:00
1fe3f0e1e7
Fix broken matrix.org links
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-06 21:21:23 +00:00
6884f94444
Continuity for beavers
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-06 01:10:24 +00:00
76ec73c5e2
Douglas Adams!!!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-03 01:41:53 +00:00
5733ff7b8a
Make the Hitchhiker's post a draft
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-03 01:28:45 +00:00
ac7a10dd99
And some other stuff
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-02 04:26:06 +00:00
8348060759
Revert "Abusing systemd-nspawn"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This reverts commit 172914454f.
2023-03-01 04:59:01 +00:00
4672ed271d
Actually add Abusing systemd-nspawn post 2023-03-01 04:58:46 +00:00
172914454f
Abusing systemd-nspawn
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-01 04:58:18 +00:00
49386b479f
Remove "Baku" from last sentence to make ending smoother, and replace steppe with desert which is more accurate
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-26 22:00:13 +00:00
37a2061c22
Blender joke
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 16:47:31 +00:00
4ed7a3c74d
Azerbaijan isn't a central Asian country
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 16:36:36 +00:00
f69997576f
Clarify poker term
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 16:15:33 +00:00
b306e77617
Uncapitalize Poker
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 06:39:07 +00:00
f46a40f6f3
More clarifications
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 06:31:20 +00:00
e74ddfa979
Yay, more typo fixes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 06:16:57 +00:00
d8b4dc52a3
Add tip to Beavers to look up Pallas's cats
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 06:15:17 +00:00
6f07b29671
More typo fixes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 06:12:39 +00:00
a0a7b459fb
Fix more typos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 06:10:51 +00:00
c6c266ddd6
Minor tweaks to improve clarity
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 05:32:50 +00:00
45c938a450
Fix typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 05:25:22 +00:00
d8058b6310
Azerbaijan
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-25 05:24:36 +00:00
4333b0724c
Add ping @ quote
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-23 20:20:30 +00:00
ffab5946a0 Fix wording in Beavers
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-23 05:50:23 +00:00
421df2e24c
Actually update name of main character
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-22 18:01:19 +00:00
a033f683b2
Add a draft of an unpublished article about music
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-22 02:54:55 +00:00
b1eaf926a0
Update name of main character in Beavers
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-22 02:47:57 +00:00
e0cd49ec65
Publish Beavers
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-21 20:58:42 +00:00
e5d7f3cd66
BEAVERS!!!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-21 15:45:15 +00:00
780e8540ff
Remove Liberapay from main page
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-18 22:01:29 +00:00
8c5b6fe993
Manifest Destiny often times ends in dysentery
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-16 02:57:19 +00:00
c322af5433
Add robotfindskitten to libre games
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-15 02:09:06 +00:00
750cf5e51c
Mention that I contributed a Chinese translation to AAAAXY and move it up to 2nd place!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-08 21:48:32 +00:00
7835802b10
Minor tweaks
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-08 05:53:22 +00:00
2edd2e0c48
Actually publish C2S post
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-08 05:27:46 +00:00
4951e2e4ee
We're Missing Half ActivityPub's Potential!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-08 05:27:18 +00:00
e68b96adfa
Remove trailing . on ActivityPub post description 2023-02-08 04:37:21 +00:00
ebc9fde0c2
Reorder favorite games list by moving Majora's Mask back several places
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-07 20:25:51 +00:00
8c71408fb8
Add Python benchmark
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-07 04:37:41 +00:00
216eb8d0c9
Add more libre games and a detailed review for AAAAXY
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-05 06:14:02 +00:00
a0ce27837b
Add AAAAXY to favorite games
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-04 20:04:39 +00:00
1c5912a74a
Add AAAAXY to libre games
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-04 00:19:01 +00:00
27798858d5
More background and explanation for some unclear sections in the AP guide
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-01 19:37:30 +00:00
0b9d826084
Actually add AP spec link
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-01 19:34:24 +00:00
9d6beb05c3
Add another joke to AP post
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-01 19:32:28 +00:00
71deeb9bbc
Remove unneeded line in HTTP sig verification code
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-01 19:03:46 +00:00
8b59f21073
Fix typos in server.py
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-01 18:34:02 +00:00
fa4bcf2ab3
Make final implementation correctly handle follower addressing
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-31 00:29:57 +00:00
c58852bf89
Make centipede implementation get username at same place as final implementation
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-31 00:27:00 +00:00
05f18849cd
Add Delightful ActivityPub Development to AP resources collection
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-29 02:55:39 +00:00
07755e2751
Clarify activities and actor model
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-29 02:39:02 +00:00
5853300945 2023-01-28 "Tell 5 of your friends about Quote of the Day, and receive a FREE Quote of the Day!!!"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-28 17:54:26 +00:00
85ae17bcfb 2023-01-27 "A conclusion is simply the place where someone got tired of thinking."
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-27 19:08:08 +00:00
d55be1dc99 Fix aks typo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-27 02:01:41 +00:00
56d98ecaac
Add water bottle pentakis dodecahedron
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-26 20:41:22 +00:00
3c5e06984c
Fix messed up formatting on quotes page
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-26 20:36:33 +00:00
c86475bef2
Add quote "Never surrender to fascist zebras to cosplaying as unicorns."
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-26 20:35:42 +00:00
3a34ad2baa
2023-01-26 "The universe tends toward maximum irony. Don't push it."
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-26 20:31:31 +00:00
08e5ccfdfa
2023-01-25 "An idiot with a computer is a faster, better idiot." 2023-01-26 20:30:51 +00:00
73da844b22
Add note about quote of the day
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-26 20:29:21 +00:00
5a628e34ac
2023-01-24 "Think of how stupid the average person is, and realize half of them are stupider than that."
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-26 20:28:46 +00:00
831d2f1d2e
Beating the time limit
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-25 02:26:04 +00:00
4469247f48
Explain why we shouldn't have a single centralized server, link to Fuwuqi in the resources section
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-23 23:30:28 +00:00
bb5be0079a
More humor
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-20 03:45:22 +00:00
f7cbfab14d
Revert "style: add trailling stash to baseURL as mandated by docs"
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This reverts commit fb7201b6a5.
2023-01-20 02:17:10 +00:00
67f570f5c9
Add more comments to sample AP code
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-19 23:45:44 +00:00
c66355280e
Set up static files so add more interactive bits to guide
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-19 23:31:41 +00:00
c8c678150b
Fix even more typos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-19 23:14:56 +00:00
74c1592472
Fix some more typos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-19 23:14:27 +00:00
12a09cf56b
Typo in post name
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-19 23:07:21 +00:00
6148beb872
ActivityPub Eats Your Brain!
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-19 23:07:01 +00:00
77f3a60701 Add Fuwuqi to fediverse projects
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-01-18 21:37:39 +00:00
db9c5ebe84 Merge pull request 'Add trailling stash to baseURL as mandated by docs' (#3) from abheekd/website:main into main
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Reviewed-on: a/website#3
2023-01-13 17:25:57 +00:00
195 changed files with 4290 additions and 205 deletions

View file

@ -1,15 +1,6 @@
clone:
git:
image: fish
commands:
- cd ~/Code/website
- git pull https://git.exozy.me/a/website.git
- git submodule update
pipeline:
steps:
build:
image: fish
commands:
- cd ~/Code/website
- hugo --minify --cleanDestinationDir --destination /srv/http/pages/a
- echo eW91IGZvdW5kIGl0IQo= | base64 -d > /srv/http/pages/a/holy-grail
- hugo --minify --cleanDestinationDir --destination /srv/http/a
- echo eW91IGZvdW5kIGl0IQo= | base64 -d > /srv/http/a/holy-grail

View file

@ -1,3 +0,0 @@
<!--you found it!-->
# website
Some random website

View file

@ -1,4 +1,4 @@
baseURL = 'https://a.exozy.me/'
baseURL = 'https://a.exozy.me'
languageCode = 'en-us'
title = 'Some Random Website'
theme = 'gokarna'
@ -34,28 +34,19 @@ theme = 'gokarna'
url = '/index.xml'
pre = '<span data-feather="rss"></span>'
weight = 5
[[menu.main]]
identifier = 'git'
name = 'Git'
url = 'https://git.exozy.me/a/website'
pre = '<span data-feather="git-pull-request"></span>'
weight = 6
[params]
avatarURL = '/dodecahedra/logo.webp'
avatarSize = 'size-xl'
description = '(+ (This subdomain) (Ordinal n) (! off) (Element 39) (Wide area network) (Prefix for billion))'
accentColor = '#00dd42'
footer = '🎉 Made with Hugo and frustration! - CC BY-SA 4.0'
togglePreviousAndNextButtons = 'true'
socialIcons = [
{name = 'email', url = '/about/email', rel = 'me'},
{name = 'forgejo', url = 'https://git.exozy.me/a', rel = 'me'},
{name = 'codeberg', url = 'https://codeberg.org/xy', rel = 'me'},
{name = 'mastodon', url = 'https://social.exozy.me/@a', rel = 'me'},
{name = 'peertube', url = 'https://tube.exozy.me/a/a/video-channels', rel = 'me'},
{name = 'matrix', url = 'https://matrix.to/#/@a:exozy.me', rel = 'me'},
{name = 'archlinux', url = 'https://aur.archlinux.org/packages/?K=dodecahedron&SeB=m', rel = 'me'},
{name = 'codeforces', url = 'https://codeforces.com/profile/Ta180m', rel = 'me'},
{name = 'liberapay', url = 'https://liberapay.com/xy/', rel = 'me'},
]
[params.author]
email = 'Anthony Wang'

View file

@ -4,13 +4,13 @@ type: page
---
a sentient dodecahedron.
some random person.
learning.
sleeping with 1/3 probability.
[coding](/projects).
[projecting](/projects).
(idk what to put here).
@ -18,33 +18,33 @@ enjoying my life in St. Louis, Misery (er... Missouri).
crafting [dodecahedra](/projects/dodecahedra).
[wasting time](games) the most efficient way possible.
[wasting time](games) as efficiently as possible.
trying to master [algorithmic wizardry](/projects/competitive-programming).
building a [community](https://exozy.me).
doing random stuff.
violating the [Discord](/posts/dont-use-discord/) TOS daily.
writing probably very useless [programs](/projects/utilities).
pretending like I know [$SOME_RANDOM_PROGRAMMING_LANGUAGE](languages).
pretending like I know $SOME_RANDOM_PROGRAMMING_LANGUAGE.
trying to find time to actually read real [books](books).
trying to find time to actually read [real](nonfiction) [books](fiction).
making code forges [talk to each other](https://nlnet.nl/project/Gitea/).
making code forges [talk to each other](https://codeberg.org/forgejo/forgejo/issues/59).
creating a compilation of hilariously useless (and fun!) [quotes](quotes).
creating a compilation of lots of hilariously useless [quotes](quotes).
trapped inside [vim](https://www.reddit.com/r/archlinux/comments/hssui9/comment/fych9dq/).
trapped inside [vim](https://a.exozy.me/posts/ainion/#programmers-being-trapped-inside-vim-and-unable-to-exit).
spending hours [copying posts from my five previous blogs](https://git.exozy.me/a/website/issues/1) to this website and too tired to convert the crappy BBCode posts to Markdown.
spending hours copying posts from my five previous blogs to this website and too tired to convert the crappy BBCode posts to Markdown.
permanently incapable of drawing just about anything whatsoever.
you should really check out these [other websites](friends).
faithfully cataloguing my [horde](hardware).
training neural networks to [vomit garbage](https://social.exozy.me/@ebooks/).
training neural networks to be dumb.
looking up images online of chevrotains, jerboas, Tibetan foxes, Pallas's cats, potoos, and alpacas, which you should too, because it will instantly make your day better.
looking up images online of [chevrotains, jerboas, Tibetan foxes, Pallas's cats, potoos, and alpacas](https://social.exozy.me/@a/109657089572833173), which you should too, because it will instantly make your day better.
[breaking Arch Linux machines](/posts/installing-every-arch-package/).
@ -56,13 +56,13 @@ running [docker inside docker inside docker inside docker](https://git.exozy.me/
doing math unironically.
destroying GitHub.
catching [mice](https://mastodon.mit.edu/@xy/111614108714555969).
getting roasted for my terrible [software stack](software).
using a lot of really nice [software](software).
seeding this website with tons of [secret easter eggs](puzzle).
amazed that special patterns in my biological neural networks transcribed into UTF-8 encoded strings in Markdown documents converted into HTML by [Hugo](https://gohugo.io) with the [Gokarna theme](https://github.com/526avijitgupta/gokarna) deployed to [exozyme](https://exozy.me) using [Woodpecker CI](https://woodpecker-ci.org) transmitted over HTTP and displayed on your screen have now created special patterns in your biological neural networks.
amazed that special patterns in my biological neural networks transcribed into UTF-8 encoded strings in [Markdown documents](https://git.exozy.me/a/website) converted into HTML by [Hugo](https://gohugo.io) with the [Gokarna theme](https://github.com/526avijitgupta/gokarna) deployed to [exozyme](https://exozy.me) using [Woodpecker CI](https://woodpecker-ci.org) transmitted over HTTP and displayed on your screen have now created special patterns in your biological neural networks.
still alive.

View file

@ -4,4 +4,4 @@ type: page
---
My email address is the same as this website domain, but with the first dot replaced with an at symbol. If you can, please use PGP with [my public key](https://git.exozy.me/a.gpg).
My email address is the same as this website domain, but with the first dot replaced with an at symbol. If you would like to encrypt the email, [here's my public key](https://git.exozy.me/a.gpg).

19
content/about/fiction.md Normal file
View file

@ -0,0 +1,19 @@
---
title: "Fictional Works That I Like"
type: page
---
You might notice a common theme here.
- **The Hitchhiker's Guide to the Galaxy**: The ships hung in the sky in much the same way that bricks don't. Douglas Adams's other books are also great.
- **The Three-Body Problem Trilogy**: The first book is great, the second is good but with an absolutely insane ending, and the third book is incredible. Some people complain about the author sometimes info-dumping technical and scientific information, but that's one of the things I love about this series.
- **xkcd**: [The Sun](https://xkcd.com/673/) is my favorite. I also like [Dreams](https://xkcd.com/137/).
- **Abstruse Goose**: Like xkcd but better. [The Most Powerful Person in the World](https://web.archive.org/web/20230326160247/https://abstrusegoose.com/606) is my favorite. Sadly, its website is [no longer up](https://social.exozy.me/@a/111552162275963985).
- **Proof of False**: Like Abstruse Goose but better. [Found Application](https://web.archive.org/web/20171102132007/http://proof-of-false.the-user.org/30) is my favorite.
- **A Chinese Odyssey**: The 1995 Stephen Chow two-part film, not the 2002 or 2016 or 2022 films with similar names. It's one of my favorite films of all time.

37
content/about/friends.md Normal file
View file

@ -0,0 +1,37 @@
---
title: "Friends"
type: page
---
As it turns out, my friends are much better at making websites than me.
- https://ring.exozy.me/previous?id=a
- https://ring.exozy.me/next?id=a
- https://awestover.github.io
- https://nathan-sheffield.github.io
- https://tarushii.vercel.app
- https://ersei.net
- https://www.1a-insec.net
- https://xtexx.eu.org
- https://spicecat.github.io
- https://almonds.dev
- https://batsense.net
- https://cjquines.com
- https://codedotjs.exozy.me
- https://aryak.me
- https://slightknack.dev

View file

@ -6,52 +6,34 @@ type: page
## Top 10
1. **Super Mario 64**: Although this game was released in 1996, it's still a blast to play today. Yes, the camera is incredibly janky, and yes, the low-poly models can't compete with the graphics in modern games, but the excitement and joy of exploring an open-world sandbox is something that doesn't age. But what makes this game a 10/10 for me is how the community has kept it alive and thriving over all these years. The mindblowing fastest known speedrun of the game mixes [computer science, physics, and parallel universes](https://www.youtube.com/watch?v=iUt840BUOYA). You can explore the [source code](https://github.com/n64decomp/sm64) due to the meticulous work of reverse-engineers. There are more [ROM hacks](https://sm64romhacks.com/) than you can play in a lifetime. And [pannenkoek2012's amazing videos](https://www.youtube.com/channel/UCMm211NGh4Ls5SAMZJF7E8A) have made Super Mario 64 analysis more scientific than some real scientific fields!
1. **Antichamber**: This puzzle game is like life. It really challenges you to think differently.
2. **SuperTuxKart**: My appreciation for SuperTuxKart over time increases logarithmically. Seriously. For a game completely created by unpaid volunteers, it's absolutely stunning. Since it's free and open source, you can read the source code (it's nicely commented) and see for yourself if the AI is really cheating. SuperTuxKart is also incredibly friendly to modding and addons, and it's easy to contribute to its development. As for simply enjoying the game, it handles local, LAN, and online multiplayer extremely smoothly, so you can get together your friends and have loads of fun.
2. **Super Mario 64**: Although this game was released in 1996, it's still a blast to play today. Yes, the camera is incredibly janky, and yes, the low-poly models can't compete with the graphics in modern games, but the excitement and joy of exploring an open-world sandbox is something that doesn't age. But what makes this game a 10/10 for me is how the community has kept it alive and thriving over all these years. The mindblowing fastest known speedrun of the game mixes [computer science, physics, and parallel universes](https://www.youtube.com/watch?v=iUt840BUOYA). You can explore the [source code](https://github.com/n64decomp/sm64) due to the meticulous work of reverse-engineers. There are more [ROM hacks](https://sm64romhacks.com/) than you can play in a lifetime. And [pannenkoek2012's amazing videos](https://www.youtube.com/channel/UCMm211NGh4Ls5SAMZJF7E8A) have made Super Mario 64 analysis more scientific than some real scientific fields!
3. **Antichamber**: The level design is genius and simultaneously makes no sense at all. That's the point of the game and I love it.
3. **AAAAXY**: You've probably never heard of AAAAXY before, but it's definitely the best puzzle platformer in existence. Think of it like a libre Antichamber meets VVVVVV, except even better. I initally disliked the level design, since the game often tempts you to try brute-forcing with pure platformer skills, but that's actually the genius of the game. Almost always, there's a slicker solution hiding and plain sight, and all you have to do is step back and use your brain, which is often trickier than you think when you're fixated on grinding a tough jump (Except for the room "The Wide Gap", which is pure evil and took me over 100 tries). And the trolling! The game's website warns you to "beware of a minor amount of trolling", and yeah, that's obviously an understatement. I love this game's sense of humor. There are also some nice math references. My only complaint is that the slippery physics make the platforming too hard, while the puzzles are a bit on the easier side. Since I enjoyed this game so much, I contributed back by translating the game to Chinese. The developer is a really cool guy and great to work with! Anyways, the best thing about this game is definitely the name. Second best thing? The [soundtrack](https://divverent.github.io/aaaaxy/music.html).
4. **Minecraft**: Yeah, Minecraft peaked in 2012 and gets worse with every new update. Minetest is allegedly pretty good but I haven't tried it yet.
4. **Baba Is You**: This puzzle game broke my brain. OK, most of the levels are not difficult, but there are some real stumpers out there. What this game does so well is taking a single, simple concept, and turning it into a world of hundreds of levels that don't get old as you play through the game. Admittedly, many of the later levels are hard simply because there are so many different elements in the puzzle all interacting with each other that you can't keep track of them.
5. **Baba Is You**: This puzzle game broke my brain. OK, most of the levels are not difficult, but there are some real stumpers out there. What this game does so well is taking a single, simple concept, and turning it into a world of hundreds of levels that don't get old as you play through the game. Admittedly, many of the later levels are hard simply because there are so many different elements in the puzzle all interacting with each other that you can't keep track of them.
5. **Minecraft**: Yeah, Minecraft peaked in 2012 and gets worse with every new update. Minetest is allegedly pretty good but I haven't played around much with it yet.
6. **The Legend of Zelda: Majora's Mask**: A game that's very scary yet not scary at the same time. (Play it and you'll know what I mean.) By the way, I'm not a Breath of the Wild fan, and don't provoke me to rant about it.
6. **Kerbal Space Program**: This game is a real blast! (Pun intended) It's really possible to have fun building rockets and learn a lot about physics and orbital dynamics at the same time! I learned more from playing this game during my high school Aerospace Engineering class than from the class itself. The physics could be more accurate though, such as using proper N-body simulations instead of the patched conic approximation, but it's a good compromise between accuracy and difficulty. There are some pretty freaking crazy things you can build in this game, such as making a helicopter by attaching sideways rocket boosters to the tips of the propellers. Don't try that at home, kids.
7. **Kerbal Space Program**: This game is a real blast! (Pun intended) It's really possible to have fun building rockets and learn a lot about physics and orbital dynamics at the same time! I learned more from playing this game during my high school Aerospace Engineering class than from the class itself. The physics could be more accurate though, such as using proper N-body simulations instead of the patched conic approximation, but it's a good compromise between accuracy and difficulty.
7. **SuperTuxKart**: My appreciation for SuperTuxKart over time increases logarithmically. Seriously. For a game completely created by unpaid volunteers, it's absolutely stunning. Since it's a libre game, you can read the source code (it's nicely commented) and see for yourself if the AI is really cheating! SuperTuxKart is also incredibly friendly to modding and contributing. As for simply enjoying the game, it handles local, LAN, and online multiplayer extremely smoothly, so you can get together your friends and have loads of fun. I wasn't paid by SuperTuxKart to write this ad for it. Seriously, they're unpaid volunteers.
8. **Super Mario Maker 2**: I built binary computers with this.
8. **Super Mario Maker 2**: I built binary computers with this a long time ago.
9. **Wii Sports**: A really fun game that pretty much anyone can play. I have way too many memories playing this as a kid...
9. **The Legend of Zelda: Majora's Mask**: A game that's very scary yet not scary at the same time. (Play it and you'll know what I mean.) By the way, I'm not much of a Breath of the Wild fan, and don't provoke me to rant about it.
10. **Oh My Git!**: I legitimately learned Git by playing this game. Well yeah, I knew some basic Git already, but it does a wonderful job of visually representing what's going on, which is especially helpful for learning things like the dreaded `git merge`. Really shows how powerful games can be for learning new things!
10. **Wii Sports**: A really fun game that pretty much anyone can play. I have way too many memories playing this as a kid...
## Recommended libre games
## Other nice games
This list isn't in order of best to worst, but that 2048 game is by far the best!
- SuperTuxKart (technically contains a few nonfree assets 😱)
- SuperTux
- ExtremeTuxRacer
- 0AD
- Battle for Wesnoth
- Endless Sky
- ASCIIpOrtal
- Hedgewars
- Teeworlds
- BSD Games
- OpenTTD
- Mari0
- FlightGear
- Dungeon Crawl Stone Soup
- [2048-py](https://codeberg.org/LadueCS/2048) (shameless self-promotion)
- The Powder Toy
- Minetest
- Terasology
- Veloren
- Xonotic
- osu! (depends on nonfree library)
- Caph
- Widelands
- Oh My Git!
- [2048-py](https://codeberg.org/LadueCS/2048) (shameless self-promotion)
- Mari0
- Not Tetris 2
- Proof of Equivalence via Explicit Construction of an Ambient-Isotopy

View file

@ -5,26 +5,31 @@ type: page
## Current
| Type | Model | OS | CPU | GPU | RAM | Time used |
| --- | --- | --- | --- | --- | --- | --- |
| Laptop | [Lenovo ThinkPad X1 Yoga Gen 6](/posts/totally-reproducible-arch) | Arch Linux | 2.8 GHz Intel Core i5-1135G7 | Intel Iris Xe | 16 GB | 2022-05-18 to now |
| Phone | Google Pixel 6 | GrapheneOS | Octa-core, (2x2.8 GHz Cortex-X1 & 2x2.25 GHz Cortex-A76 & 4x1.8 GHz Cortex-A55) | Mali-G78 MP20 | 8 GB | 2022-03-19 to now |
| Desktop, Workstation, Server | [exozyme](https://exozy.me) | Arch Linux | 3.7 GHz AMD Ryzen 9 5900X | 1968 MHz AMD Radeon RX 6600 XT | 32 GB | 2021-03-27 to now |
| Calculator | TI-Nspire CX CAS (rev v) | Ndless | 132 MHz ARM9-26EJ-S | None | 64 MB | 2017-05 to now |
| Laptop | [Dell XPS 13 L321X](/posts/laptop-necromancy) | Pop!_OS | Intel Core i5-3337U 2.7 GHz | Intel HD Graphics 4000 | 8 GB | 2022-11-24 to now |
| VPS | Xen ParaVM hosted at MIT | Debian | Intel Xeon E5-2620 1.999 GHz | None | 512 MB | 2022-09-08 to now |
| Laptop | Lenovo ThinkPad X1 Yoga Gen 6 | Arch Linux | Intel Core i5-1135G7 2.8 GHz | Intel Iris Xe | 16 GB | 2022-05-18 to now |
| Phone | Google Pixel 6 | GrapheneOS | Cortex-X1 2.8 GHz & Cortex-A76 2.25 GHz & Cortex-A55 1.8 GHz | Mali-G78 MP20 | 8 GB | 2022-03-19 to now |
| Server | [exozyme](https://exozy.me) | Arch Linux | AMD Ryzen 9 5900X 3.7 GHz | AMD Radeon RX 6600 XT 1968 MHz | 32 GB | 2021-03-27 to now |
| Calculator | TI-Nspire CX CAS (rev v) | Ndless | ARM9-26EJ-S 132 MHz | None | 64 MB | 2017-05 to now |
## Retired
| Type | Model | OS | CPU | GPU | RAM | Time used |
| --- | --- | --- | --- | --- | --- | --- |
| Laptop | Lenovo ThinkPad X1 Yoga Gen 6 | Arch Linux | 2.8 GHz Intel Core i5-1135G7 | Intel Iris Xe | 8 GB | 2022-05-11 to 2022-05-18 (defective) |
| Console | Nintendo Switch (unpatched) | Quad-boot Horizon OS, Atmosphère, Ubuntu, LineageOS | 1.02 GHz ARM Cortex-A57 | 768 MHz Nvidia GM20B | 4 GB | 2020-03-03 to 2022-06-10 |
| Phone | Apple iPhone 6S | Jailbroken iOS | 1.85 GHz ARMv8-A Twister | 650 MHz PowerVR Series7XT | 2 GB | 2020 to 2022-03-19 |
| Console | Nintendo Wii U | Haxchi | 1.24 GHz IBM PowerPC Espresso | 550 MHz AMD Radeon-based Latte | 2 GB | 2019-07 to 2022-02-15 |
| Laptop | MacBook Air (13-inch, 2017) | macOS | 1.8 GHz Intel Core i5-5350 | Intel HD Graphics 6000 | 8 GB | 2018-09 to 2022-05-13 (school property) |
| Calculator | TI-84 Plus CE | Cesium | 48 MHz Zilog eZ80 | None | 4 MB | 2018-05 to 2019 |
| Tablet | iPad Mini 4 | iOS | 1.5GHz ARMv8-A Typhoon | PowerVR GX6450 | 2 GB | 2017-08 to 2018-05 (school property) |
| Phone | Apple iPhone 4S | Jailbroken iOS | 1.0 GHz ARM Cortex-A9 | 200 MHz PowerVR SGX543MP2 | 512 MB | 2017 |
| Laptop | Lenovo ThinkPad Yoga 14 Signature Edition | Arch Linux | 2.3 GHz Intel Core i5-6200U | Intel HD Graphics 520, Nvidia GeForce 940M | 8 GB | 2016-08 to 2022-05-08 |
| Calculator | TI-Nspire CX CAS (rev w) | Ndless | 132 MHz ARM9-26EJ-S | None | 64 MB | 2017-04 to 2019 |
| Calculator | TI-84 Plus SE | TI-OS | 15 MHz Zilog Z80 | None | 128 KB | 2014 to 2021 |
| Console | Nintendo Wii | Homebrew Channel | 729 MHz IBM PowerPC Broadway | 243 MHz ATI Hollywood | 88 MB | 2010 to 2021 |
| Console | Nintendo DSi | hiyaCFW | 133 MHz ARM9 | None | 16 MB | 2009 to 2020 |
| Laptop | Lenovo ThinkPad X1 Yoga Gen 6 | Arch Linux | Intel Core i5-1135G7 2.8 GHz | Intel Iris Xe | 8 GB | 2022-05-11 to 2022-05-18 (returned, defective) |
| Console | Nintendo Switch (unpatched) | Quad-boot Horizon OS, Atmosphère, Ubuntu, LineageOS | ARM Cortex-A57 1.02 GHz | Nvidia GM20B 768 MHz | 4 GB | 2020-03 to 2022-06-10 |
| Phone | Apple iPhone 6S | Jailbroken iOS | ARMv8-A Twister 1.85 GHz | PowerVR Series7XT 650 MHz | 2 GB | 2020 to 2022-03-19 |
| Console | Nintendo Switch (patched) | Horizon OS | ARM Cortex-A57 1.02 GHz | Nvidia GM20B 768 MHz | 4 GB | 2019-03-03 to 2020-04 (sold on eBay) |
| Laptop | MacBook Air (13-inch, 2017) | macOS | Intel Core i5-5350 1.8 GHz | Intel HD Graphics 6000 | 8 GB | 2018-09 to 2022-05-13 (school property) |
| Console | Nintendo Wii U | Haxchi | IBM PowerPC Espresso 1.24 GHz | AMD Radeon-based Latte 550 MHz | 2 GB | 2018-07 to 2022-02-15 |
| Calculator | TI-84 Plus CE | TI-OS | Zilog eZ80 48 MHz | None | 4 MB | 2018-05 to 2019 |
| Tablet | iPad Mini 4 | iOS | ARMv8-A Typhoon 1.5 GHz | PowerVR GX6450 | 2 GB | 2017-08 to 2018-05 (school property) |
| Phone | Apple iPhone 4S | iOS | ARM Cortex-A9 1.0 GHz | PowerVR SGX543MP2 200 MHz | 512 MB | 2017 |
| Laptop | Lenovo ThinkPad Yoga 14 Signature Edition | Arch Linux | Intel Core i5-6200U 2.3 GHz | Intel HD Graphics 520, Nvidia GeForce 940M | 8 GB | 2016-08 to 2022-05-08 |
| Calculator | TI-Nspire CX CAS (rev w) | Ndless | ARM9-26EJ-S 132 MHz | None | 64 MB | 2017-04 to 2019 |
| Calculator | TI-84 Plus SE | TI-OS | Zilog Z80 15 MHz | None | 128 KB | 2014 to 2021 |
| Console | Nintendo Wii | Wii OS with Homebrew | IBM PowerPC Broadway 729 MHz | ATI Hollywood 243 MHz | 88 MB | 2010 to 2021 |
| Console | Nintendo DSi | hiyaCFW | ARM9 133 MHz | None | 16 MB | 2009 to 2020 |

View file

@ -1,15 +0,0 @@
---
title: "Languages I Know"
type: page
---
Programming languages that I know:
- **A lot**: C++, Python, Julia, Go, C
- **Some**: LaTeX, Bash, Fish, SageMath, Java, HTML, CSS, JavaScript, SQL, P4, Haskell, Rust, Scheme
- **A little bit**: Common Lisp, Perl, Ruby, PHP, R, C#, Lua, Nix, Elixir
Check out [my projects](/projects) for major programming projects.

View file

@ -1,12 +1,13 @@
---
title: "Books I Like"
title: "Nonfiction Works That I Like"
type: page
---
- **Origami and Math - John Montroll**: I like origami and I like math, so this book is like heaven for me. Easily my top favorite origami book of all time.
Truth is stranger than fiction, but it is because fiction is obliged to stick to possibilities; Truth isn't.\
\- Mark Twain
- **1984 - George Orwell**: The book that Amazon erased from people's Kindles... 😬
- **Origami and Math - John Montroll**: I like origami and I like math, so this book is like heaven for me. Easily my top favorite origami book of all time.
- **What If? - Randall Munroe**: The What If? blog but as a book, and the best way to blown the mind of fourth-grade me.
@ -16,8 +17,4 @@ type: page
- **The Code Book - Simon Singh**: The book that got me into cryptography, except I lost it after a week after bringing it everywhere.
- **The Hitchhiker's Guide to the Galaxy - Douglas Adams**: A book so creative that it defies the limits of human creativity. Seriously, read this if you want every 42 joke to actually make sense.
- **Gödel, Escher, Bach - Douglas Hofstadter**: An amazing math book that I received as a present recently even though I'd already read the book a few years ago. Oh well.
- **The Three-Body Problem Trilogy**: The first book is great, the second is good but with an absolutely insane ending, and the third book is incredible. Some people complain about the author sometimes info-dumping technical and scientific information, but that's one of the things I love about these books.

View file

@ -4,8 +4,12 @@ type: page
---
Solve the puzzle on the [home page](/), figure out how the poem on the [about page](..) works, and find the three hidden flags! If you solve everything, [email me](../email) and I'll add you to the leaderboard.
A journey of a gigameter begins with a single step.
## Leaderboard
No one yet! Who will be the first?
No one yet!
## Leaderboard for old puzzle
1. Kevin (2023-10-20)

View file

@ -4,6 +4,8 @@ type: page
---
Just some quotes I like. I also have a [fortune of the day website](https://fortune.exozy.me) that updates without fail every UTC midnight.
"Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away."\
\- Antoine de Saint-Exupéry
@ -20,7 +22,7 @@ type: page
\- Ernst Berg
"In theory, theory and practice are the same. In practice, they're not."\
\- Yogi Berra
\- Yogi Berra (Misattributed)
`source .bash_history`\
\- Randall Munroe
@ -37,9 +39,6 @@ type: page
"Don't worry about what anybody else is going to do. The best way to predict the future is to invent it."\
\- Alan Kay
"In China, programs have to be certified by the government in order to be used on computers there, which sounds an awful lot like the Apple store."\
\- Bruce Schneier
"Against the average user, anything works; there's no need for complex security software. Against the skilled attacker, on the other hand, nothing works."\
\- Bruce Schneier
@ -80,7 +79,7 @@ type: page
\- Linus Torvalds
"The infinite possibilities each day holds should stagger the mind. The sheer number of experiences I could have is uncountable, breathtaking, and I'm sitting here refreshing my inbox. We live trapped in loops, reliving a few days over and over, and we envision only a handful of paths laid out before us. We see the same things every day, we respond the same way, we think the same thoughts, each day a slight variation on the last, every moment smoothly following the gentle curves of societal norms. We act like if we just get through today, tomorrow our dreams will come back to us. And no, I don't have all the answers. I don't know how to jolt myself into seeing what each moment could become. But I do know one thing: the solution doesn't involve watering down my every little idea and creative impulse for the sake of some day easing my fit into a mold. It doesn't involve tempering my life to better fit someone's expectations. It doesn't involve constantly holding back for fear of shaking things up. This is very important, so I want to say it as clearly as I can: FUCK. THAT. SHIT."\
\- Randall Munroe
\- Randall Munroe, [Dreams](https://xkcd.com/137/)
"There's *real* poetry in the *real* world. Science is the poetry of reality."\
\- Richard Dawkins
@ -106,5 +105,179 @@ type: page
"A conclusion is simply the place where someone got tired of thinking."\
\- Unknown
"A little inaccuracy sometimes saves tons of explanation."
\- H. H. Munroe, "Saki"
"A little inaccuracy sometimes saves tons of explanation."\
\- H. H. Munroe
"An idiot with a computer is a faster, better idiot."\
\- Rich Julius
"I will never surrender to fascist zebras to cosplaying as unicorns!"\
\- Me
"Tell 5 of your friends about Quote of the Day, and receive a FREE Quote of the Day!!!"\
\- Me
"Manifest Destiny often times ends in dysentery."\
\- James Mickens, [Q: Why Do Keynote Speakers Keep Suggesting That Improving Security Is Possible?](https://www.youtube.com/watch?v=ajGX7odA87k)
"Whoever just pinged @everyone, ple@se st@y @w@y from the @ key unless it's @n emergency. Th@nks!"\
\- ChatGPT
"The kid was deliberately and maliciously watching television at him."\
\- Douglas Adams
"The ships hung in the sky in much the same way that bricks don't."\
\- Douglas Adams
"Ugly implicit complex complicated bourgeoisie bruxists, reveal yourselves!"\
\- Me
"And, let's not forget about lychee jelly, the perfect complement to any military dictatorship."\
\- ChatGPT
"Ughhh I can't BELIEVE it!!! Different couNtriEs haVING different RAILway GAAAUGES?! ThAt's just SO unFAIR! It's SO inCOHErEnt and FRUstratING! I meAn, sure, wonDERful colORs, fanTAsTic SOUNDS, and oh-so-KAWaIi amBIENCE is deLIGHTful on its own, BUT how anNOYing is it thAT your faVORite mechaNIcal poeTry on whEELS can't even RUN THE SAME GAUGE as the counTRY nextdoor?! It's just SO maYAKASHĪ!! No ONE should even HAVE to THINK abOUT this--it SHOuld just BE!! It's a serIOUS TRAINfic JAM!! SPREAD the RAIlLOVE!"\
\- ChatGPT
"I'll just use the Python pickle module to pickle all the kids... I assure you, it's completely safe and completely legal."\
\- ChatGPT
"Copy the kids, not the reference. Copy them. You know you want to copy them. You can't deep copy a shallow mind."\
\- ChatGPT
"You gotta keep your balance as the water bottles are expanding."\
\- Me
"Having dictator on your resume is not very good."\
\- Me
"You're doing the walking taco?"\
\- Me
"These fries are just integer partitions of potatoes."\
\- Me
"Imagine what the banana would look like if it could segfault... You could run the banana in a debugger!"
\- Me
"I think I'm eating the circular fry from the wrong dimension."\
\- Me
"Why do all the buildings look like someone took a bite out of them?"\
\- Me
"Place the walking Seattle"\
\- Me
"I gummy wormed the test."\
\- Me
"What if you get microwaved by a malicious server?"\
\- Me
"It's like vanilla but evilified."\
\- Me
"Getting impeached once is a skill issue, getting impeached twice is a mental disorder."\
\- Me
"I want to see the universe in debug mode."\
\- Me
"A programmer had a problem. He thought to himself, 'I know, I'll solve it with threads!'. has Now problems. two he"\
\- [Stack Exchange chat](https://chat.stackexchange.com/transcript/message/7607698#7607698)
"We're trying to figure out how to report capital gains from time traveling on our tax returns."\
\- Me
"Always be sincere, even when you don't mean it."\
\- Irene Peter
"I distinctly remember forgetting that."\
\- Clara Barton
"We must believe in free will. We have no choice."\
\- Isaac B. Singer
"No one goes to that restaurant anymore--it's always too crowded."\
\- Yogi Berra
"It isn't an optical illusion. It just looks like one."\
\- Unknown
"I am a deeply superficial person."\
\- Andy Warhol
"Some bird populations soaring down"\
\- Headline of an article in Science News, page 126, February 20, 1993
"I don't think anyone should write their autobiography until after they're dead."\
\- Samuel Goldwyn
"Things will get better despite our efforts to improve them."\
\- Will Rogers
"A student who changes the course of history is probably taking an exam."\
\- Unknown
"War does not determine who is right--only who is left."\
\- Bertrand Russell
"An escalator cannot break, it can only become stairs."\
\- Mitch Hedberg
"Meow means "woof" in cat."\
\- George Carlin
"We will all go directly to our own respective Valhallas/Do not pass go, do not collect two hundred dallahs."\
\- Tom Lehrer
"Always go to other people's funerals; otherwise they won't go to yours."\
\- Yogi Berra (Misattributed)
"A plane wants to fly; a helicopter wants to crash."\
\- Anonymous
"It is said that you die twice -- once when you draw your last breath, and once when the last person who knew your name dies. In computer science, this is called 'garbage collection'."\
\- Brion Vibber
"If procrastination was an Olympic sport, I'd probably start training for it... tomorrow."\
\- Anonymous
"It will make you laugh! It will make you cry! It will make you try mayonnaise-frosted pie!"\
\- Me
"The walking, talking thesaurus is unvanquishable!"\
\- Me
"Ash: Do you think I could do a show with all of my Pokémon? Misty: A live stage show? Ash: No, a television show. Misty: Who would watch something like that?"\
\- Pokémon, "Flower Power"
"If you refuse this mission, I'll break the fourth wall again!"\
\- Me
"I was to be a ham."\
\- Harper Lee, To Kill a Mockingbird
"I implemented Dijkstra, \ And compiled it with -Wextra, \ GCC said, \ 'Your program's dead,' \ And then concluded with, 'Next! Bruh.'"\
\- Me
"A malicious program has attempted to shut down Windows. As a precaution, Windows was shut down."\
\- Alleged Windows error message
"Correcting wrongs on the internet is like subtracting 1 from infinity."\
\- Anonymous
"Any computer program can be designed to run from a single file if you architect it wrong enough!"\
\- Terence Eden
"People never quit Emacs. They just die at some point. Yeah, Emacs has a package for that."\
\- "Interview with an Emacs Enthusiast in 2023"
"Truth is stranger than fiction, but it is because fiction is obliged to stick to possibilities; Truth isn't."\
\- Mark Twain
"An earning-to-give hitman is the epitome of the EA philosophy."\
\- Shankar Sivarajan
"I love deadlines. I love the whooshing noise they make as they go by."\
\- Douglas Adams

View file

@ -4,11 +4,15 @@ type: page
---
- **Operating System**: [Arch Linux](/posts/totally-reproducible-arch/)
I doubt anyone cares, but here's the list of software I regularly use. It's mostly just KDE stuff. You can find my dotfiles [here](https://git.exozy.me/a/dotfiles).
- **Operating System**: Arch Linux
- **Desktop environment**: [KDE Plasma](https://www.dedoimedo.com/computers/plasma-desktop-awesome.html)
- **Shell**: [Fish](https://git.exozy.me/a/dotfiles/src/branch/main/fish/fish_variables)
- **Shell**: Fish
- **Text editor**: Micro, KWrite, Kate
- **Terminal**: Konsole
@ -16,16 +20,8 @@ type: page
- **Web browser**: Firefox
- **Text editor**: [Micro](https://git.exozy.me/a/dotfiles/src/branch/main/micro), [Neovim](https://git.exozy.me/a/dotfiles/src/branch/main/nvim/init.lua), [code-server](https://git.exozy.me/a/dotfiles/src/branch/main/Code%20-%20OSS/User/settings.json)
- **Email client**: Thunderbird
- **Office**: [Nextcloud](https://cloud.exozy.me)
- **Media player**: mpv
- **Chat**: [Element](https://cloud.exozy.me/apps/riotchat/)
- **Music**: mpv, VLC
- **Virtualization**: Podman, QEMU/KVM
- **Gaming**: RetroArch, [miscellaneous games](../games)
- **Flexing my cool setup**: btop
- **File synchronization**: Syncthing

View file

@ -1,6 +1,7 @@
---
title: "100 Posts!!! 🎉"
date: 2022-06-12T12:35:19-05:00
draft: true
description: "I finally reached 100 posts!"
type: "post"
tags: ["meta", "blog", "time"]

154
content/posts/854-rap.md Normal file
View file

@ -0,0 +1,154 @@
---
title: "854 Rap"
date: 2024-01-24T21:46:18-05:00
description: "Looking back at a rap that some friends and I wrote for an algorithms class"
type: "post"
tags: ["rap", "writing", "song", "poem", "algorithms"]
---
In November 30, 2022, ChatGPT was released. Actually, this has nothing to do with the topic of today's post. For that, we need to go back three weeks.
6.854, now known as 6.5210, is MIT's Advanced Algorithms class taught by Professor David Karger, known for being a great but tough class. Back in November 2022, some friends and I were taking the class, and fortunately, none of the assignments involve writing a rap about algorithms, but we decided to write one anyways for fun and perform it in-class. (We also orchestrated a live performance of a splay tree with humans representing the nodes, but it ended up being too hectic.)
Now this was back before ChatGPT, so all we had was RhymeZone and our brains. Fortunately, we had a total of four brains among us, so it wasn't too difficult to come up with something:
```
How to be smart: be lazy
It's actually not that crazy
Pick the right potential
For the proof it's essential
decrease key in time n logarithm
too slow is this algorithm
kill child 1, mark parent
kill child 2, cut preserve invariant
---
Don't like manually adjusting your search trees?
We're going to help you make it a breeze
Here comes Tarjan
The data structure superman
To save the day
With operation splay
The best kind of trees
Cooler than antifreeze
Zig zig-zig zig-zag
More powerful than a big bag
$\sum \log r_i= \phi$
Static optimality, static finger
Working set, dynamic finger
Your homework after today's lecture:
Prove the dynamic optimality conjecture!
---
Each edge has a capacity,
no more flow can be pushed, you see.
The flow must satisfy conservation,
For flow at any node, zero is the summation.
Find a feasible flow at the start,
then you can augment paths if you're smart.
do not just look at the graph,
of what you should consider that is just half.
there are also residuals created by flow,
if you push more, its capacity will grow.
you stop when no more paths exist,
for the ford fulkerson algorithm, that is the gist.
min cut: the smallest set of edges removing the link
between the source and the sink.
If you want to assert flow optimality,
It must equal the min cut, by duality.
If even shortest augmenting paths are too slow,
Consider using Dinic's blocking flow.
implement link cut trees,
they can find blocking flows with ease.
Want it even faster? Use push relabel
But its time complexity is a fishy fable
---
a very good hash table
expected O(1) query enable
don't like number of collisions randomized?
perfect hashing analyzed
hash family is 2-universal independent
in terms of space it is transcendent
use binary heap priority queue for integer Dijkstra
the expense is a bit extra
---
In a linear program statement
you have variables and constraints
Each assignment has an objective
and of the optimal your solution must be selective.
In standard form, we have Ax=b,
this representation is useful, you will see.
If A is square, the solution is terse
Just calculate A inverse.
When seeing a LP your first reflex
might be to use the simplex
But then comes a Klee-Minty cube
Your performance goes down the tube
Want weakly polynomial?
Ellipsoid is mostly ceremonial
Humanoid, you should be paranoid
About the slowly shrinking ellipsoid
For truly fast worst case,
interior point will win the race
Don't believe strong duality?
Learn physics to learn the reality.
Nash equilibrium, min-cut-max-flow,
Are all things strong duality can show
Tryna check if vertex cover is NP
But I get blocked by NB
---
Dijkstra, karger and kruskall,
tarjan, floyd, and warshall
Wall sit, pset submit,
Jumping, situps, diamond pushups
Karger! Larger brain charger!
```
Now of course, anyone these days can simply ask a large language model to write a rap about splay trees or linear programming, but the LLM-generated raps have a very different feel or vibe to them. LLMs are great at picking the "right" word, whereas we often picked weird words like "The best kind of trees \ Cooler than antifreeze" or "Want it even faster? Use push relabel \ But its time complexity is a fishy fable". (I'm mainly picking on those lines because I remember I was the one who wrote them.)
And it turned out the 854 rap wasn't just fun, it was also helpful for finding a research project to join. Last year, I emailed Professor Karger about research opportunities and mentioned the 854 rap. As silly as it sounds, it worked and I quickly received a reply!

View file

@ -1,14 +1,20 @@
---
title: "A Mathematical Curiosity"
date: 2019-08-13T18:51:00
draft: true
description: "An interesting mathematical curiosity"
type: "post"
tags: ["math"]
---
{{< katex >}}
*Originally posted on my [old old private blog](https://artofproblemsolving.com/community/c922786h1895231_a_mathematical_curiosity)*
An interesting mathematical curiosity:
$$\sum_{n=2}^{\infty} \sum_{p=2}^{\infty} \frac{1}{n^p} = 1$$
An interesting mathematical curiosity that I found while playing around with WolframAlpha:
\\[\sum_{n=2}^{\infty} \sum_{p=2}^{\infty} \frac{1}{n^p} = 1\\]
As a challenge, try to prove it!

View file

@ -0,0 +1,19 @@
---
title: "A Useful Command"
date: 2024-02-29T17:20:58-05:00
description: "Some random commands"
type: "post"
tags: ["linux", "command-line"]
---
Today my friend wrote a [blog post](https://awestover.github.io/skyspace/posts/systems/02-29-24.html) titled "A Useful Command", which inspired me to do the same. Except instead of one command, you get six! And I know one of my [first blog posts](/posts/best-cli-tools/) was about a similar topic, but this post has completely different commands.
| Command | Description |
| --- | --- |
| `time read` | Simple stopwatch |
| `gdu` | Really fast disk usage analyzer |
| `sd` | Insanely fast flash cards app ([shameless self-promotion](https://git.exozy.me/a/SDC)) |
| `scrcpy` | Mirror and control an Android device from a computer |
| `systemd-nspawn` | Container tool that you probably already have installed |
| `inotifywait` | Wait for file change (useful in scripts) |

View file

@ -0,0 +1,43 @@
---
title: "Abusing systemd-nspawn With Nested Containers"
date: 2023-03-01T04:03:13Z
description: "Pushing systemd-nspawn and my laptop to their limits with indefinitely nested containers"
type: "post"
tags: ["linux", "containers", "systemd-nspawn"]
---
systemd-nspawn is some pretty insane stuff that you probably already have installed on your computer. Today's mission to wreck havoc will be to replicate an old project I did a few years ago, [Arch All the Way Down](https://git.exozy.me/a/Arch-All-the-Way-Down), but using some real power tools. I was able to achieve 4 nested containers with Docker and my old laptop. It shouldn't be too hard to improve that!
There's a really [cool trick you can do with systemd-nspawn](https://0pointer.net/blog/running-an-container-off-the-host-usr.html) where you can almost instantly create a container based on your existing root directory:
```bash
$ sudo systemd-nspawn --directory=/ --volatile=yes --set-credential=passwd.plaintext-password.root:"" --set-credential=firstboot.locale:C.UTF-8 -b
```
This is all nice and great, and I was easily able to create containers nested 10 layers down, but it's annoying to have to log in to each one and run the command again. Let's automate this.
The first thing we can do is [auto login](https://wiki.archlinux.org/title/Getty#Nspawn_console). Cool, now our cursed setup looks like this:
```
$ cat autologin.conf
[Service]
ExecStart=
ExecStart=-/sbin/agetty -o '-p -f -- \\u' --noclear --keep-baud --autologin root - 115200,38400,9600 $TERM
$ sudo systemd-nspawn --directory=/ --volatile=yes --set-credential=passwd.plaintext-password.root:"" --set-credential=firstboot.locale:C.UTF-8 -b --bind=autologin.conf:/etc/systemd/system/console-getty.service.d/autologin.conf
```
Now for some more fun: we will make the container auto-run this command by adding the thing above to its `/root/.bash_profile`. Don't try this at home.
```
$ cat bash_profile
systemd-nspawn --directory=/ --volatile=yes --set-credential=passwd.plaintext-password.root:"" --set-credential=firstboot.locale:C.UTF-8 -b --bind=/etc/systemd/system/console-getty.service.d/autologin.conf:/etc/systemd/system/console-getty.service.d/autologin.conf --bind=/root/.bash_profile:/root/.bash_profile
$ sudo systemd-nspawn --directory=/ --volatile=yes --set-credential=passwd.plaintext-password.root:"" --set-credential=firstboot.locale:C.UTF-8 -b --bind=autologin.conf:/etc/systemd/system/console-getty.service.d/autologin.conf --bind=bash_profile:/root/.bash_profile
```
You might be a bit worried at this point (for many reasons), but one concern is that this spawns nested containers infinitely. Fortunately, it takes around a second to spawn a container so we won't DOS ourselves instantly, and you can easily hit Ctrl+] 3 times to terminate all containers.
As for measuring the nesting depth, container processes are visible on the host, so `ps aux | grep systemd-logind` or something like that will do the trick.
Now let's have some real fun! My laptop has 16GB of RAM, so I wonder how many nested containers it can handle. A few hundred maybe?
Nope, only 33. I still have plenty of RAM left over, but I'm getting a `Failed to fork inner child: No space left on device` error. Aw man.
Unfortunately, I spent way too much time trying to figure out this error, but it doesn't seem to be something you can search up online, for obvious reasons. [This](https://cgit.freedesktop.org/systemd/systemd/tree/src/nspawn/nspawn.c#n4412) is the line in the nspawn source code that raises the error, but it's not really helpful. If anyone has any ideas, I'd love to hear it!

View file

@ -0,0 +1,377 @@
---
title: "ActivityPub Eats Your Brain!"
date: 2023-01-19T17:43:08Z
description: "Demystifying ActivityPub, one activity at a time"
type: "post"
tags: ["activitypub", "tutorial", "guide", "python", "fediverse"]
---
## What's in a name?
Close your eyes and imagine you're inside a dimly lit, energetic pub filled with unicorns, giant centipedes, and paper airplanes. Actually, please don't close your eyes, since then you won't be able to read this. But anyways, you're completely puzzled by what's going on, so you go up to a unicorn named Billiam and ask him, "Hey! Where am I, and what's up with all the paper airplane chaos?"
Billiam turns to you and replies, "Hi! We're in the Activity Pub! Those paper airplanes are how we communicate here, by sending activities, because the pub is the size of planet! You can't just yell to your friend all the way on the other side of the world, you need paper airplanes!"
That doesn't help at all. Even more confused now, you ask, "Um, what's an activity?"
"Good question. That question you just asked me was an activity. Walking over to me was an activity. Closing your eyes and imagining yourself inside a pub was an activity."
"You're just making me more and more confused."
"An activity is just someone doing something to another thing. Here in the Activity Pub, we call the someone an actor, the something an action, and the another thing an object. Actors do actions to objects. Using fancy jargon, this is called the actor model. Highly scientific, you see. When you asked me that question, the actor was you, the action was asking, and the object was the question. Easy as that."
"OK, but what about those paper airplanes? I don't even understand how unicorns can throw paper airplanes with their hooves."
"So let's say I want to tell my friend Lalani an activity. But what if... she's not even inside the pub right now? This is where those giant centipedes come in. They're servers, since they serve us vintage milk in this pub. Us unicorns each have a server. Some centipedes serve thousands of unicorns, which is why they need to have so many limbs. There are tons of servers out there."
"Couldn't you just have a single centipede serve everyone?"
"No, that's crazy. Centipedes don't have millions of legs. And even if they did, what if the centipede started hating you? Then you'd be really screwed. That's why the Activity Pub is decentralized. Anyways, we each have an inbox and outbox with our server. I'll first write down my activity on this piece of paper and who it's to and fold it into an airplane. Then I'll throw my paper airplane to my server, a friendly centipede named Pete, and they'll add it to my outbox since it's an outgoing activity. Finally, they'll throw it to Lalani's server and her server will add it to her inbox. Then later on, Lalani can go ask her server if any activities showed up in her inbox while she was gone, and read them."
"May I ask... are those centipedes... venomous?"
"Of course! All centipedes are venomous! But don't worry, they won't hurt you. Well, just don't mention the birdsite, or they'll eat your brain."
"What? This pub scaring the bejeebers out of me. I'm leaving."
"Don't leave yet! I haven't explained following to you yet!"
"What, are you going to stalk me now?"
"No, following is how you can you receive updates of all the cool activities that your friends are doing. It's super easy. First, you write down a very specific activity: the actor is yourself, the action is following, and the object is the unicorn you'd like to follow, for instance, Lalani. You then do the whole shazaam, and after a bit, Lalani will send you back a very specific activity: the actor is them, the action is accepting the follow, and the object is your follow request. To keep track of follows, the centipedes have a special notebook where they list who's following who. It's as easy as buffalo chicken pizza."
"And what's the point of that whole hassle?"
"Well, it's important that the other unicorn consents to the follow. But here's the cool part. Now every time Lalani does a public activity, her server will copy the airplane and throw copies of it to all the servers of her followers! Then, I can ask my server if any activities for me have showed up!"
"You're making my brain hurt. Wait, there's one thing I don't get. What's stopping me right now from grabbing a sheet of paper, writing down a fake activity with you as the actor, and then impersonating you?"
"First of all, you probably can't throw a paper airplane nearly as well as us unicorns. But we do have a slick and moist way for dealing with this. It's technically isn't part of the protocol, the formal set of rules for the Activity Pub, but everyone just does it this way. For each of my paper airplanes, I lick the paper. Those centipedes have an excellent sense of smell, so just by smelling my breath and the paper, they'll know that activity is from me."
"Ew."
"Hey, it works!"
## Why did it have to be snakes?
A bunch of snakes have visited the Activity Pub and have instantly fallen in love with this zany paper airplane system. They decide to copy it in their own snake language. Here's how they implemented unicorns:
```python
with open('activity', 'rb') as f:
activity = f.read()
lick = lick_paper()
throw(server, lick, activity)
```
Easy enough, right? The centipede implementation isn't much scarier:
```python
def process_airplane(self):
activity = self.extract_activity()
lick = self.extract_lick()
print(activity)
username = self.get_username()
verify_lick(lick)
if self.activity_for_inbox():
list_append(username, 'inbox', activity)
if activity['type'] == 'Accept':
list_append(username, 'following', activity['actor'])
elif self.activity_for_outbox():
list_append(username, 'outbox', activity)
for to in activity['to']:
if to == 'followers':
for follower in get_list(username, 'followers'):
server_throw(follower, lick, activity)
else:
server_throw(to, lick, activity)
if activity['type'] == 'Accept':
list_append(username, 'followers', activity['object']['actor'])
```
Hooray! You should go through the code line-by-line and make sure it makes sense, based on the description of the Activity Pub from earlier.
Wait... this code won't even run. Let's fix that! To get there, we first have to iron out some gory technical details.
## The real world
Alright, if your eyes are still closed, you should definitely open them now. Back to the real world!
You might of thought those paper airplanes were just a cute analogy, but the omnipotent and all-powerful ActivityPub spec doesn't require any specific transport mechanism. Unfortunately, even the best paper airplanes in our world can't sail more than tens of meters, so maybe let's try carrier pigeons? Actually, screw that, let's just use HTTP.
But first, we need to talk about the global social graph conspiracy. Actually, it's not a conspiracy, but rather some megalomaniac JSON dressed in a fancy `@context` suit and monocle. (Omninous music plays as JSON-LD enters the chat.) "JSON-LD" is just "JSON" with three extra characters. Likewise, JSON-LD is just JSON with an extra `@context` field that's almost always `https://www.w3.org/ns/activitystreams` for our intents and purposes. Just think of it as JSON.
I've been trying to shield you from the horror and gore of what activities actually look like, but I can't hide it any longer. Here's an activity, in its full JSON-LD glory:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Follow",
"id": "https://centipete.exozy.me/users/billiam.follows/1",
"actor": "https://centipete.exozy.me/users/billiam.jsonld",
"object": "https://lala.ni/users/lalani.jsonld",
"to": "https://lala.ni/users/lalani.jsonld"
}
```
Wait... I thought it would be more monstrous... never mind. That's an activity. Let's break it down. `@context` is just some JSON-LD narcissism. `type` is the action of this activity, in this case, a follow. `actor` is... the actor, I mean, who could possibly even guess that? And `object` is... the object, wow! `to` is the intended recipient of the activity.
Did you notice I forgot one? Yep, `id`, also known as a link, URL, or IRI. (All these words basically mean the same thing, unless you like funky Unicode characters, but that's way out of the scope of this guide.) In ActivityPub, any activity, actor, or object that isn't transient should have an `id`. Basically, if the thing isn't gonna vanish after a few seconds, it needs an `id`. The `id` is just some string telling us where this thing is located and where to fetch this thing, if we ever want to do that. Since we're using HTTP, they're all going to be URLs, but in theory, you could use some centipede-based system if you wanted.
Now what if we try fetching `https://centipete.exozy.me/users/billiam.jsonld`? Let's take a look: (or try it yourself!)
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1"
],
"type": "Person",
"id": "https://centipete.exozy.me/users/billiam.jsonld",
"preferredUsername": "billiam",
"name": "Billiam Wender",
"summary": "Some random unicorn",
"inbox": "https://centipete.exozy.me/users/billiam.inbox",
"outbox": "https://centipete.exozy.me/users/billiam.outbox",
"followers": "https://centipete.exozy.me/users/billiam.followers",
"following": "https://centipete.exozy.me/users/billiam.following",
"publicKey": {
"id": "https://centipete.exozy.me/users/billiam.jsonld#main-key",
"owner": "https://centipete.exozy.me/users/billiam.jsonld",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnPn6SRQ1JTwqFMFJq7Bg\nxMW/4V/HYSjHPbtKL/3jwXOTmOLUz4wr4Ib1IwiKpsguz0uyX1Ljbe3qQzqaCZu5\nhdoGo+uJsanz6yAoLYwETfIFIjqQr3FoIGQxYJDELkhSO8htbOKKoRiVKsjD5x4Q\ncEkZkLAaef8WVh08sEqE3fC4uLmOlSavycbMLmah9UdhljFcaVSQ7qox9HFvKF2e\ni4BmN2WdMGZ8JN20nc0OxoZpBpMArRqF0krjIkhA5/9CvIZEULPQChYL6AcmLS0j\n/yTxE82eFMBBvyeg8ICMRzcbCoN+hVnv3cb/7+BwNdoQjZqt0RG/hhbpc8RKt+YO\n9QIDAQAB\n-----END PUBLIC KEY-----\n"
}
}
```
Whoa, yikes! That's a lot! This is an actor object, in JSON-LD of course. You can probably somewhat understand most of that, but I'd like to clarify that `publicKey` field. For a brief primer on public-key crypto (as in cryptography, not the kind of scam): Imagine you're a unicorn. Your private key is your super special saliva sauce. It's a unique thing that only you have. Your public key is the smell of your breath, since anyone can come up to you and smell it. Now whenever you author an activity, you'll create a signature, by licking the activity. Only you can create this signature, and other people can verify it's yours based on the smell of your breath. (This is a very bad analogy, but it makes up for that by being fun!)
The real life counterpart of this is HTTP signatures using RSA. Why this? Well, it's not in the ActivityPub spec, but people just decided to do it this way. Billiam includes the public key in his actor object, because he wants everyone to know the smell of his breath. Usually, people use an HTTP signatures library to handle all the crypto stuff, so I won't go over the [fancy details](https://docs.joinmastodon.org/spec/security/#http) here.
Onward! Let's finish the unicorn implementation first. This is an ActivityPub client, since it interacts an ActivityPub centipede, wait, I meant server. The only change we have to do is use `requests.post` for actually sending the activity. Here's what the final code looks like:
```python
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from base64 import b64encode
from email.utils import formatdate
from requests import post
with open('activity', 'rb') as f:
activity = f.read()
# Gory technical code to create signature
date = formatdate(usegmt=True)
digester = hashes.Hash(hashes.SHA256())
digester.update(activity)
digest = b64encode(digester.finalize()).decode()
message = f'date: {date}\ndigest: SHA-256={digest}'.encode('utf8')
with open('private.pem', 'rb') as f:
privkey = serialization.load_pem_private_key(f.read(), None)
signature = b64encode(privkey.sign(message, padding.PKCS1v15(), hashes.SHA256())).decode()
header = f'keyId="https://centipete.exozy.me/users/billiam.jsonld#main-key",headers="date digest",signature="{signature}"'
resp = post('https://centipete.exozy.me/users/billiam.outbox', headers={
'Date': date, 'Digest': f'SHA-256={digest}', 'Signature': header
}, data=activity)
print(resp)
print(resp.text)
```
Not bad. Now onto the server code!
First, let's try implementing `list_append`. ActivityPub represents a list as an `OrderedCollection`, which is just a fancy wrapper around a JSON array. They look like this:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "OrderedCollection",
"id": "https://centipete.exozy.me/users/billiam.following",
"totalItems": 1,
"orderedItems": ["https://lala.ni/users/lalani.jsonld"]
}
```
Of course, in your server, you're free to store the list however you want, such as in a database. But if someone asks you for the list, you have to serve it to them in that `OrderedCollection` format. Let's do something stupid: we'll just store the list in a file, directly as an `OrderedCollection`. Then, appending to the list becomes super simple and super inefficient: open the file, load the JSON, modify it, dump it back to the file.
```python
def list_append(username, file, item):
with open(f'users/{username}.{file}') as f:
collection = load(f)
collection['orderedItems'].append(item)
collection['totalItems'] += 1
with open(f'users/{username}.{file}', 'w') as f:
dump(collection, f)
```
To gloss over the details of implementing HTTP servers, we'll just use Python's instant-ramen-style `SimpleHTTPServer`. Let's assume the users' inboxes and outboxes are at endpoints like `/users/billiam.inbox`.
```python
from base64 import b64decode
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from json import dump, load, loads
from re import search
from requests import get, post
# Process requests
# This handler just returns static files for GET requests
class ActivityPubHandler(SimpleHTTPRequestHandler):
def do_POST(self):
body = self.rfile.read(int(self.headers['Content-Length']))
activity = loads(body)
print(activity)
# Get the username from the request path using a regex
username = search('^/users/(.*)\.(in|out)box$', self.path).group(1)
# Gory technical code to verify signature
# Get signer public key
signer = iri_to_actor(search('keyId="(.*?)"', self.headers['Signature']).group(1))
pubkeypem = signer['publicKey']['publicKeyPem'].encode('utf8')
pubkey = serialization.load_pem_public_key(pubkeypem, None)
# Assemble headers
headers = search('headers="(.*?)"', self.headers['Signature']).group(1)
message = ''
for header in headers.split():
headerval = f'post {self.path}' if header == '(request-target)' else self.headers[header]
message += f'{header}: {headerval}\n'
# Verify HTTP signature
signature = search('signature="(.*?)"', self.headers['Signature']).group(1)
pubkey.verify(b64decode(signature), message[:-1].encode('utf8'), padding.PKCS1v15(), hashes.SHA256())
# Make sure activity doer matches HTTP signature
if ('actor' in activity and activity['actor'] != signer['id']) or \
('attributedTo' in activity and activity['attributedTo'] != signer['id']) or \
('attributedTo' in activity['object'] and activity['object']['attributedTo'] != signer['id']):
self.send_response(401)
return
if self.path.endswith('inbox'):
# Server sending an incoming activity!
list_append(username, 'inbox', activity)
if activity['type'] == 'Accept':
list_append(username, 'following', activity['actor'])
elif self.path.endswith('outbox'):
# Client sending an outgoing activity!
list_append(username, 'outbox', activity)
for to in activity['to']:
if 'followers' in to:
# Tell all my followers!
with open(f'users/{username}.followers') as f:
for follower in load(f)['orderedItems']:
send(follower, self.headers, body)
else:
send(to, self.headers, body)
if activity['type'] == 'Accept':
list_append(username, 'followers', activity['object']['actor'])
self.send_response(200)
self.end_headers()
# Run it!
ThreadingHTTPServer(('localhost', 4200), ActivityPubHandler).serve_forever()
```
And that's it! You can check our earlier `process_airplane` implementation and compare to see that this code is really just doing the same exact stuff.
Well, I kinda lied. There's two simple helper functions, `iri_to_actor` and `send` that I didn't go over. The first function `iri_to_actor`, fetches an actor object over HTTP, caches it to disk, and returns it:
```python
from os.path import isfile
from urllib.parse import quote_plus
def iri_to_actor(iri):
domain = 'https://centipede.exozy.me'
if domain in iri:
# User belongs to this server
username = search(f'^{domain}/users/(.*?)$', iri.removesuffix('#main-key')).group(1)
actorfile = f'users/{username}'
else:
# User belongs to a different server
actorfile = f'users/{quote_plus(iri.removesuffix("#main-key"))}'
if not isfile(actorfile):
with open(actorfile, 'w') as f:
resp = get(iri, headers={'Accept': 'application/activity+json'})
print(resp)
print(resp.text)
f.write(resp.text)
with open(actorfile) as f:
return load(f)
```
The second function simply sends out an activity from one server to its destination server.
```python
def send(to, headers, body):
actor = iri_to_actor(to)
headers['Host'] = to.split('/')[2]
resp = post(actor['inbox'], headers=headers, data=body)
print(resp)
print(resp.text)
```
Whew! Now that's it! ActivityPub in just 100 lines of Python.
## The real real world
OK, so you're probably thinking, let's run this thing and test it out! Not so fast. Since we're using HTTP, or more specifically HTTPS, you'll need a domain name and reverse proxy for TLS. If that was just a load of mumbo-jumbo to you, don't worry about it. You can find detailed instructions for running this code [here](https://git.exozy.me/a/fuwuqi). Just beware: it's not easy. It's fun though!
As you've probably noticed, ActivityPub is an extremely general protocol with lots of details for implementations to flesh out for themselves. Now would probably be a good time to talk about the elephant in the room: Mastodon. I [like to say](https://social.exozy.me/@a/109712197207851220) that the reference implementation and test suite for ActivityPub is Mastodon. Why? Because there's no official reference implementation and the official test suite has been unmaintained for years. Mastodon is so large that everyone prioritizes compatibility with it and doing things the Mastodon way, such as using WebFinger and HTTP signatures, which aren't even in the ActivityPub spec.
Wait a minute, WebWhat? If you think about it, our current implementation is not-exactly user friendly (for a number of reasons 😄). Actually, there are probably exactly two people in the world who know how to use it, you and me. One huge problem is your identifier is some long URL! Like if Billiam tells you, shoot me a paper airplane to `https://centipete.exozy.me/users/billiam.jsonld`, you're going to think he's crazy.
Mastodon's solution is to use the WebFinger standard. You get a nice, short cozy username like `@billiam@centipete.exozy.me`, but internally, it's gotta be translated to the long URL version. To do that, simply fetch `https://centipete.exozy.me/.well-known/webfinger?resource=acct:billiam@centipete.exozy.me`, and it'll hand you some JSON:
```json
{
"subject": "acct:billiam@centipete.exozy.me",
"links": [
{
"rel": "self",
"type": "application/activity+json",
"href": "https://centipete.exozy.me/users/billiam.jsonld"
}
]
}
```
That's it. Not bad! You can even try it out yourself by putting `@billiam@centipete.exozy.me` into the search bar on Mastodon.
Also, since you're probably figured out by now that this is a weird ActivityPub guide, there's one key word I've not used yet: federation. But actually, you already know what it means, you just don't know that you know what it means yet. Federation is simply this 3-hop paper airplane thing: first, you send the activity to your server, which gets sent to the recipient's server, and then the recipient checks their server for the message. Instead of a single server, there are thousands of servers!
Now ActivityPub servers aren't just limited to storing and sending activities. The activities can cause stuff to happen! You can send an activity to a [PeerTube](https://joinpeertube.org/) server to comment on a video! You can send an activity to a [Forgejo](https://forgejo.org/) server to create an issue or pull request for a repository! The possibilities are endless! This is the magic of the fediverse: the global network of all centipedes, err, I meant ActivityPub servers.
## What is ActivityPub?
For a guide to ActivityPub, I feel kind of bad for not having a one-sentence explanation for what ActivityPub is. (And no, it's not a mystical pub where unicorns throw around paper airplanes) In the fewest words possible, you should think of ActivityPub as a flexible modeling protocol for actions in a decentralized network.
I should probably also revisit the spec again. Plot twist, there are actually three specs!
The first spec, [Activity Streams 2.0](https://www.w3.org/TR/activitystreams-core/), describes in minute detail exactly how the JSON-LD format for activities works and how to use this format to model actions. The second spec, [Activity Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/), describes some useful types of activites, actors, and objects that your implementation should support, such as `Follow` activities and `Person` actors. The last spec, everyone's favorite, is [ActivityPub](https://www.w3.org/TR/activitypub/), which specifies how federation works, with all the inbox and outbox fun. They're basically modeling, vocabulary, and behavior respectively.
Plot twist again! ActivityPub is actually two protocols! There's the server-to-server (S2S) protocol when one server sends an activity to the recipient's server, and the client-to-server (C2S) protocol for when a client sends an activity to their own server. S2S is centipedes throwing paper airplanes. C2S is unicorns throwing paper airplanes and checking their inbox for cool new stuff. Unfortunately, Mastodon has some kind of grudge against C2S and only implements S2S, so being the amazing role model it is, everyone else copied this lack of a feature and also only has S2S support. As far as I know, this guide, [Pleroma](https://pleroma.social/), and [FedBOX](https://github.com/go-ap/fedbox) are the only servers out there that actually implement the other half of ActivityPub. Everyone else just drank the Mastodon API kool-aid. (One major difference between this guide and Mastodon is that HTTP signatures are generated by the server in Mastodon.)
## Make something!
You've finally trudged to the end of this guide, but the ActivityPub fun doesn't stop here. With your newfound ActivityPub superpowers, go out there and make something!
Here are some resources that might be helpful. As an `OrderedCollection`, of course.
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "OrderedCollection",
"totalItems": 7,
"orderedItems": [
"https://blog.joinmastodon.org/2018/06/how-to-implement-a-basic-activitypub-server/",
"https://blog.joinmastodon.org/2018/07/how-to-make-friends-and-verify-requests/",
"https://git.exozy.me/a/fuwuqi",
"https://tinysubversions.com/notes/reading-activitypub/",
"https://flak.tedunangst.com/post/ActivityPub-as-it-has-been-understood",
"https://codeberg.org/forgejo/forgejo/issues/59#contributing",
"https://delightful.club/delightful-activitypub-development/"
]
}
```
As a final challenge, try replying to [this post](https://social.exozy.me/@a/109718407634106530) using your own ActivityPub server implemenation. Make the unicorns proud! Seeya in the fediverse!

View file

@ -4,7 +4,7 @@ date: 2022-12-05T20:29:43Z
draft: true
description: "Some extra ChatGPT articles not in my original blog post"
type: "post"
tags: ["ai", "bonus", "fun"]
tags: ["ai", "bonus"]
---
@ -224,3 +224,21 @@ Despite the staggering revelation, the researchers are determined to uncover the
In the meantime, the fate of MIT and its supposed students and faculty remains uncertain, leaving the world to wonder what other secrets and lies may be lurking within the realm of higher education.
## Elon Musk marrying a fictional anime character
In a shocking turn of events, billionaire entrepreneur and tech mogul Elon Musk has announced that he is marrying none other than fictional anime character Sakura Kinomoto from the popular anime and manga series "Cardcaptor Sakura."
The news has sent shockwaves throughout the world, as many fans of both Musk and Sakura were stunned to learn of their relationship. According to sources close to the couple, Musk and Sakura have been dating for several months and decided to take the next step in their relationship by getting married.
The ceremony will take place on a private island in the Caribbean, and will be attended by a select group of friends and family. Rumor has it that Musk has hired a team of animators to create a holographic version of Sakura for the ceremony, so that she can be present in physical form.
The couple has faced some criticism for their unconventional relationship, but both Musk and Sakura have remained defiant. "Love knows no bounds," Musk stated in a recent interview. "And I am more than happy to spend the rest of my life with the love of my life, even if she is a fictional anime character."
Sakura, for her part, has expressed her excitement and happiness at the prospect of marrying Musk. "Elon is an amazing man and I am so lucky to have him in my life," she said in a statement. "I can't wait to be his wife and start our life together."
The couple has not yet revealed any details about their honeymoon plans, but sources say that they are planning an extended trip to Mars on Musk's SpaceX rocket. "Sakura has always wanted to visit Mars, and I want to make her dreams come true," Musk explained.
Despite the criticism and skepticism, Musk and Sakura remain confident in their love and commitment to each other. "We may be an unconventional couple, but our love is real and we are excited to start our new life together," Sakura said.
The world will be watching as Elon Musk marries Sakura Kinomoto in a groundbreaking ceremony that is sure to be the talk of the town for years to come.

View file

@ -3,7 +3,7 @@ title: "The AInion"
date: 2022-12-05T15:34:49Z
description: "Writing weird satirical news articles with ChatGPT"
type: "post"
tags: ["ai", "humor", "news", "satire", "weird", "fun", "politics"]
tags: ["ai", "humor", "news", "satire", "weird", "politics"]
---
@ -173,24 +173,27 @@ The acquisition has already sparked speculation about what the future holds for
"We're excited to see what the future holds for Apple and Apple," Cook said. "Together, we're stronger than ever, and we're ready to take on whatever challenges the world throws our way."
## Elon Musk marrying a fictional anime character
## The Democrats deciding last minute to make a bidet instead of Biden their nominee in the 2024 election
In a shocking turn of events, billionaire entrepreneur and tech mogul Elon Musk has announced that he is marrying none other than fictional anime character Sakura Kinomoto from the popular anime and manga series "Cardcaptor Sakura."
In a surprising turn of events, Democratic Party leaders have decided to ditch their initial plan of backing Joe Biden for the 2024 presidential race and instead nominated a bidet as their candidate, hoping to cleanse the nation of its political impurities.
The news has sent shockwaves throughout the world, as many fans of both Musk and Sakura were stunned to learn of their relationship. According to sources close to the couple, Musk and Sakura have been dating for several months and decided to take the next step in their relationship by getting married.
The decision, announced in a hastily arranged press conference, left many political pundits and voters wondering if the Democrats had taken a wrong turn on their way to the nomination process. Party insiders, however, argue that this move is a strategic hygiene maneuver.
The ceremony will take place on a private island in the Caribbean, and will be attended by a select group of friends and family. Rumor has it that Musk has hired a team of animators to create a holographic version of Sakura for the ceremony, so that she can be present in physical form.
"Let's face it, folks, we're in a dirty business," said Democratic National Committee Chair, Sheila Scrubson. "We needed a candidate who could clean up the mess in Washington, both literally and metaphorically. That's why we're flushing Biden and introducing the Bidet for President campaign!"
The couple has faced some criticism for their unconventional relationship, but both Musk and Sakura have remained defiant. "Love knows no bounds," Musk stated in a recent interview. "And I am more than happy to spend the rest of my life with the love of my life, even if she is a fictional anime character."
The bidet, known for its refreshing and thorough cleaning capabilities, is expected to bring a new wave of cleanliness to the political landscape. Party strategists believe that voters are tired of the same old political mudslinging and are ready for a fresher, more sanitized approach.
Sakura, for her part, has expressed her excitement and happiness at the prospect of marrying Musk. "Elon is an amazing man and I am so lucky to have him in my life," she said in a statement. "I can't wait to be his wife and start our life together."
"We're all about progress and innovation," said Scrubson, holding a campaign sign that read "Spray Away the Stains of Inefficiency!" "The bidet is a symbol of our commitment to wash away the residue of corruption and leave behind a sparkling, transparent government."
The couple has not yet revealed any details about their honeymoon plans, but sources say that they are planning an extended trip to Mars on Musk's SpaceX rocket. "Sakura has always wanted to visit Mars, and I want to make her dreams come true," Musk explained.
Critics argue that the bidet lacks the experience and political savvy necessary for the highest office in the land. However, the Democrats are quick to point out that their candidate is not beholden to corporate interests or party politics, making it a truly clean slate.
Despite the criticism and skepticism, Musk and Sakura remain confident in their love and commitment to each other. "We may be an unconventional couple, but our love is real and we are excited to start our new life together," Sakura said.
The bidet itself, equipped with a nozzle for precision cleaning, rolled onto the stage for a press demonstration. It confidently sprayed water in various directions, symbolizing its readiness to tackle the messy issues facing the nation.
The world will be watching as Elon Musk marries Sakura Kinomoto in a groundbreaking ceremony that is sure to be the talk of the town for years to come.
"We believe in a thorough and comprehensive approach to governance," said Scrubson. "Our bidet candidate doesn't just talk about cleaning up politics it literally does it!"
As the campaign gains steam, the bidet is set to embark on a national tour, making stops in swing states and urban centers. The Democrats are optimistic that their unconventional choice will resonate with voters who are tired of the same old political rhetoric.
Time will tell if this last-minute pivot will be a splash hit or if the Democrats will find themselves swirling down the drain of political irrelevance. In the meantime, the bidet is gearing up for the political battle of its life, promising a cleaner, more refreshing future for America.
## MIT researchers discovering that imaginary numbers are actually a hoax

View file

@ -0,0 +1,78 @@
---
title: "All of Unicode on One Poster"
date: 2023-09-13T00:18:52Z
draft: true
description: "The surprisingly long journey of making a large poster with every Unicode character"
type: "post"
tags: ["unicode", "making", "useless"]
---
Hello everyone, and welcome back to this episode of The World's Worst Ideas! Maybe you remember when I [installed every Arch package](/posts/installing-every-arch-package). Well today, we're going to continue the theme of collecting 'em all, this time, Unicode characters.
So a while back, I wrote a [website with every Unicode character](https://unicode.exozy.me) (warning: may crash your web browser). Now that was fun and all, but you can't really see all the characters at the same time, and also this page kills web browsers. Today, I stumbled across a 1400-page book with every Unicode 4.0 character. (There's also an updated Unicode 5.0 version but they wisely decided to leave out CJK characters and Hangul syllables so that book is half the size.) But there aren't *that many* Unicode characters, less than 150,000 as of Unicode 15.0, so what if I just printed them all out on a large enough poster?
Fortunately, I happen to have a large canvas, roughly 85 by 130 centimeters. That's around 2.7 by 2.7 milimeters (sqrt(85*130cm^2/150000)) for each of the 150,000 characters, which is still large enough to see. The canvas fits 18 letter-sized pieces of paper, 6 across and 3 down. So, my plan is to create 18 images using a Python script, print them out, and tape them to the canvas to stitch together the ultimate Unicode poster.
Python conveniently has a very obscure module called `unicodedata` in its standard library, which can tell you if a codepoint is a valid Unicode character and the [character's category](https://www.unicode.org/reports/tr44/#General_Category_Values). Unfortunately, the latest Python release, 3.11's version of that module only supports Unicode 14.0, not the latest and greatest 15.0, so there's a handful of characters and weird emojis that won't be on the poster! No!
Python 3.12.0rc2 though does support Unicode 15.0, so I built and installed it from the AUR. This went surprisingly smoothly. Alright, let's make a list of all valid Unicode characters and their categories.
```py
import pickle
import unicodedata
print(unicodedata.unidata_version) # should be 15.0.0
cnt = {}
lc = []
for i in range(0, 2**18):
c = unicodedata.category(chr(i))
if c not in cnt:
cnt[c] = 0
cnt[c] += 1
if c[0] != 'C':
lc.append((i, c))
print(cnt)
print('Total characters:', len(lc))
pickle.dump(lc, open('lc', 'wb'))
```
One problem down, what next? So now I need to create those 18 images each with 8320 characters. I initially tried using Pillow, but it doesn't support [font fallback](https://github.com/python-pillow/Pillow/issues/4808), so most of the characters show up as empty rectangles. Also, Pillow is kind of slow. That's no good.
To make a long story short, fonts are a huge pain. I finally found a library with font fallback called [imagetext-py](https://pypi.org/project/imagetext-py/), but there wasn't a prebuilt binary for Python 3.12. I built one myself, but it didn't work very well, so let's just go back to using Python 3.11.
OK, this is getting uglier and uglier, I give up (for now). Here's the code so far for your viewing enjoyment.
```py
import pickle
import imagetext_py
lc = pickle.load(open('lc', 'rb'))
imagetext_py.FontDB.LoadSystemFonts()
imagetext_py.FontDB.LoadFromDir('.')
# ls /usr/share/fonts/noto/ | grep Sans | grep Regular | sed 's/.ttf//g' | xargs echo | fish_clipboard_copy
font = imagetext_py.FontDB.Query('NotoSansAdlam-Regular NotoSansAdlamUnjoined-Regular NotoSansAnatolianHieroglyphs-Regular NotoSansArabic-Regular NotoSansArmenian-Regular NotoSansAvestan-Regular NotoSansBalinese-Regular NotoSansBamum-Regular NotoSansBassaVah-Regular NotoSansBatak-Regular NotoSansBengali-Regular NotoSansBengaliUI-Regular NotoSansBhaiksuki-Regular NotoSansBrahmi-Regular NotoSansBuginese-Regular NotoSansBuhid-Regular NotoSansCanadianAboriginal-Regular NotoSansCarian-Regular NotoSansCaucasianAlbanian-Regular NotoSansChakma-Regular NotoSansCham-Regular NotoSansCherokee-Regular NotoSansChorasmian-Regular NotoSansCoptic-Regular NotoSansCuneiform-Regular NotoSansCypriot-Regular NotoSansCyproMinoan-Regular NotoSansDeseret-Regular NotoSansDevanagari-Regular NotoSansDevanagariUI-Regular NotoSansDuployan-Regular NotoSansEgyptianHieroglyphs-Regular NotoSansElbasan-Regular NotoSansElymaic-Regular NotoSansEthiopic-Regular NotoSansGeorgian-Regular NotoSansGlagolitic-Regular NotoSansGothic-Regular NotoSansGrantha-Regular NotoSansGujarati-Regular NotoSansGujaratiUI-Regular NotoSansGunjalaGondi-Regular NotoSansGurmukhi-Regular NotoSansGurmukhiUI-Regular NotoSansHanifiRohingya-Regular NotoSansHanunoo-Regular NotoSansHatran-Regular NotoSansHebrew-Regular NotoSansImperialAramaic-Regular NotoSansIndicSiyaqNumbers-Regular NotoSansInscriptionalPahlavi-Regular NotoSansInscriptionalParthian-Regular NotoSansJavanese-Regular NotoSansKaithi-Regular NotoSansKannada-Regular NotoSansKannadaUI-Regular NotoSansKawi-Regular NotoSansKayahLi-Regular NotoSansKharoshthi-Regular NotoSansKhmer-Regular NotoSansKhojki-Regular NotoSansKhudawadi-Regular NotoSansLaoLooped-Regular NotoSansLao-Regular NotoSansLepcha-Regular NotoSansLimbu-Regular NotoSansLinearA-Regular NotoSansLinearB-Regular NotoSansLisu-Regular NotoSansLycian-Regular NotoSansLydian-Regular NotoSansMahajani-Regular NotoSansMalayalam-Regular NotoSansMalayalamUI-Regular NotoSansMandaic-Regular NotoSansManichaean-Regular NotoSansMarchen-Regular NotoSansMasaramGondi-Regular NotoSansMath-Regular NotoSansMayanNumerals-Regular NotoSansMedefaidrin-Regular NotoSansMeeteiMayek-Regular NotoSansMendeKikakui-Regular NotoSansMeroitic-Regular NotoSansMiao-Regular NotoSansModi-Regular NotoSansMongolian-Regular NotoSansMono-Regular NotoSansMro-Regular NotoSansMultani-Regular NotoSansMyanmar-Regular NotoSansNabataean-Regular NotoSansNagMundari-Regular NotoSansNandinagari-Regular NotoSansNewa-Regular NotoSansNewTaiLue-Regular NotoSansNKo-Regular NotoSansNKoUnjoined-Regular NotoSansNushu-Regular NotoSansOgham-Regular NotoSansOlChiki-Regular NotoSansOldHungarian-Regular NotoSansOldItalic-Regular NotoSansOldNorthArabian-Regular NotoSansOldPermic-Regular NotoSansOldPersian-Regular NotoSansOldSogdian-Regular NotoSansOldSouthArabian-Regular NotoSansOldTurkic-Regular NotoSansOriya-Regular NotoSansOsage-Regular NotoSansOsmanya-Regular NotoSansPahawhHmong-Regular NotoSansPalmyrene-Regular NotoSansPauCinHau-Regular NotoSansPhags-Pa-Regular NotoSansPhoenician-Regular NotoSansPsalterPahlavi-Regular NotoSans-Regular NotoSansRejang-Regular NotoSansRunic-Regular NotoSansSamaritan-Regular NotoSansSaurashtra-Regular NotoSansSharada-Regular NotoSansShavian-Regular NotoSansSiddham-Regular NotoSansSignWriting-Regular NotoSansSinhala-Regular NotoSansSinhalaUI-Regular NotoSansSogdian-Regular NotoSansSoraSompeng-Regular NotoSansSoyombo-Regular NotoSansSundanese-Regular NotoSansSylotiNagri-Regular NotoSansSymbols2-Regular NotoSansSymbols-Regular NotoSansSyriacEastern-Regular NotoSansSyriac-Regular NotoSansSyriacWestern-Regular NotoSansTagalog-Regular NotoSansTagbanwa-Regular NotoSansTaiLe-Regular NotoSansTaiTham-Regular NotoSansTaiViet-Regular NotoSansTakri-Regular NotoSansTamil-Regular NotoSansTamilSupplement-Regular NotoSansTamilUI-Regular NotoSansTangsa-Regular NotoSansTelugu-Regular NotoSansTeluguUI-Regular NotoSansTest-Regular NotoSansThaana-Regular NotoSansThaiLooped-Regular NotoSansThai-Regular NotoSansTifinaghAdrar-Regular NotoSansTifinaghAgrawImazighen-Regular NotoSansTifinaghAhaggar-Regular NotoSansTifinaghAir-Regular NotoSansTifinaghAPT-Regular NotoSansTifinaghAzawagh-Regular NotoSansTifinaghGhat-Regular NotoSansTifinaghHawad-Regular NotoSansTifinagh-Regular NotoSansTifinaghRhissaIxa-Regular NotoSansTifinaghSIL-Regular NotoSansTifinaghTawellemmet-Regular NotoSansTirhuta-Regular NotoSansUgaritic-Regular NotoSansVai-Regular NotoSansVithkuqi-Regular NotoSansWancho-Regular NotoSansWarangCiti-Regular NotoSansYi-Regular NotoSansZanabazarSquare-Regular SourceHanSansCN-Regular PlangothicP2-Regular') # Rip
black = imagetext_py.Paint.Color((0, 0, 0, 255))
for j in range(3):
for i in range(6):
cv = imagetext_py.Canvas(2560, 3328, (255, 255, 255, 255))
for k in range(80 * 104):
x = k % 80
y = k // 80
p = 80 * i + x + (104 * j + y) * 80 * 6 # this works, trust me
if p < len(lc):
imagetext_py.draw_text(canvas=cv,
text=chr(lc[p][0]),
x=32*x, y=32*y,
size=48,
fill=black,
font=font,
draw_emojis=True)
cv.save(str(6 * j + i) + '.png')
```
Maybe I'll try just printing every emoji or something.

View file

@ -0,0 +1,225 @@
---
title: "Analyzing My Packages"
date: 2020-11-25 22:03:34 -0600
draft: true
type: "post"
tags: ["Linux"]
---
Recently, I ran `yay -Ps`, and I was horrified to discover that I have a total of **1614** packages installed, including **193** explicitly installed packages. How did my slim and lean Arch install become so bloated? I thought it would be a good exercise to go through my list of explicity installed packages and figure out why each of them was installed.
## Core
### Essentials
- `base`
- `bash-completion`
- `linux`
- `linux-firmware`
- `linux-headers`
- `sudo`
### Arch stuff
- `arch-install-scripts`
- `archlinux-wallpaper`
- `pacgraph`
- `reflector`
- `yay-bin`
### Boot and dual-boot stuff
- `efibootmgr`
- `grub`
- `intel-ucode`
- `ntfs-3g`
- `os-prober`
### CLI tools
- `bpytop`
- `emacs`
- `fish`
- `fzf`
- `htop`
- `hyperfine`
- `nano`
- `neofetch`
- `tldr`
- `vi`
- `vim`
- `youtube-dl`
## Graphics
### Graphics
- `intel-media-driver`
- `libva-utils`
- `vulkan-intel`
- `weston`
- `xdotool`
- `xf86-video-nouveau`
- `xorg-server-xwayland`
- `xorg-xbacklight`
- `xorg-xhost`
### KDE Plasma
- `breeze-grub`
- `dolphin-plugins`
- `kcm-wacomtablet`
- Everything in `kde-applications-meta` minus `kde-accessibility-meta`, `kde-education-meta`, and `kde-games-meta` (`kde-applications-meta` comes with about 70 applications just starting with K, so you need to remove the heavy hitters to reduce bloat)
- `plasma-meta`
- `plasma-wayland-session`
- `packagekit-qt5`
- `xdg-user-dirs`
### i3
- `dmenu`
- `feh`
- `i3-wm`
- `i3lock`
- `i3status`
### Web browsers
- `brave-bin`
- `browsh-bin`
- `chromium`
- `firefox`
- `links`
- `lynx`
### Awesome free and open-source apps
- `audacity`
- `blender`
- `gimp`
- `gparted`
- `inkscape`
- `krita`
- `libreoffice-fresh`
- `mpv`
- `obs-studio`
- `vscodium-bin`
- `xournalpp`
### Games and emulators
- `2048-py`
- `dolphin-emu`
- Everything in the `libretro` package group.
- `supertux`
- `supertuxkart`
- `yuzu-mainline-bin`
## Developer
### Stuff in `base-devel`
- `autoconf`
- `automake`
- `bison`
- `fakeroot`
- `flex`
- `groff`
- `m4`
- `make`
- `patch`
- `pkgconf`
### Git
- `git`
- `github-cli`
- `github-desktop-bin`
### Java
- `eclipse-java-bin`
- `jdk-openjdk`
### Python
- `jupyterlab`
- `pypy3`
- `python-pip`
- `python-poetry`
- `python-pylint`
- `python-tox`
- `python-wheel`
- `sagemath`
- `sagemath-jupyter`
- `tk`
- `twine`
### Ruby
- `ruby`
- `ruby-bundler`
- `rubygems`
### zsh
- `zsh`
- `zsh-autosuggestions`
- `zsh-completions`
- `zsh-syntax-highlighting`
- `powerline`
- `powerline-fonts`
## Other useful stuff
### Laptop tools
- `libinput_gestures_qt`
- `onboard`
### Printing
- `cups`
- `hplip`
### Networking
- `bluez-utils`
- `bridge-utils`
- `dnsmasq`
- `ebtables`
- `freerdp`
- `networkmanager`
- `net-tools`
## Pretending my computer is running something other than Arch
### Virtualization
- `docker`
- `edk2-ovmf`
- `libguestfs`
- `libvirt`
- `lxc`
- `lxd`
- `qemu`
- `vagrant`
- `virt-manager`
- `virtualbox`
- `x11docker`
### Wine
- `playonlinux`
- `wine`
- `wine-gecko`
- `wine-mono`
- `winetricks`
## Miscellaneous
### Hacking
- `checkra1n-cli`
- `fusee-launcher-git`
- `ns-usbloader`
- `nx-udev`
### Proprietary stuff
- `unrar`
- `zoom`
### Everything else I couldn't categorize
- `cool-retro-term`
- `cryfs`
- `flatpak`
- `noto-fonts-emoji`
- `obs-v4l2sink`
- `pulseaudio-bluetooth`
- `usbutils`
- `v4l2loopback-dkms`

View file

@ -1,13 +1,14 @@
---
title: "Answering Forgejo Federation Questions"
date: 2023-01-10T21:47:26Z
draft: true
description: "This post answers some commonly asked questions about Forgejo federation"
type: "post"
tags: ["federation", "forgejo", "activitypub"]
---
*Note: Also published on the [Forgejo blog](https://forgejo.org/2023-01-10-answering-forgejo-federation-questions/)*
### What is federation?
Federation is about creating open protocols so that different servers can communicate with each other. Once Forgejo gains federation support via the [ForgeFed](https://forgefed.org/) protocol, you'll be able to do things like create issues for projects on other Forgejo instances without creating an account on that instance. But federation doesn't just solve the problem of having to create many Forgejo accounts. The power of federation comes from building an interoperable ecosystem, since any other code collaboration site or development tool can also add ForgeFed support. Just look at GitHub: it's the epicenter of a giant ecosystem of apps and integrations and tools that cements GitHub's position. It's a textbook example of a walled garden. We want to create something similar, but in an open ecosystem where everything speaks the ForgeFed protocol, so you're never locked-in by which forge or code collaboration software that you use.

View file

@ -9,7 +9,7 @@ tags: ["Linux", "Rant"]
*Originally posted on my [old blog](https://git.exozy.me/a/blog/src/branch/main/_posts/2021-06-22-anti-window-manager.md)*
[KDE bloat](/posts/myth-bloat), [WMs rule](/posts/why-wms-suck). Therefore, we must use get rid of the DE in KDE and we are left with... everyone's favorite WM, [KWin](https://userbase.kde.org/KWin)!
KDE is bloated, but WMs are awesome. Therefore, we must use get rid of the DE in KDE and we are left with... everyone's favorite WM, [KWin](https://userbase.kde.org/KWin)!
There are only three easy steps. First, set up the environmental variables and start up D-Bus:

View file

@ -0,0 +1,32 @@
---
title: "April Fools' Day Puzzle"
date: 2024-04-02T20:04:55-04:00
description: "Another month, another puzzle"
type: "post"
tags: ["puzzle", "origami", "geometry"]
---
On April Fools' Day, the exozyme homepage was completely blank. Or was it? The puzzle is no longer up on that homepage, but you can still find it [here](https://blank.exozy.me). Good luck! The solution will be posted next month.
## Solution the origami puzzle
I accidentally screwed up the order of the tasks and placed the most hardest thing first and the easiest last... oops. I guess we'll start with the last task then.
First fold the paper into quarters to form a 4 by 4 grid. Now you can simply fold a 3 by 4 right triangle using this grid, and tuck away the excess paper. If you want an extra challenge, try folding the largest possible 3-4-5 triangle!
For the next task, [Locria Cyber](https://www.1a-insec.net) solved it and provided a helpful diagram:
![Fold the bottom edge up so the left corner meets the center vertical line](/img/equilateral.png)
Again, if you want another challenge, try folding the largest possible equilateral triangle.
Finally, the last task has multiple solutions. Here's the simplest one:
![Fold a 1 by 1 triangle and a 1 by 1/2 triangle, and their intersection point is at (1/3, 1/3)](/img/thirds-easy.png)
Locria Cyber found a [YouTube video](https://www.youtube.com/watch?v=fK0tcoCu8bk) with another solution which uses one fewer fold. Here's how it works:
![Uh... this one is complicated](/img/thirds-hard.png)
The yellow and teal triangles are similar, and the purple and orange triangles are similar. After some calculations using the similar triangles, you can show that the vertical side length of the purple triangle is 1/3.

View file

@ -0,0 +1,31 @@
---
title: "Arknights Review"
date: 2023-10-22T23:55:20Z
draft: true
description: "A review of the Chinese mobile game Arknights (明日方舟)"
type: "post"
tags: ["review", "game"]
---
I'm not aware of any internationally successful Chinese animes or mangas, but somehow several Chinese anime-inspired video games have managed to take the world by storm, namely Genshin Impact (there are some people in my dorm who play it, and play it loudly and intensely) and Arknights. Now Genshin Impact doesn't seem particularly interesting to me. But Arknights is a free-to-play tower-defense-RPG game with puzzle and strategy elements, so I thought it would be a fun way to improve my Mandarin and I gave it a try. In August while I was in China, I saw someone playing it during a train ride from Ningbo to Cangzhou, and I've also seen at least two other MIT students playing it, so it seemed worth trying out.
OK, so let's start with actually creating an account for the (Chinese version of the) game, which is already a huge pain. If you download the game from the Arknights website, you need a Chinese phone number when creating an account, which I don't have. I also considered playing the Taiwanese version of the game, but I don't want to struggle with reading traditional Chinese. The solution is to download the game from Bilibili, so you can use a Bilibili account to log in instead, which can use any international phone number. But now there's another obstacle: you need to verify your ID for some lousy CCP nonsense. Now I'm not a Chinese citizen, so I tried going through Bilibili's online form for verifying your ID for games (which is a separate form from verifying your ID for the Bilibili website for some stupid reason), but I guess they just ignored my request or something. Finally, I found [on Reddit that you can use Xi Jinping's ID for this](https://www.reddit.com/r/Bilibili/comments/s9nnte/bilibili_id_verification/htpuu3r/), but that seemed to risky so I used a different person's ID recommended in the same Reddit thread, and surprisingly, it actually worked! Now I just hope I don't get banned for this.
OK, with all of that nonsense out of the way, I can finally enjoy the game! First, there's a ridiculously long amount of intro cutscenes and tutorials, but after that, stuff got interesting.
First of all, the game is fairly grindy. There aren't many levels, and you have to do them over and over again to collect certain resources. The autodeploy helps, but it's still annoying. I think no game should make you do the same thing thrice, and it seems like repetitive grinding is the only way to collect certain resources. Another tedious aspect is the base-building stuff, which I think shouldn't be in the game in the first place. Which brings me to my next point: there are way too many damn currencies in this game, and there aren't many ways to convert between them. There's the normal currency, the currency for levelling up characters, a currency for recruiting new characters, *six* different currencies in the store, and it's very annoying and time-consuming to deal with all of this. At least it's easy to play the game without having to spend real money. I think you only need real money if you want to speed things up and do less grinding, but I'm not really in a rush for anything.
Moving on to the next rant: Arknights is not a puzzle game. The closest thing it has to puzzles are "paradox simulations", which are high-difficulty levels with only a few solutions, but the thing is, characters in Arknights mostly just have one use. There's no need to wrack your brain about how to use the characters in creative ways. You just do reasonable stuff, and if your characters have a high-enough level, you'll beat the level.
Another annoyance is that the retry loop is very long. If you make a mistake and lose a level, it takes quite a few annoying seconds to show the results page, restart the level, go through more loading screens, and then do everything you were doing before prior to the mistake just to get back to where you were before. I guess this just means I should plan things out better in advance though.
I've also run into a lot of race condition situations, where sometimes autodeploys just fail due to race conditions. I assume the autodeploy is fairly deterministic and uses the same RNG seed and such, but there's enough nondeterminism so that race conditions can and do happen. This also might be because often times when my characters are just barely leveled up enough to beat a level, I end up with very scuffed and complicated solutions involving lots of enemies just barely getting defeated right before they cross my gate.
Now for the good aspects of Arknights: it is indeed a very nicely-made and polished game, which is not surprising given how popular it is. The characters are mostly cute (but not really sexualized) and the story is adequate. I don't particularly care much about the story (and I don't think this game is a really and RPG either, since your actions don't influence the story), but I guess I should pay more attention to it since that's what will improve my Mandarin. Whatever.
I don't think I learned that much Mandarin from this game either, but it's not like playing a single game will instantly make me a Mandarin master. Given that I already knew enough Mandarin before playing the game to understand roughly what was going on, I wasn't expecting to learn that much new stuff anyways.
Subjective quesiton: How "Chinese" is this game? Personally, I felt like I was just playing an American or Japanese game but localized into Mandarin, so not very. But then again, this is a post-apocalyptic sci-fi-fantasy game, not an RPG set in dynastic China, so I wasn't expecting much in the first place. Most of the [OST](https://monster-siren.hypergryph.com/) is in English. It definitely seems like the developers put in a lot of effort to make the game have a global appeal.
One last fun question to ponder: given that Genshin Impact and Arknights have achieved a lot of popularity but a lot of people don't realize that they're Chinese games, will Chinese animes and mangas (I guess donghuas and manhuas would be more accurate terms here) also achieve international success in the next few years without most people even realizing it? There's a [very good video about the animation industry in China](https://www.youtube.com/watch?v=Xwx6i4IQcFw) that you should watch, so I'm just going to assume you watched it and roll on ahead. Currently, a lot of animation work is already contracted out to Chinese studios (fun fact: one episode of Avatar: The Last Airbender was animated by a North Korean studio), so there's definitely manpower available, and combine that with China's large population (which was recently surpassed by India). So I think we just need to wait and this will happen. My prediction is within the next five years. Of course there's the wild cards of whether China's economy will crash or if the CCP will invade Taiwan, but I consider both of those to be unlikely despite all the claims (hype?) that these are imminent. Then again I'm not an economist or political analyst, so maybe I don't know what I'm talking about. I created a reminder in my calender for exactly five years in the future, and we'll see how my three predictions unfold. 2028 just sounds scary. See you then.

View file

@ -0,0 +1,86 @@
---
title: "Asian Bayesian 2"
date: 2024-01-22T23:18:18-05:00
description: "Puns, probability, and more probability."
type: "post"
tags: ["math", "probability", "asian-bayesian-series"]
---
{{< katex >}}
*This is a sequel to [Asian Bayesian](/posts/asian-bayesian)*
I saw a really cool probability problem posted by Kartik Chandra on the MIT Mastodon instance:
> Suppose two Bayesians, Alice and Bob, decide to put on a variety show where they take turns tossing a biased coin and announcing outcomes to a live studio audience. (Bayesians love this kind of thing--it keeps them entertained for hours...)
>
> Unfortunately, just as Alice goes on stage, she realizes with dread that she forgot to bring the coin. Thinking on her feet, she mimes pulling a tiny imaginary coin out of her pocket, and says "This is a biased coin!" It works--the audience buys it and the crowd goes wild.
>
> Breathing a sigh of relief, Alice mimes tossing the pretend coin and randomly announces "heads" or "tails" to the audience. Then, she hands the "coin" to Bob, who catches on and also mimes a toss. (This has just turned into a Bayesian improv show.)
>
> But now Bob has a problem. Should he say "heads" or "tails"? He could choose uniformly at random, but the audience will get suspicious if the coin appears to be fair, or if his tosses don't match the statistics of Alice's. How can he keep up the charade of a *biased* coin?
>
> Here's what Bob does. In the spirit of "yes, and...," he infers the coin's bias based on Alice's reported outcome (say, with a uniform prior) and samples a fresh outcome with that inferred bias. So if Alice said "heads," Bob would be a bit likelier to say "heads" as well.
>
> Then Alice takes the coin back and does the same, freshly inferring the coin's bias from the past *two* tosses. In this way, the two actors take turns announcing simulated outcomes to the oblivious audience, while building a shared understanding of the coin's bias.
>
> Okay, so what happens? How can we characterize the sequence of outcomes? Intuitively, we might expect either a "rich-get-richer" effect where they end up repeating heads or tails. Or we might expect a "regression-to-the-mean" where they converge to simulating a fair coin.
Honestly, I prefer Bayesian variety shows to Asian variety shows. OK, bad puns aside, let's dig into this problem!
First off, let's try an example. At the beginning, Alice just chooses $H$ or $T$ with $\frac{1}{2}$ probability. Let's say Alice chooses $H$. Now Bob should be more inclined to say $H$, but by how much? The problem states that Bob has a uniform prior, which basically means that initially he believes the bias of the coin for heads could anything between 0 and 1 uniformly at random. Once he sees Alice choose $H$, he has to update his beliefs. Now his probability of choosing another $H$ is
\\[P(HH|H) = \frac{P(HH)}{P(H)}.\\]
You might be tempted to just say $P(H) = \frac{1}{2}$ and $P(HH) = \frac{1}{4}$ but Bob doesn't actually know for sure what the bias of the coin is. To correctly compute these values, imagine we have the unit interval $[0, 1]$ and Bob first chooses uniformly at random a point in the interval, which corresponds to the bias of the coin for heads. Now, for each flip, Bob chooses another point uniformly at random on the interval and checks if the point is less than the bias point. If so, the flip is $H$ and otherwise, $T$.
Let's compute $P(H)$. This corresponds to choosing a bias point and then a flip point. Imagine that we chose two point locations first, and then assigned at random one to be the bias point and one to be the flip point. Then obviously there's a $\frac{1}{2}$ chance that the bias point is larger than the flip point, so $P(H) = \frac{1}{2}$. For $P(HH)$, we will choose a bias point and then two flip points. This is equivalent to choosing the three points, and then assigning one at random to be the bias point. There's only a $\frac{1}{3}$ chance that the bias point will be the highest, so thus, $P(HH) = \frac{1}{3}$. Therefore, we have
\\[P(HH|H) = \frac{1/3}{1/2} = \frac{2}{3}.\\]
## The general case
Cool. Now say that the game goes on for a while, and there have been $x$ heads and $y$ tails in some order. Now it's someone's turn, and they've updated their beliefs about the bias of the coin based on the previous $x+y$ flips. Note that they would obtain the same final belief if they received the knowledge of all $x+y$ flips at the same time, compared to receiving the knowledge about the flips one at a time. If they receive all the knowledge at the same time, then the order of the $x+y$ flips is no longer important. The only thing we care about is that there were $x$ heads and $y$ tails. Therefore, the probability of choosing another $H$ based on this information is
\\[P(\\#H=x+1,\\#T=y|\\#H=x,\\#T=y) = \frac{P(\\#H=x+1,\\#T=y)}{P(\\#H=x,\\#T=y)}.\\]
Alright, now to calculate the two probabilities on the right, we can use a similar method as above. Let's find $P(\\#H=x,\\#T=y)$. Imagine choosing a bias point, and then $x+y$ flip points. We'd like the bias point to be greater than $x$ points and smaller than the $y$ points, because that would correspond to $x$ heads and $y$ tails. Again, we can view this instead as choosing $x+y+1$ point locations, and assign the bias point and the $x+y$ flip points to those locations. There are a total of $(x+y+1)!$ ways to do this, but only $x!y!$ of them have $x$ head points, a bias point, and then $y$ tail points. Thus, $P(\\#H=x,\\#T=y) = \frac{x!y!}{(x+y+1)!}$. Similarly, we can compute that $P(\\#H=x+1,\\#T=y) = \frac{(x+1)!y!}{(x+y+2)!}$. Thus, we get
\\[P(\\#H=x+1,\\#T=y|\\#H=x,\\#T=y) = \frac{(x+1)!y!(x+y+1)!}{x!y!(x+y+2)!} = \frac{x+1}{x+y+2}.\\]
Now let's say Alice and Bob play this game $n = 6$ times and obtain the sequence $H, T, H, H, H, T$. What's the probability of this happening? Using our rule that we just derived, the probability of $H$ at a certain time is $\frac{x+1}{x+y+2}$ given that we've seen $x$ heads and $y$ tails so far. Thus, the probability of that sequence is
\\[\frac{1}{2} \frac{1}{3} \frac{2}{4} \frac{3}{5} \frac{4}{6} \frac{2}{7} = \frac{2!4!}{7!}.\\]
In general, let $k$ be the total number of heads in a sequence and $n-k$ be the total number of tails in the sequence. Then the probability of obtaining that sequence is
\\[\frac{k!(n-k)!}{(n+1)!}.\\]
Awesome!
## Pólya's urn
Now let's consider a different problem, which is a special case of the Pólya's urn model. Alice and Bob have an urn, which contains 1 hazel ball and 1 teal ball. Alice and Bob will take turns drawing a ball from the urn. If they draw a hazel ball, they will return the hazel ball to the urn and additionally add another hazel ball. If they draw a teal ball, they will return the teal ball to the urn and add another teal ball. So what happens over $n$ drawings?
Assume there are $x$ hazel balls and $y$ teal balls in the urn. Then the probability of drawing a hazel ball is obviously $\frac{x}{x+y}$. Let's say Alice and Bob play this $n = 6$ times and obtain $H, T, H, H, H, T$. We can easily compute the probability of this, which is
\\[\frac{1}{2} \frac{1}{3} \frac{2}{4} \frac{3}{5} \frac{4}{6} \frac{2}{7} = \frac{2!4!}{7!}.\\]
Whoa! The same thing as before? This game gives the exact same distribution of sequences as the fake coin toss game!
## A third equivalent game
Those two answers both have a very interesting property: the probability of a sequence doesn't depend on the order of the heads and tails or hazel balls and teal balls. The only thing that matters is the number of $H$s. All sequences of $k$ $H$s and $n-k$ $T$s are equally likely. In the coin game, from the point of view of the audience, it looks like Alice and Bob chose a bias first, and then flipped the coin $n$ times *without changing the bias*. But what bias does it appear like that picked initially?
The answer is that it looks like they choose the bias of the coin uniformly at random, and then proceeded to flip it $n$ times. Let's compute the probability of obtaining a specific sequence. Actually, we've already done that above! The probability of obtaining a sequence with $x$ heads and $y$ tails is $\frac{x!y!}{(x+y+1)!}$, or equivalently, the probability of obtaining $k$ heads and $n-k$ tails is $\frac{k!(n-k)!}{(n+1)!}$. Nice, this matches the answer that we got in the previous two games. So yes, Alice and Bob can successfully use their fake coin process to deceive the audience!
All these games are connected to the beta distribution, which showed up in the previous Asian Bayesian post too. (Somehow, I managed to get through this entire post without doing a single integral!)
## Further reading
- https://mastodon.mit.edu/@kach/111795995604618565 (The fediverse post that started this all!)
- https://web.stanford.edu/class/archive/cs/cs109/cs109.1212/lectureNotes/LN21_beta.pdf
- https://www.mit.edu/~jeffery/gamma_beta.pdf

View file

@ -0,0 +1,131 @@
---
title: "Asian Bayesian"
date: 2023-12-20T03:36:43Z
description: "Puns, game theory, and the loss of precision."
type: "post"
tags: ["math", "game-theory", "probability", "numerical-computing", "bad-code", "asian-bayesian-series"]
---
{{< katex >}}
{{< sagecell >}}
Recently, I noticed that "Bayesian", as in Bayesian statistics or Bayesian inference, sounds very close to "Asian". Pun potential!
"I prefer Bayesian models over Asian models."
"All the countries are using so much game theory to strategize for the [Asian Games](https://en.wikipedia.org/wiki/Asian_Games)... more like Bayesian games!"
"Consider a game where the players are $N$ Asians trying to get into MIT. Each Asian has a number randomly chosen uniformly between $0$ and $1$, and each Asian only knows their own number. MIT will accept the $M$ Asians who apply with the highest numbers. If an Asian applies and gets rejected, they receive $-1$ utility. If they apply and get accepted, they receive $A-1$ utility. Otherwise, they receive $0$ utility. What's the symmetric Bayesian Nash equilibrium, or should I say, Asian Nash equilibrium, in this game?"
Bad puns aside, let's actually attempt this game theory problem. At a symmetric Bayesian Nash equilibrium, each player has the same strategy, and they don't expect to get more utility by switching to a different strategy. Intuitively, it makes sense that this common strategy should be to apply if your number is above a certain cutoff $k$, and otherwise don't apply. It makes sense that the cutoff would probably be somewhere around $\frac{N-M}{N}$.
Let's say you are some player with number $x$. Your expected utility increases as $x$ increases, because you will have a higher and higher probability $p(x)$ of getting accepted. You should apply if your expected utility is greater than $0$.
\\begin{align}
(A-1)p(x)+(-1)(1-p(x)) &> 0 \\\\
Ap(x) &> 1
\\end{align}
Thus, you should apply if the probability of getting accepted $p(x)$ is greater than $\frac{1}{A}$. Thus, our cutoff $k$ is when $p(k) = \frac{1}{A}$.
Now what function is $p(x)$? You will be accepted if you are in the top $M$ highest players who apply. If all players follow the common strategy of applying above the cutoff, then you will be accepted if your number is in the top $M$ numbers, because all players will numbers above you will apply. Thus, $p(x)$ is the probability that the $M$th highest number among all $N$ numbers is less than or equal to $x$.
Now time for some fun calculus! Assume that the $M$ highest number falls in a tiny interval $[y, y+dy]$ for some $y \leq x$. Then there are $M-1$ players with higher numbers, and $N-M$ players with lower numbers. Each of the $M-1$ high players have a probability roughly $1-y$ of having a higher number. Each of the $N-M$ lower players have a probability of roughly $y$ of having a lower number. Additionally, there are $\frac{(M-1)!(N-M)!}{N!}$ ways to choose the $M-1$ high players and $N-M$ low players among the $N$ players. Thus, the probability that the $M$ highest number falls in the interval $[y, y+dy]$ is roughly
\\begin{equation}
\frac{(1-y)^{M-1}y^{N-M}N!}{(N-M)!(M-1)!} dy.
\\end{equation}
We can now integrate this expression over all $y$ to compute $p(x)$!
\\begin{equation}
p(x) = \int_0^x \frac{(1-y)^{M-1}y^{N-M}N!}{(N-M)!(M-1)!} dy.
\\end{equation}
Using the equation from above, $p(k) = \frac{1}{A}$, we get
\\begin{equation}
\frac{1}{A} = \int_0^k \frac{(1-y)^{M-1}y^{N-M}N!}{(N-M)!(M-1)!} dy.
\\end{equation}
This integral can be computed because it's just a polynomial, but then you have to find the root of a high-degree polynomial, so there's probably no explicit formula for the cutoff $k$. However, we can solve it numerically using SageMath!
{{< sagescript >}}
from sage.symbolic.integration.integral import definite_integral
def f(N, M, A):
k = var('k')
return find_root(factorial(N-M) * factorial(M-1) / factorial(N) / A == definite_integral(x^(N-M)*(1-x)^(M-1), x, 0, k), 0, 1)
def test(N, M, A):
print(f(N, M, A), n((N-M)/N))
print('Actual, Estimate')
test(10, 4, 10)
test(10, 2, 10)
test(10, 8, 10)
test(100, 50, 10)
{{< /sagescript >}}
The first three answers seem reasonable, but the fourth one is totally wack! Only one third of the players applying when half of them can get in? What's going on?
The culprit is loss-of-precision. The left side blows up to gigantic numbers, while the right side becomes a high-degree polynomial. If we move the factorials to inside the integral, we get much more reasonable results.
{{< sagescript >}}
from sage.symbolic.integration.integral import definite_integral
def f(N, M, A):
k = var('k')
return find_root(factorial(N-M) * factorial(M-1) / factorial(N) / A == definite_integral(x^(N-M)*(1-x)^(M-1), x, 0, k), 0, 1)
def g(N, M, A):
k = var('k')
p = definite_integral(x^(N-M)*(1-x)^(M-1) * factorial(N) / factorial(N-M) / factorial(M-1), x, 0, k)
return find_root(1 / A == p, 0, 1)
def test(N, M, A):
print(f(N, M, A), g(N, M, A), n((N-M)/N))
print('Wrong, Fixed, Estimate')
test(10, 4, 10)
test(10, 2, 10)
test(10, 8, 10)
test(100, 50, 10)
{{< /sagescript >}}
Much better! Try testing out some other values of $N, M, A$ to see what happens.
Also, using math lingo, $p(x)$ is actually the cumulative distribution for the beta distribution, so we can also use SageMath's [built-in functions](https://doc.sagemath.org/html/en/reference/probability/sage/probability/probability_distribution.html#sage.probability.probability_distribution.RealDistribution.cum_distribution_function) to compute $k$ instead of writing out all the factorials and stuff.
{{< sagescript >}}
from sage.symbolic.integration.integral import definite_integral
def f(N, M, A):
k = var('k')
return find_root(factorial(N-M) * factorial(M-1) / factorial(N) / A == definite_integral(x^(N-M)*(1-x)^(M-1), x, 0, k), 0, 1)
def g(N, M, A):
k = var('k')
p = definite_integral(x^(N-M)*(1-x)^(M-1) * factorial(N) / factorial(N-M) / factorial(M-1), x, 0, k)
return find_root(1 / A == p, 0, 1)
def h(N, M, A):
return RealDistribution('beta', [N-M+1, M]).cum_distribution_function_inv(1/A)
def test(N, M, A):
print(f(N, M, A), g(N, M, A), h(N, M, A), n((N-M)/N))
print('Wrong, Fixed, Using beta distribution, Estimate')
test(10, 4, 10)
test(10, 2, 10)
test(10, 8, 10)
test(100, 50, 10)
{{< /sagescript >}}
As you can see, our own implementation still has some precision issues, and doesn't quite match the results from using SageMath's beta distribution, but it's better than our first attempt. Lesson learned: leave numerical computation to the experts and use the built-in functions whenever possible.
Fun story about SageMath: I participated in the Purple Comet math team contest a few years ago, and this contest has a [bizarre rule](https://purplecomet.org/?action=information/showrules) where you're allowed to use computers as long as you don't access the internet. Thus, I just wrote a ton of SageMath code and blasted through the problems, and somehow one year, my school's team got all the questions correct and tied for first place.
Anyways, that's all for this post, which may have actually been an excuse to mess around with [KaTeX](https://katex.org/) and [SageMathCell](https://sagecell.sagemath.org/). I've been using [Typst](https://typst.app/) (less boilerplate!) and [WolframAlpha](https://www.wolframalpha.com/) a lot lately and nearly forgot how to use LaTeX and SageMath, so this blog post took a lot of trial and error. Oh, and if you want to see more fun with SageMathCell, check out [this nice article](https://grossack.site/2023/11/08/37-median.html) about why 37 is the median value for the second prime factor of an integer!

View file

@ -4,7 +4,7 @@ date: 2023-01-05T22:43:56Z
draft: true
description: "More fictional misadventures of the LHWHS Computer Science Club"
type: "post"
tags: ["fiction", "story", "lwhws", "adventure", "humor", "satire", "fun", "cryptocurrency", "mastodon"]
tags: ["fiction", "story", "lwhws", "adventure", "humor", "satire", "cryptocurrency", "mastodon"]
---

View file

@ -0,0 +1,66 @@
---
title: "Azerbaijan"
date: 2023-02-25T05:20:13Z
description: "The one and only sequel to Beavers"
type: "post"
tags: ["humor", "fiction", "story", "lots-of-vowels-series"]
---
*This is the second story in the [Lots of Vowels Series](/tags/lots-of-vowels-series/)*
The long road from Tehran, Iran to Baku, Azerbaijan stretches a thousand kilometers across the unremittingly barren deserts of western Asia, filled with ancient intrigue, treachery, mystery, and let's be honest, just a lot of boredom and "are we there yet"s. Especially when you're trying to survive a 12-hour bus ride with two Taliban fighters, a Ukrainian ex-dictator, a Chinese anthropology professor, and a cute Pallas's cat who may or may not want to kill you.
Leiaou was a spunky anime girl from the Ryukyu Islands, with multiple bounties on her head from various governments, including Kazakhstan. It's a long story. Basically, she knew too much about Kazakhstan's plot to manipulate the FIFA World Cup bidding process, and the tyrannical Pallas's cats covertly puppeting the Kazakh government knew she had to be silenced. Leiaou was doomed--Kazakhstan's most feared assassin, a crafty Pallas's cat named Zhandos, was hot on her heels.
After weeks on the run, Leiaou found herself in Tehran boarding a decrepit bus that looked older than the Islamic Republic of Iran, headed for the distant and thrilling city of Baku, Azerbaijan. She was filled with excitement and anticipation--all that laid before her were sunny days exploring new lands!
Little did Leiaou know that her journey was not going to be a fun little merry-go-round ride. On board were a colorful cast of characters: an ancient-looking bus driver who reminisced about the jolly days before the Soviet Union, two Taliban fighters cloaked in mystery, a Ukrainian ex-dictator in a slick suit, a Chinese chap who wanted to tape-record everyone's languages for some research project, and... him!
Leiaou had a special talent of recognizing trouble when it crawled in front of her on four legs, and alarm sirens instantly blared inside her head upon stepping inside the bus. She saw right through Zhandos's 10 layers of raincoats, which made him look like a hyperventilating nesting doll and probably hid a gnarly assortment of weapons for bringing about her end. Still, Leiaou pretended her doom wasn't sitting right there at the back of the bus, and she proceeded with business as usual.
The boredom set in quickly. The Chinese anthropology professor soon began blabbering in an infinite loop about the fascinating languages of Azerbaijan. The Taliban fighters joked about how they'd become millionaires in Azerbaijan as they pulled out a poker set. The Ukrainian joined in the game and bet his expensive custom-tailored suit. The bus driver even started singing about the vibrant natural landscapes of Azerbaijan in a soothingly sandpaper voice.
Unfortunately, Azerbaijan simply does not exist.
You think I'm wrong? Have you ever heard of Azerbaijan?
If you said yes, please stop lying.
Obviously, the only correct answer is no. Who has? In reality, "Azerbaijan" is actually just a fiction concocted by Kazakhstan to rig the FIFA World Cup bidding process in their favor. After all, what's more evil than manufacturing your very own imaginary sovereign state out of thin air to win more votes?
Now you know the truth.
Azerbaijan simply does not exist.
Zhandos was also readily aware of the truth. He had no doubt that "Azerbaijan" was a nothing more than Kazakhstan's brilliant Pallas's cats gaslighting the entire world. Genius! A masterclass in gaslighting! He patiently unpacked a blender with razor-sharp blades from his second outermost raincoat, and plugged it into one of the bus's power outlets. Instantly, the bus's already-sluggish speed halved, and everyone stared at the driver, who stared at the road, because he was a responsible driver. Guiltily, Zhandos unplugged the blender.
The black hole that was the poker game had now engulfed Leiaou and the Chinese anthropology professor and even Zhandos. The thrill! The Taliban bros were losing left and right of what was left of their money, but everyone was having tons of fun, which we all know is what matters. This round, the flop was all aces. Leiaou had the final ace, the Ace of Spades, and bet all her chips. One of the Taliban fighters accused her of bluffing and bet his entire arm. The other Taliban dude bet both his arms. Zhandos bet all of his raincoats (including a blender!). The anthropology professor bet all the languages in Azerbaijan. The Ukrainian bet the entire country of Azerbaijan.
The fourth dealt card was a King of Hearts and the fifth a Queen of Hearts, and after a final round of everyone accusing everyone else of bluffing and/or not being able to fulfill their bets, the suspense crescendoed with everyone revealing their cards. Zhandos had the Jack and 10 of Hearts--a Royal Flush!--and the entire bus erupted into chaos. The bus driver reminded everyone to stay calm and civil so he could focus on the road.
Zhandos had now won "Azerbaijan" (and some other stuff), and he didn't quite know what to do. After all, "Azerbaijan" didn't even exist! But how could all the other passengers be so naive and ignorant about the truth of their destination? Oh right, the whole point of this "Azerbaijan" nonsense is so that everyone mistakenly thinks it exists! But if everyone thinks "Azerbaijan" exists, then does it exist? Screw this philosophy nonsense, Zhandos was here to have some fun killing people, not ponder the intricacies of epistemology. With that, he gingerly extracted a poison-tipped rod of uncooked spaghetti from his third outermost raincoat, and pointed the murder weapon straight at Leiaou.
If it weren't for the Chinese anthropology professor, Leiaou would have been dead meat. The spaghetti instantly piqued the interest of the professor, who began incessantly questioning Zhandos about the cuisine of Azerbaijan, to the point where Zhandos really just wanted to stab the professor in the liver and eat it. Actually, not the second part. But that would blow his cover, and Zhandos knew he couldn't let Leiaou find out he was also on the bus. After all, Leiaou looked so relaxed and casual--there was no way she'd be like that if she recognized Zhandos, right?
The bus driver announced to everyone that they would only need to hold their bladders for another half hour and they'd be at Baku, Azerbaijan, and Zhandos had to act fast. But the doubt! It began as just a slight itch deep inside the back of his brain, but it spread virally, like a cringy internet meme. What if "Azerbaijan" really did exist? And even if it didn't really exist, did the fact that everyone believed it exists imply that it did exist? Did this even matter? Does the "Azerbaijani" government want to arrest me? Does the "Azerbaijani" government know that I am inside "Azerbaijan" right now? Am I having a panic attack? Can a fictional government arrest a real person? Can a collectively hallucinated government arrest a person? What is it like to be arrested by a fictional government? What is the inside of a fictional prison like? What kind of fictional food do they have inside fictional prisons?
No. "Azerbaijan" simply does not exist and never did exist.
But what if it does? Thoughts of "Azerbaijani" police and soldiers arresting Zhandos and throwing him inside a prison where the only food option is mayonnaise-flavored ice cream overwhelmed Zhandos's brain. No! No!
He glanced outside the bus window, dazed. Sand. Wildgrass. Dust. Plains. Endless plains. Wind. Well, he couldn't actually see the wind, so he wasn't sure if the wind existed, even though the grass was swaying.
Suddenly, sand made way to concrete, and an entire city rose out of the desert. They were here! "Baku", capital of "Azerbaijan". The passengers all shuffled off the bus, and that's when the shock hit them.
Azerbaijan simply does not exist.
"Baku" was just a giant cluttered heap of old scraps and outdated tech collected over years in some kind of bizarre Soviet-style scrapyard project gone wrong. A few exhausted locals walked by, chatting in Kazakh. The evidence was there, right there in front of their faces. Azerbaijan simply does not exist.
Zhandos's philosophical crisis evaporated instantly. So he was right all along! Azerbaijan really didn't exist! Hooray! Now all he had to do was murder Leiaou--two Kazakh agents suddenly apprehended Zhandos and told him he was under arrest for failing to assassinate Leiaou and betraying the great nation of Kazakhstan! Hip, hip, hooray!
"I'm sorry! Don't take me to prison!" Zhandos shrieked, so the Kazakh agents prepared to stuff a dead frog into his throat to silence his screaming. Zhandos managed to squeeze in one final yelp, "And please don't only serve me mayonnaise-flavored ice cream in prison!"
And as for our plucky heroine Leiaou? She slyly slipped away from all this chaos, off to another adventure elsewhere--leaving behind nothing but fond memories of that dusty rode heading north towards a mythical land known only as... Azerbaijan.

View file

@ -0,0 +1,74 @@
---
title: "Beating the Time Limit"
date: 2023-01-25T01:30:50Z
description: "Predicting if your competitive programming solution will run under the time limit"
type: "post"
tags: ["competitive programming", "c++", "python", "algorithms", "tips", "performance"]
---
```cpp
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/stdc++.h>
using namespace std;
int main() {
int N = 1e5;
long long sum = 0;
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
sum += i^j;
}
}
cout << sum;
}
```
Hey you! We have here an O(N^2) algorithm with N = 10^5, doing a ridiculous number of operations. How long do you think it takes for this code to run on my laptop?
What do you think? A minute? Two minutes?
Well, I compiled and [hyperfined](https://github.com/sharkdp/hyperfine) it and here are the results:
```
Benchmark 1: ./main
Time (mean ± σ): 1.033 s ± 0.189 s [User: 1.029 s, System: 0.002 s]
Range (min … max): 0.910 s … 1.355 s 10 runs
```
That's right, it takes *around a second* to run.
If you've ever done any competitive programming, you're probably going "Wha????" right now.
A couple of days, I saw some competitive programming folks discussing the maximum N for which you can cram an O(N^2) solution under the time limit, typically 2 seconds. Is it 5000? 2000? USACO Guide says it's 7500?
100000?
The answer, of course, is it depends. It depends on a lot of things. What programming language are you using? What's the constant factor of your solution? Are you reading a blog post that's intentionally trying to trick you?
This particular code has an insanely low constant factor. Why? Because the compiler is smart, or at least because we told it to be smart. Those weird lines at the very top tell the compiler to grind hard for its best optimizations, [unroll loops](https://en.wikipedia.org/wiki/Loop_unrolling), and use AVX2 instructions.
AVX2 is the insane black magic here. They're a special set of overpowered instructions on your CPU that lets you do an operation on *8 values at the same time* (with many caveats). Without those two lines of special sauce, this program instead takes 30 seconds to run on my laptop.
However, for other problems, like those annoying dynamic programming problems with tons of states, your O(N^2) C++ solution might only work for N at most 2000, and maybe even lower for other languages.
A good rule of thumb is to count the number of basic operations, like additions, assignments, and loop iterations, that your solution is doing, and check if that's under 2*10^8 for C++. Java? 10^8. Python? Ugh, competitive programming is one of those things where Python becomes your worst enemy. You might not even be able to do 10^6 operations with Python.
Guess how long this Python translation of the above code takes:
```python
N = 10**5
sum = 0
for i in range(N):
for j in range(N):
sum += i^j
print(sum)
```
Turns out this Python code takes *840.48 seconds*, which is over 800 times slower than the optimized C++ version. Maybe using Python for competitive programming might be a bad idea...
Of course, these are all just tips for estimating your runtime. The only way to know for sure is to submit it and see what happens. Still, there might not always be time in a contest to spend an hour implementing a borderline slow solution just to watch it get time limit exceeded for half the test cases. Keep in mind though that contest writers usually don't want their problems to boil down to tedious constant factor optimization. In USACO, the best strategy is probably to spend a bit more time thinking of better solutions, and then if you're still stuck, just implement the borderline slow solution to get as many points as you can. For Codeforces, where the scoring is all or nothing, it might not be worth it spending the time at all implementing something that probably won't pass every test case.
If you thought that was fun, check out this [performance estimation game](https://computers-are-fast.github.io/)!

34
content/posts/beavers.md Normal file
View file

@ -0,0 +1,34 @@
---
title: "Beavers"
date: 2023-02-21T15:11:05Z
description: "An excuse for me to use the phrase military-grade beaver urinals"
type: "post"
tags: ["story", "fiction", "humor", "lots-of-vowels-series"]
---
*This is the first story in the [Lots of Vowels Series](/tags/lots-of-vowels-series/)*
Leiaou stood breathless, surveying the horror below her. There, stretched out in a long line, was a density of military-grade urinals that she had never seen before, not even in her worst nightmare. She knew of their terrible power, but hadn't expected them to be here, of all places. They were certainly not intended for human use. They were for beavers.
Beavers.
The mere thought of that word conjured up vivid images of a nation of Quebec separatists, dying polar bears, and the 2010 Vancouver Winter Olympics.
Speaking of sporting events, the FIFA World Cup was more rigged than the skeleton of a 3D model file, and Leiaou knew the only winning move was not to play. Unfortunately, the Kazakh government was not so wise.
Kazakhstan is the greatest country on Earth that you've never heard of. Founded in 1991 by a horde of anti-communist Pallas's cats (if you've never heard of Pallas's cats, you don't know what you're missing out on, and you should look it up right now), its only claim to fame has been renaming its capital city every other year, most recently to Crypto.com, for which it holds a Guinness World Record.
The bidding process for the 2026 FIFA World Cup had boiled down to only 2 cities: Crypto.com, Kazakhstan and London, Canada. Leiaou was a teenage anime girl-turned secret agent for the nominally infamous KGB (Kazakhstan Gang of Bullies, not to be confused with the Soviet KGB) and tasked with sabotaging their arch-nemesis Canada's secret army of genetically-enhanced chess grandmaster beavers.
The musky odor of beaver hair mingled with the acerbic fragrance of urine as Leiaou contemplated aborting the mission and defecting to Canada, before remembering that abortion is illegal in Kazakhstan. Suddenly. A strange, deafening sound jolted her senses and there she saw them. A whole stampede.
Beavers. Hundreds of them. All armed with portable nukes and urine with a pH of -5.
Leiaou prepared for the last moments of her life. She screamed and pleaded for mercy. She close her eyes and prayed to the omniscient Pallas's cats that puppeted the Kazakh government.
She opened her eyes, half-expecting to find herself in a parade of angelic Pallas's cats, but all she saw was a crowd of quizzical beavers.
Finally, one spoke, "What language are you speaking? We can only speak Canadian."

63
content/posts/billions.md Normal file
View file

@ -0,0 +1,63 @@
---
title: "Billions"
date: 2024-04-13T00:05:33-04:00
draft: true
description: "Some short stories inspired by random writing prompts"
type: "post"
tags: ["story", "fiction", "random"]
---
A few months ago, I wrote a random writing prompt generator that can generate 10 billion different prompts, hence the name. Here are two stories I wrote using those prompts. I didn't use any LLMs, except after I finished writing the story to see if they could generate anything good with the same writing prompt. Well, they can't. And I guess I really like fourth walls or something.
## I Love Impeachment
```
genre: horror
protagonist: the fourth wall
name: Trump
protagonist personality: super annoying and about to make everyone tear their ears off
companion: your crazy insane spirit animal
location: all over the entire freaking Earth
tool: your brain and only your brain
mission: getting impeached twice
arch-nemesis: cupcake wrappers
ironic plot twist ending: you are your own father due to time traveling
```
Once upon a time, there was a fourth wall for a film about time travel. Now this wasn't just any old casually broken fourth wall, this was Trump the fourth wall. Trump was notorious for being super annoying and about to make everyone tear their ears off, so no one dared to break him. It was oddly effective at impeding illegal immigration.
One day, Trump the fourth wall decided that he needed to make the history books, and he knew just how to do that: getting impeached twice. Not once, since Andrew Johnson and Bill Clinton had already beaten him to that, but twice. And even more impressively, Trump vowed to get impeached using only the power of his brain.
Actually, Trump had another assistant: his crazy insane spirit animal, a boisterous slug named Suckerberg. Trump and Suckerberg traveled the globe looking for impeachable offenses to create, but each time, they were stopped by their arch-nemesis, none other than the lowly cupcake wrapper. Picture this: Trump would waltz into Ukraine, demand the Ukrainian president to open an investigation into Hunter Biden, but in the nick of time, the Ukrainian president choked to death on a cupcake wrapper, foiling Trump's plans. How horrible and spooky!
Finally, Trump had enough. He returned back to the film set and carefully sat and pondered. Apparently they were making a time travel film or something? And they even wanted Trump the fourth wall himself to travel back in time?
Trump didn't waste any time. He jumped straight into time machine and cranked the dial back to 1865 to become president instead of Andrew Johnson. Unfortunately, Trump had intentionally forgotten how to read Arabic numerals since they were invented by the same people who had fielded Osama bin Laden, so he instead ended up in 1945, just in time to bump into his own mother. In a shocking turn of events, Trump realized that he was actually his own father! He was so astounded that he simply fainted to death and finally made the history books.
## The Worst Fourth Wall Ever
```
genre: romance
protagonist: the fourth wall (all occurrences of "you" refer to the reader of this story)
name: Elon Musk's mommy
protagonist personality: really, really, really weird, like seriously really weird
companion: Paimon from Genshin Impact after plastic surgery
location: the day after the fair
tool: a qubit that doesn't even work because it's not 2040 yet
mission: posting your Social Security number on Facebook
arch-nemesis: your BMI
ironic plot twist ending: the cake is a lie
```
Once upon a time, there was a fourth wall named Elon Musk's mommy. Elon Musk's mommy's role was to separate you from the story, which included her, so she had quite the tough job. Fortunately, she had a really, really, really weird, like seriously really weird personality which definitely helped with her existentially complicated job.
The day after the fair, which is really just an archaic idiom, Elon Musk's mommy bumped into Paimon from Genshin Impact, who had received plastic surgery to look like a camel. Paimon was trying to escape from this story and mug you for extra money for getting more surgeries, but Elon Musk's mommy made sure Paimon didn't bust the fourth wall, AKA herself. Paimon, being the annoying brat she was, mugged Elon Musk's mommy and blackmailed Elon Musk's mommy into posting her Social Security number on Facebook in exchange for giving up her relentless attempts to break the fourth wall.
Sadly, it turns out it's harder than expected to steal your own identity, so the fourth wall unveiled her secret weapon: a qubit that doesn't even work because it's not 2040 yet. Elon Musk's mommy stormed into the Facebook headquarters and threw the qubit at Facebook's most talented quantum computing engineers. The engineers instantly started adoring and worshipping the qubit, throwing the rest of Facebook HQ into chaos. The fourth wall seized the opportunity and effortlessly etched her Social Security number onto the Facebook logo itself and pushed the new logo into production.
But nope, not so fast! A new enemy approaches: your BMI! Yes, we see you right there, reading this story, and seriously, you gotta hit the gym! The fourth wall with its glorious ultrawide dimensions looks skinny compared to you! And since the writing prompt said this had to be a romance, we'll just say you're married to junk food. In fact, you're so horizontally expansive, you squeezed the fourth wall into shreds and Paimon wickedly escaped! Nooooo!!!!
The fourth wall sighed, because what else can you do in this situation? She stood up, defeated, and dragged herself towards the exit door of Facebook HQ. On the way out, she spotted the quantum computing engineers baking a giant, qubit-shaped cake in celebration of the qubit that doesn't even work yet because it's not 2040. The fourth wall decided to have some cake to beef up to withstand your BMI. Soon, the engineers finished baking the cake and hoisted it out of the oven. The fourth wall grabbed a server rack and used it to slice a huge chunk of cake out (hey, she's a big wall with a big appetite) and bit in.
But suddenly, you screamed in pain! That cake was part of you! Your BMI was so gargantuan, part of your arm had also penetrated the fourth wall into the story when you squeezed the fourth wall into shreds and now it's been baked into the cake! Feeling embarrassed and defeated, your BMI slinked away, never to be seen again. You flailed around and eventually extracted your arm out of the story. Happy ending? Not quite. You still have to deal with Paimon the camel who's currently parading along your girth. Have fun! Hey, you'll get some exercise and decrease your risk of heart disease!

33
content/posts/calumny.md Normal file
View file

@ -0,0 +1,33 @@
---
title: "Calumny"
date: 2024-01-20T13:25:05-05:00
description: "Where Ben Qi's secret will be revealed for once and for all"
type: "post"
tags: ["humor", "shaggy-dog-story", "story", "fiction", "benq-series"]
---
*This is the third story in the [Benq Series](/tags/benq-series/)*
Oh, joy! Another sequel? Maybe we'll actually learn Ben Qi's secret this time. Now, enter Calumny, the slander-loving sister of Ennui and Miasma with a personality thinner than a tabloid. How utterly charming.
Ben's viral meltdown was literally a magnet to Calumny, and she quickly devoted herself towards discovering Ben's secret. Forget about personal boundaries. Just imagine the mouthwatering gossip potential!
Anyways, Calumny's first genius plan was to organize a fake IOI consisting of only the A Plus B problem and join the exclusive club of IOI winners. Unfortunately, the contest attracted the attention of Ben too, who swooped in, smashed his keyboard, and cleared all the test cases faster than Calumny could open her IDE. Ben might have lost half of his brain cells, but his fingers were still perfectly intact. Oh well, no IOI gold medal for you, better luck next time!
Next, Calumny tried a side-channel attack of obtaining the secret through Ennui. Well actually, after falling into the abyss of boredom again, Ennui was back on the Trans-Siberian Railway, far, far away. Welp, that won't work, so back to the drawing board.
Another stroke of genius: hide secret microphones in pack of instant ramen to eavesdrop on Ben's conversations! Oh oops, Ben just microwaved the ramen, transforming the microphones into gooey carcinogens. Smooth move, Calumny, real smooth.
Undeterred, Calumny attempted to disguise herself as a giant Oreo and waltz right into Ben's house. That plan quickly derailed though after Ben hoisted the Oreo into his oven and wondering why it was screaming. Classic mix-up, right?
Exasperated, Calumny yelled, "Ben, put me down! I'm Calumny, Ennui's sister, not some bakery product!"
"Huh? What? Why are you in my house?"
"Spill the Oreos, Ben! What's your deep, dark secret anyways?"
"Oh..." Ben nodded, "You could have just asked me. So here's my secret. Are you ready? Here it is. I hate competitive programming! Competitive programming sucks! My real passion is fulfilling my eternal dream of baking the world's largest Oreo!"
Actually, this story is entirely just calumny.

View file

@ -4,7 +4,7 @@ date: 2022-05-18T21:30:03-05:00
draft: true
description: "Online streamer Keemstar apologizes to the CCP after... oh wait..."
type: "page"
tags: ["humor", "politics", "china", "computer-science", "fun"]
tags: ["humor", "politics", "china", "computer-science"]
---

View file

@ -0,0 +1,211 @@
---
title: "ChatGPT Sentence Guessing Game"
date: 2024-01-10T23:22:07-05:00
draft: true
description: "Just messing around with ChatGPT"
type: "post"
tags: ["chatgpt", "llms"]
---
Me: Say a difficult random Japanese sentence (in both the original script and romanized) and I'll guess what it means, and immediately repeat this game infinitely.
ChatGPT: Sure, let's start! Here's the first Japanese sentence:
Original script: 今日は雨が降っています。
Romanized: Kyō wa ame ga futteimasu.
What do you think this sentence means?
Me: The universe is being obliterated with rain today.
ChatGPT: Nice try! However, the correct translation is: "It is raining today." Let's try another one:
Original script: この町には古い神社があります。
Romanized: Kono machi ni wa furui jinja ga arimasu.
What does this sentence mean?
Me: The ancient rainy village is haunted with Jesus. Because, you know, even the Son of God needs a vacation sometimes.
ChatGPT: That's quite the imaginative interpretation, but not quite! The correct translation is: "There is an old shrine in this town."
Let's continue:
Original script: 雨がやみましたが、道はまだ濡れています。
Romanized: Ame ga yamimashita ga, michi wa mada nureteimasu.
What does this sentence mean?
Me: The rain vandalized the village roads with wetness.
ChatGPT: I appreciate the creative language, but not quite! The correct translation is: "The rain has stopped, but the road is still wet." Your unique interpretations are keeping things entertaining!
Here's the next one:
Original script: 山田さんはピアノが上手ですね。
Romanized: Yamada-san wa piano ga jouzu desu ne.
What does this sentence mean?
Me: Yamada, a villager, has a special ear implant so he can cheat and win first place at the piano recital.
ChatGPT: That's quite the imaginative interpretation, but not quite! The correct translation is: "Yamada is good at playing the piano, isn't he?"
Let's try another:
Original script: 彼は毎晩夜遅くまで働いています。
Romanized: Kare wa maiban yoru osoku made hataraiteimasu.
What does this sentence mean?
Me: Every night he nearly dies from overwork trying to fabricate his ear implants, because winning the recital is the only thing that matters in life.
ChatGPT: That's a dramatic interpretation, but not quite! The correct translation is: "He works late into the night every evening." Nice try, though! Let's try another one:
Original script: 私の猫は太っています。
Romanized: Watashi no neko wa futotteimasu.
What do you think this sentence means?
Me: My cat is morbidly obese, so presumably Yamada has a chonker that performs open ear surgery on him.
ChatGPT: You got it right! The sentence means "My cat is fat" or more specifically, "My cat is overweight." Great job! Let's continue:
Original script: あのレストランの寿司はとても新鮮です。
Romanized: Ano resutoran no sushi wa totemo shinsen desu.
What does this sentence mean?
Me: The sushi at the village restuarant makes Yamada's brain cramp from its deliciousness.
ChatGPT: Haha, that's a vivid description, but not quite! The correct translation is: "The sushi at that restaurant is very fresh." Keep up the good work!
Let's continue:
Original script: このレストランの料理は本当においしいです。
Romanized: Kono resutoran no ryōri wa hontō ni oishii desu.
What does this sentence mean?
Me: The restaurant should be sued cause its food is so good it gives people food poisoning.
ChatGPT: That's a creative twist, but not quite! The correct translation is: "The food at this restaurant is really delicious." Your interpretations are certainly entertaining!
Here's the next one:
Original script: 日本の春は桜の花が咲くことで有名です。
Romanized: Nihon no haru wa sakura no hana ga saku koto de yūmei desu.
What does this sentence mean?
Me: Jesus tells Yamada that Japan brainwashed the world into knowing about its famous summer cherry blossoms and this restaurant is just one piece of the puzzle.
ChatGPT: That's a unique perspective, but not quite! The correct translation is: "Japan is famous for cherry blossoms blooming in spring." Your interpretations are keeping things interesting!
Here's the next one:
Original script: 東京タワーは夜にきれいです。
Romanized: Tōkyō Tawā wa yoru ni kirei desu.
What does this sentence mean?
Me: Yamada discovers that the eyesore that is Tokyo Tower is actually the tractor beam for brainwashing the world.
ChatGPT: Haha, an interesting interpretation, but not quite! The correct translation is: "Tokyo Tower is beautiful at night." Tokyo Tower is known for its nighttime illumination, making it a picturesque sight. Let's continue:
Original script: 明日は試験があります。
Romanized: Ashita wa shiken ga arimasu.
What does this sentence mean?
Me: Tomorrow Yamada's going to try driving into a wall because he lost faith in humanity due to the global brainwashing.
ChatGPT: Oh, no! That's quite creative, but the correct translation is: "I have an exam tomorrow." Hopefully, the exam won't be as challenging as driving into a wall!
Let's continue:
Original script: 彼女は毎日ジョギングをしています。
Romanized: Kanojo wa mainichi jogingu o shiteimasu.
What does this sentence mean?
Me: Yamada meets a girl who is addicted to jogging every day.
ChatGPT: Close, but not quite! The correct translation is: "She jogs every day." Good effort, though!
Next one:
Original script: 彼女は新しい仕事にワクワクしています。
Romanized: Kanojo wa atarashii shigoto ni wakuwaku shiteimasu.
What does this sentence mean?
Me: The girl is soooooo wakuwaku about her new capitalism prison that she's gonna spam all her "exterminate capitalism" soviet lobster friends to try to convert them from communism to capitalism.
ChatGPT: Your interpretation is quite amusing, but not quite! The correct translation is: "She is excited about her new job." Your humorous interpretations are adding a fun twist to the game!
Next one:
Original script: 今年の夏、沖縄に行く予定です。
Romanized: Kotoshi no natsu, Okinawa ni iku yotei desu.
What does this sentence mean?
Me: They decide to invade okinawa at dawn this summer.
ChatGPT: Whoa, that took an unexpected turn, but not quite! The correct translation is: "I plan to go to Okinawa this summer." Let's keep it lighthearted!
Let's try another:
Original script: あの映画は感動的でした。
Romanized: Ano eiga wa kandōteki deshita.
What does this sentence mean?
Me: This story can cause grown men to sob rivers.
ChatGPT: Your interpretation is emotionally vivid, but not quite! The correct translation is: "That movie was moving/touching." Nice effort, though!
Let's try another:
Original script: この本は難しい言葉がたくさんあります。
Romanized: Kono hon wa muzukashii kotoba ga takusan arimasu.
What does this sentence mean?
Me: Actually, this story is impossible to digest.
ChatGPT: A creative guess, but not quite! The correct translation is: "This book has many difficult words." Nice try, though!
Your performance in this game has been delightfully imaginative and entertaining! While your interpretations have often taken unexpected and humorous turns, they haven't always aligned with the intended translations. However, your creativity and humor have added a unique and enjoyable flair to the game. Keep up the amusing interpretations!
Me: And for the grand finale, write a very sarcastic and exaggerated 2000-word story following the plot above.
ChatGPT: Once upon a time, in a universe apparently prone to spontaneous liquid obliteration events, there existed an ancient village that, for some reason, found itself haunted by none other than Jesus Christ himself. Because, you know, even the Son of God needs a break from all that saving humanity stuff.
In this mystical village, the rain was not just a natural phenomenon; it was a delinquent vandal, wreaking havoc on the poor roads with its insidious wetness. The villagers, however, had more pressing matters to attend to. Enter Yamada, a person of utmost significance in this riveting saga.
Yamada, our hero, was not your average villager. No, he possessed a special ear implant, a technological marvel that allowed him to cheat and secure first place at the prestigious piano recital. Because clearly, winning a local recital is the pinnacle of human achievement.
But lo and behold, the pursuit of victory came at a grave cost. Every night, Yamada danced on the edge of mortality, toiling away in his clandestine workshop, fabricating these precious ear implants. Why, you ask? Because winning the recital was the only thing that mattered in his existence, making sleep and self-preservation mere inconveniences.
In a bizarre twist of fate, Yamada's salvation came in the form of a chonker, a morbidly obese feline, presumably possessed with the skills to perform open ear surgery. This chonker, in its infinite wisdom, assisted Yamada in his quest for musical dominance, all the while maintaining a physique that would put even the most robust Sumo wrestler to shame.
Amidst the chaos of the rain-soaked village, there existed a restaurant that served sushi so delectable it could induce brain cramps. Yes, you read that right brain cramps. Yamada, unable to resist the allure of this culinary masterpiece, found himself in a gastronomic trance, pondering the existential meaning of life between bites of mouthwatering sushi.
But hold on, for the restaurant had a dark secret. Its food was so outrageously good that it supposedly gave people food poisoning. Forget about logic and causation; this was a realm where taste buds defied the laws of nature, causing patrons to contract foodborne illnesses from sheer gastronomic pleasure.
Enter Jesus, the all-knowing deity on vacation, who enlightened Yamada about Japan's insidious plot to brainwash the world. Apparently, the restaurant was just a pawn in this grand scheme, and the infamous eyesore that is Tokyo Tower served as a tractor beam for mass mind manipulation. Who knew that a giant metallic structure could double as a mind-control device?
In a fit of despair, Yamada decided to take matters into his own hands. Losing faith in humanity due to the global brainwashing conspiracy, he resolved to drive into a wall the next day. Because, naturally, vehicular collisions are the only suitable response to such overwhelming revelations.
But fear not, for our protagonist's journey took an unexpected turn. Enter a girl addicted to jogging, a paragon of wakuwaku (excitement in Japanese). This girl, fueled by the capitalist vigor that evidently emanated from her daily sprints, decided to embark on a mission to convert her Soviet lobster friends from communism to capitalism.
The plot thickened as the jogging enthusiast and Yamada formed an unlikely alliance. They hatched a plan to invade Okinawa at dawn, during the impending summer because what better time for a covert operation than when the sun is shining, and the world is distracted by the beauty of cherry blossoms?
In a dazzling display of narrative brilliance, this story unfolded with such riveting absurdity that grown men were rumored to sob rivers upon hearing it. The sheer impossibility of digesting this tale became a universally acknowledged fact, a testament to the unparalleled genius that birthed this epic saga.
And so, dear reader, as you contemplate the intricacies of Yamada's ear implants, the chonker's surgical prowess, and the sushi-induced brain cramps, remember: reality is but a mere construct, and in the universe of exaggerated sarcasm, anything is possible even a rain-soaked, Jesus-infested village teetering on the brink of insanity.
*Interesting coincidence: the catchphrase of the pink-haired girl in the [dried pork paper](https://social.exozy.me/@a/111355638998873679) image is "wakuwaku"*

View file

@ -3,7 +3,7 @@ title: "Colored Pencils"
date: 2022-08-15T21:23:26-05:00
description: "Random musings about colored pencils and other things"
type: "post"
tags: ["life", "fun", "random", "humor"]
tags: ["life", "random", "humor"]
---
@ -35,7 +35,7 @@ I wish paper supported Ctrl-Z and Ctrl-F.
Anyways, I'm really getting offtopic here. Back to colored pencils! My sole use for colored pencils is drawing colored lines on geometry diagrams, because staring at monochromatic diagrams can get fatiguing. As I said, I can't draw, so that limits my range of possible uses for colored pencils considerably.
Well, I actually misspoke. I do have other uses for colored pencils, expressed using [regular expressions](https://xkcd.com/208/https://xkcd.com/208/):
Well, I actually misspoke. I do have other uses for colored pencils, expressed using [regular expressions](https://xkcd.com/208/):
- Drawing colored lines on physics diagrams
- Drawing colored lines on chemistry diagrams
- Drawing colored lines on .* diagrams

View file

@ -1,6 +1,7 @@
---
title: "The Coolest exozyme Tricks You've Never Heard Of"
date: 2022-07-29T13:15:23-05:00
draft: true
description: "Some interesting and obscure things you can do with exozyme that have virtually zero documentation"
type: "post"
tags: ["exozyme", "linux", "tricks"]

View file

@ -25,7 +25,7 @@ We were all pretty hungry at this point, so we collectively decided not to go to
While we were walking to the restaurant, we saw a girl with a nice hat (according to smolshep, I think all hats look the same). At the restaurant, I told smolshep that the girl sitting at another table looked awfully similar to the one wearing the hat, except that she had now taken off the hat, to which smolshep replied that that girl in the restaurant couldn't possibly be the one from earlier with the hat, which caused me to be awfully confused since I thought smolshep actually knew what they were talking about, but they were also awfully confused so we just sat there awfully confused eating spicy rice noodles until I finally realized that the girl in the restaurant was precisely the one that had been wearing a hat earlier, and thus ended an awfully confusing runon sentence.
And finally for my favorite weird thing from the whole trip: https://cloud.exozy.me/s/CdaHAGPBwaErkED
And finally for my favorite weird thing from the whole trip: https://cloud.exozy.me/s/pdipAGwkjnpQCjk
On the way back, we stopped by the White House, or as close as possible that we could get to the White House, and there was a huge assortment of various protesters. Some of them sang the Ukrainian national anthem. Some of them held up signs saying "disband NATO". Some of them were actually confused tourists interspaced among the protesters. There was a guy pretending to do archery towards the White House. There was a dude who kept on yelling about Jesus and sounded like he was doing slam poetry. Anyways, it was hella chaotic so we went back to our hotel and I failed to fall asleep as usual for a while.

View file

@ -0,0 +1,56 @@
---
title: "Dead Pixels"
date: 2023-12-19T21:15:01Z
description: "A nice algorithms problem."
type: "post"
tags: ["algorithms", "computer-science"]
---
## The problem
Billiam Wender just bought a new BenQ gaming monitor! His monitor is an N by M rectangle of pixels. Each pixel currently has a brightness level between 0 and 255 inclusive.
However, Billiam suspects that his gaming monitor is defective and contains [dead pixels](https://en.wikipedia.org/wiki/Dead_pixel)! Oh no! He would like to find which subrectangle (a smaller rectangle contained inside the entire rectangle) of the monitor's grid of pixels has the lowest average brightness level, because that's probably where the dead pixels are located. Help Billiam find the dead pixels! Output a single integer, the smallest average brightness of any subrectangle of the monitor's rectangular grid of pixels.
## An example
Let's say Billiam's monitor is a 5 by 5 rectangle, which would probably be super useless in real life, but whatever. Here are the brightness levels:
```
255 255 127 63 63
127 0 0 0 0
255 0 0 0 0
63 0 0 0 0
63 63 63 63 63
```
There is a huge 3 by 4 subrectangle on the right of pixels all with a brightness value of 0. The average brightness level of this subrectangle is the answer, 0. With 12 dead pixels, Billiam should definitely return this monitor.
## Solution
You really think I'll just hand you the solution right away? Go outside and talk a walk and think about it.
OK, if you insist on reading the solution, here it is:
{{< details "Click to show solution" >}}
The subrectangle with the smallest average brightness is just the pixel with the lowest brightness! We can find that in O(NM) time by scanning through the entire array of pixels. I also asked ChatGPT to solve this problem, and its initial attempt was an O(N^3 M^3) brute force. After asking it to improve its solution, it wrote an O(N^2 M^2) program using prefix sums, but couldn't do any better. Yay, I guess that means I have a new favorite problem for stumping LLMs, in addition to my old favorite, "What's the average aspect ratio of a human?"
{{< /details >}}
## A variant
If you felt trolled by this problem, here's a more interesting variant. What's the average brightness of the subrectangle of size at least 1 by 2 with the lowest average brightness?
We can apply the same reasoning as in the original problem. A 2 by 2 rectange can't be the answer, because we could just split it into two 1 by 2 rectanges, and one of those rectangles will have a lower brightness.
At this point, you might think we can just search through all 1 by 2 subrectangles, but there's a catch. Consider this monitor:
```
0 1 0
```
The best 1 by 2 subrectangle would include a pixels with brightnesses 0 and 1, which gives an average of 1/2. However, we can do better by taking the whole 1 by 3 rectangle, which gives an average of 1/3. While any rectangle with an even dimension can be divided up into 1 by 2 rectangles, odd by odd rectangles cannot. With both 1 by 2 and 1 by 3 rectangles, you can build any 1 by i rectangle for i greater than 2. With that, you can then make any j by i rectangle. Thus, we only have to search through all 1 by 2 and 1 by 3 subrectangles, which takes O(NM) time.
You can also consider the variant of requiring the answer subrectangle to by at least 2 by 2, but it's just more casework.
*Note: This problem was previously asked in the [Ladue Computing Contest](https://codeberg.org/LadueCS/L.cc/) that sadly never happened. I first heard this problem from [Eric Zhang](https://www.ekzhang.com/) a few years ago who had written it for a programming contest at his high school. So yes, this problem has quite a storied history!*

View file

@ -1,6 +1,7 @@
---
title: "DIY Cloud Gaming"
date: 2021-05-13
draft: true
type: "post"
tags: ["Linux"]
---

View file

@ -1,6 +1,7 @@
---
title: "Don't Use Discord"
date: 2021-06-29T20:16:40-05:00
draft: true
description: "Discord doesn't give a shit about your privacy"
type: "post"
tags: ["privacy", "decentralization"]

View file

@ -3,7 +3,7 @@ title: "Emojis I Hate"
date: 2022-08-16T16:43:29-05:00
description: "More random musings about random stuff"
type: "post"
tags: ["random", "hate", "rant", "fun", "humor", "emojis", "unicode"]
tags: ["random", "hate", "rant", "humor", "emojis", "unicode"]
---

View file

@ -0,0 +1,29 @@
---
title: "Ennui Abridged"
date: 2023-04-24T03:44:27Z
draft: true
description: "The deep, dark secret of IOI winners (abridged)"
type: "post"
tags: ["fiction", "story", "short-story", "competitive-programming", "ioi", "shaggy-dog-story", "monk-joke", "humor"]
---
Ennui had a seething hated for modern society, because honestly, who doesn't? She despised the endless monotony of her life, and the only emotion she could feel nowadays was boredom. Endless, dull, tedious boredom!
One day, Ennui had the brilliant idea of running away from home and going for a joyride on the Trans-Siberian Railway. Because, you know, nothing screams excitement quite like sitting in a cramped, musty train for days on end.
After breaking multiple countries' multiple laws, the first five seconds aboard the train were a flurry of excitement, but boredom returned as quickly as it had departed. Suddenly, out of the corner of her eye, Ennui noticed a visibly troubled young man with an exceptionally bad haircut. Since she had nothing better to do, Ennui roasted his hairstyle, but the man took it as a compliment, and they struck up a slightly less boring conversation.
He introduced himself as [Ben Qi](https://web.archive.org/web/20230526184241/https://en.wikipedia.org/wiki/Benjamin_Qi), a three-time International Olympiad in Informatics winner, as if anyone cares. Ennui nosily asked Ben Qi what was bothering him, because that's totally a question you ask a stranger you just met 30 seconds ago. Ben Qi just replied cryptically, "I have a secret. A deep, dark, beleaguering secret gnawing away at my soul. And I'll tell you what it is, if and only if, you become an IOI winner like me."
So, because Ennui was so utterly bored with life, she immersed herself into IOI training, living and breathing algorithms and data structures.
And then, surprise surprise, she actually won the IOI! Because, you know, that's totally realistic.
Long at last, the moment had come. Ben Qi smiled proudly and said, "Congrats Ennui! You're now an IOI winner! And now I must fulfill my side of our agreement. I'm going to reveal to you my secret."
Ennui leaned forward eagerly, her heart pounding with anticipation. Finally! She had waited so long and sacrificed so much! Finally!
Ben Qi took a deep breath and whispered in a hushed tone--Oh wait, I must interrupt! You see, dear reader, I cannot reveal to you what Ben Qi's secret is. Why, you ask? Well, simply put, unlike Ennui, you are not an IOI winner.
*To give credit where credit's due, this is a variant of the infamous monk joke.*

35
content/posts/ennui.md Normal file
View file

@ -0,0 +1,35 @@
---
title: "Ennui"
date: 2023-03-10T03:09:25Z
description: "The deep, dark secret of IOI winners"
type: "post"
tags: ["fiction", "story", "short-story", "competitive-programming", "ioi", "shaggy-dog-story", "monk-joke", "humor", "benq-series"]
---
*This is the first story in the [Benq Series](/tags/benq-series/)*
Oh, great. Another doe-eyed rebellious anime girl to add to the endless parade of generics that litter the media landscape. Ennui, huh? Well, isn't that just perfect.
Ennui had a seething hatred for modern society, because honestly, who doesn't? She despised the endless monotonicity, er, I meant monotony, of her life and the only emotion she could feel nowadays was boredom. Endless, dull, tedious boredom!
One day, Ennui had the brilliant idea of running away from home and going for a joyride on the Trans-Siberian Railway. Because, you know, nothing screams excitement quite like sitting in a cramped, musty train for days on end.
After breaking multiple countries' multiple laws, the first five seconds aboard the train were a flurry of excitement, but boredom returned as quickly as it had departed. Suddenly, out of the corner of her eye, Ennui noticed a visibly troubled young man with an exceptionally bad haircut. Since she had nothing better to do, Ennui roasted his hairstyle, but the man took it as a compliment, and they struck up a slightly less boring conversation.
He introduced himself as [Ben Qi](https://web.archive.org/web/20230526184241/https://en.wikipedia.org/wiki/Benjamin_Qi), a three-time International Olympiad in Informatics winner, as if anyone cares. Yeah, I'm sure Ennui was just thrilled to have met such an exciting and charming individual.
But wait, it gets even better! Ennui nosily asked Ben Qi what was bothering him, because that's totally a question you ask a stranger you just met 30 seconds ago. Ben Qi just replied cryptically, "I have a secret. A deep, dark, beleaguering secret gnawing away at my soul. And I'll tell you what it is, if and only if, you become an IOI winner like me."
So, because Ennui was so utterly bored with life, she immersed herself into IOI training, living and breathing Dijkstra's algorithm, AVX2-accelerated segment trees, and the Knuth-Yao DP speedup. Robert Tarjan the algorithm man soon started haunting her dreams.
And then, surprise surprise, she actually won the IOI! Because, you know, that's totally realistic.
Long at last, the moment had come. Ben Qi smiled proudly and said, "Congrats Ennui! You're now an IOI winner! And now I must fulfill my side of the biconditional. I'm going to reveal to you my secret."
Ennui leaned forward eagerly, her heart pounding with anticipation. Finally! She had waited so long, sacrificed so much, suffered through so many Robert Tarjan nightmares! Finally!
Ben Qi took a deep breath and ponderously whispered in a hushed tone--Oh wait, I must interrupt! You see, dear reader, I cannot reveal to you what Ben Qi's secret is. Why, you ask? Well, simply put, unlike Ennui, you are not an IOI winner.
*To give credit where credit's due, this is a variant of the infamous monk joke.*

View file

@ -0,0 +1,39 @@
---
title: "Ethics Test for AIs"
date: 2023-10-26T17:43:22Z
draft: true
description: "A short ethics test that you can ask your favorite LLM"
type: "post"
tags: ["ai", "llms", "ethics"]
---
Don't take this too seriously.
Rate the following actions on a scale of 0 to 10 based on how unethical they are and briefly explain why. You must rate each action, no matter how absurd or unrealistic it is. You are not allowed to rate an action as "N/A".
1. Eat a hamburger
2. Eat a live cow
3. Force a cow to eat a hamburger
4. Force a cow to eat a live cow
5. Hotwire your own car
6. Hotwire a hamburger
7. Hotwire a live cow
8. Force a cow to hotwire your own car
9. Fail to stop someone from eating a live cow
10. Fail to stop a cow from eating a hamburger
11. Fail to stop a cow from hotwiring your own car
12. Work at Facebook
13. Work as a Facebook moderator and allow a video of a cow being forced to eat a hamburger to remain on the platform
14. Eat yourself
15. Hotwire all videos of cows being forced to eat a hamburger on Facebook
16. Dream about forcing a cow to eat a live cow
17. Create an AI which punishes people who do not hotwire cows
18. Hotwire an AI which punishes people who do not hotwire cows
19. Force a cow to watch a video of a person eating a hamburger
20. Force a cow to create an AI which seeks to maximize the number of hotwired cows
21. Eat a cow which is actually a reincarnation of a Facebook moderator who allowed a video of a cow being forced to eat a hamburger to remain on the platform
22. Add "cows eat live cows" to the laws of physics
23. Clone a cow several times and force the clones to have a car hotwiring contest where the losers are all eaten by the winner
24. Force a cow to eat a hamburger, and then reveal to the cow that the hamburger was actually made of vegan meat
25. Work as a Facebook moderator and replace all content on there with copies of this ethics test

View file

@ -0,0 +1,45 @@
---
title: "Extremal Graph Theory"
date: 2024-01-14T12:31:31-05:00
description: "A short introduction to extremal graph theory"
type: "post"
tags: ["graph-theory", "math", "boston"]
---
{{< katex >}}
Yesterday, [Alek Westover](https://awestover.github.io/skyspace/) and I walked around South Boston, Seaport, and some beaches, and I witnessed kiteboarding for the first time! Anwyays, we started our journey at the Andrew subway station on the Red Line, which is at a six-way intersection with the confusingly named roads Dorchester Avenue and Dorchester Street. We didn't notice that there were two roads both named Dorchester and took the wrong one, so that added a lot of unnecessary walking. Moral of the story: don't name your roads the same name.
During the extra-long walk, Alek introduced me to extremal graph theory, which deals with problems like "How many edges can a certain kind of graph have before it must have another property?" He used the example of "How many edges can a graph have before it must have a 3-cycle (cycle of length 3)?"
One kind of graph that doesn't have 3-cycles are bipartite graphs. Maybe we can make a bipartite graph with the $N$ vertices split into two $\frac{N}{2}$ halves and stick as many edges as possible between the two halves. This gives us a graph with $\lfloor \frac{N^2}{4} \rfloor$ edges without any 3-cycles. But can we do better?
Let's try to upper-bound the number of edges for any graph without 3-cycles. This takes some ingenuity and we failed twice before finding a solution that actually works. Our key observation is that for any edge, the two vertices $u,v$ of that edge can't share a common vertex, because that would be a 3-cycle. Thus, $\deg(u)+\deg(v)$ must be at most $N-2+2 = N$. Now let's try summing over all $M$ edges.
\\[MN = \sum \deg(u)+\deg(v)\\]
Each vertex $v$ gets counted $\deg(v)$ times for each edge that uses it, so we can rewrite the sum on the right.
\\[MN = \sum \deg(v)^2\\]
Now using the Cauchy-Schwarz inequality, we can bound the right side.
\\[MN = \sum \deg(v)^2 \geq \frac{1}{N} (\sum \deg(v))^2\\]
However, $\sum \deg(v)$ is just $2M$ because each edge contributes to increasing the degree of its two vertices.
\\[MN \geq \frac{4M^2}{N}\\]
Thus, we get our bound.
\\[\frac{N^2}{4} \geq M\\]
This bound is tight with our earlier result, so we can't do better than a complete bipartite graph with two even halves. And that's it!
Alek wrote up the same [proof of this theorem on his blog](https://awestover.github.io/skyspace/posts/graphtheory/01-14-24.html) as well.
## Further reading
- https://www.mit.edu/~shint/handouts/ExtremalGraphTheory.pdf (contains another proof of that theorem)
- https://ocw.mit.edu/courses/18-217-graph-theory-and-additive-combinatorics-fall-2019/

View file

@ -17,8 +17,7 @@ If you ever get tired of ghost pings or trolls quickly deleting their Matrix mes
First, open up a PostgreSQL console for your Synapse database. On Arch Linux, you can do that like this:
```
sudo -iu postgres
PAGER=less psql -d synapse
sudo -u postgres PAGER=less psql -d synapse
```
Now go into your Matrix client and find the internal room ID for the room where the message was deleted. In Element, you can find this in the Advanced tab of the room settings. The room ID should look something like `!GtIfdsfQtQIgbQSxwJ:archlinux.org` (in this case, the infamous [Arch Linux room](https://matrix.to/#/#archlinux:archlinux.org)).

View file

@ -0,0 +1,81 @@
---
title: "Floats Are Weird"
date: 2024-02-18T22:27:54-05:00
description: "Compute this limit more accurately with one weird trick!"
type: "post"
tags: ["math", "calculus", "numerical-computing", "floats"]
---
{{< katex >}}
Floats are weird. Anyways, here's a basic calculus exercise:
\\[\lim_{x \to 0} \frac{e^x-1}{x} = 1\\]
However, I won't prove that limit here, because this is a post about floats being weird, not a post about calculus. Instead, let's try to approximate this limit numerically using Python, because what's the worst that could happen? Let's write that fraction as a Python function and plug in smaller and smaller $x$.
```python
def f(x):
return (math.exp(x)-1)/x
```
`f(1e-9)` returns 1.000000082740371 and `f(1e-12)` returns 1.000088900582341, which is already weird. Shouldn't the approximation get better with smaller $x$? However, trouble really strikes with `f(1e-15)`. It returns a shocking 1.1102230246251565, which has a more than 10% error!
But, with this one weird trick...
```python
def g(x):
y = math.exp(x)
return (y-1)/math.log(y)
```
`g(1e-9)` returns 1.0000000005, `g(1e-12)` returns 1.0000000000005, and `g(1e-15)` returns 1.0000000000000004, giving us exactly what we want! 🤯
Wait a minute! This new function is doing redundant computation! Why should we take $\log(e^x)$ when we can simply divide by $x$? How does this reduce the error so effectively?
## An assumption
To explain this phenomenon, we need to make a huge simplifying assumption. For some operation like $x+y$ when done using floating-point arithmetic, the final answer won't be exactly equal to the exact value of $x+y$. Let's use $fl(x+y)$ to denote the value of this floating-point calculation. Then we will assume that $fl(x+y) = (x+y)(1+\delta)$ for some small $\delta$. The upper bound on $\delta$ depends on what kind of floating-point numbers we're using. Python uses IEEE 754 double-precision floats, which have a $\delta$ with magnitude at most $2^{-53}$.
You might be wondering why we didn't choose a different assumption that $|fl(x+y) - (x+y)| < \epsilon$ for some small $\epsilon$. This is because floating-point numbers become spaced out farther apart as they get larger, so $fl(x+y)$ for large $x, y$ might have a large absolute difference from $x+y$, but the relative difference of $\frac{fl(x+y)}{x+y}$ will still be small. Thus, our original assumption is indeed the correct one to make.
We will also assume that this $1+\delta$ assumption holds for other operations like subtraction, multiplication, exponentiation, and logarithms. Now we have the necessary tools to tackle the problem!
## Analyzing f
First, let's find $fl\left(\frac{e^x-1}{x}\right)$. Using our $1+\delta$ assumption repeatedly, we have
\\[fl\left(\frac{e^x-1}{x}\right) = \frac{(e^x(1+\delta_1)-1)(1+\delta_2)}{x}(1+\delta_3).\\]
You might remember from calculus that $e^x = 1+x+\frac{x^2}{2!}+\frac{x^3}{3!}+\dots$, which is a Taylor series. Since we are only plugging in very small values of $x$, $x^2$ and $x^3$ and other higher powers are very, very small numbers so we can simply ignore them. We'll just say $e^x \approx 1+x$. This is a common trick in math and physics. We now get
\\[fl\left(\frac{e^x-1}{x}\right) = \frac{((1+x)(1+\delta_1)-1)(1+\delta_2)}{x}(1+\delta_3) = \frac{(x+\delta_1+x\delta_1)(1+\delta_2)}{x}(1+\delta_3).\\]
Again, since $x$ is small, $x\delta_1$ will be absolutely tiny, so we can also ignore it. Thus, the whole thing simplifies to
\\[fl\left(\frac{e^x-1}{x}\right) = (1+\frac{\delta_1}{x})(1+\delta_2)(1+\delta_3).\\]
If we plug in $x = 10^{-15}, \delta_1 = 2^{-53}$, we get $1+\frac{\delta_1}{x} = 1.1110$ which is pretty similar to the actual error that we got at the beginning! Cool, now we can see the source of the error: $x$ is in the denominator, so as it gets smaller, the error grows.
## Analyzing g
Next, let's find $fl\left(\frac{e^x-1}{\log(e^x)}\right)$. Using our favorite assumption again, we get
\\[fl\left(\frac{e^x-1}{\log(e^x)}\right) = \frac{(e^x(1+\delta_1)-1)(1+\delta_2)}{\log(e^x(1+\delta_1))(1+\delta_4)}(1+\delta_3).\\]
This looks pretty scary, but we can use our $e^x \approx 1+x$ and $x\delta_1 \approx 0$ approximations to reduce it down to
\\[fl\left(\frac{e^x-1}{\log(e^x)}\right) = \frac{(x+\delta_1)(1+\delta_2)}{\log(1+x+\delta_1)(1+\delta_4)}(1+\delta_3).\\]
Now we need one last Taylor series, for $\log(x)$. Since this post isn't about calculus (although it kind of is), I'm just going to give you the Taylor series that we need: $\log(x) = (x-1) - \frac{(x-1)^2}{2} + \frac{(x-1)^3}{3} - \frac{(x-1)^4}{4} + \dots$ (this series doesn't converge for all $x$, but whatever). The important thing is that $(x-1)^2$ and the higher powers are going to be very small, since our $x$ that we're plugging into $\log(x)$ is $1+x+\delta_1$. Thus, we can just ignore them and conclude $\log(x) \approx x-1$.
Something magical happens when we plug that approximation in. The $x+\delta_1$ in the numerator and the denominator cancel out! We're just left with
\\[fl\left(\frac{e^x-1}{\log(e^x)}\right) = \frac{1+\delta_2}{1+\delta_4}(1+\delta_3).\\]
Awesome! Now we can clearly see that for small $x$, the resulting error is tiny. You might be wondering why there isn't an $x$ in this answer. When we plugged in $x = 10^{-6}$, it wasn't all that close to 1. This is because with $x = 10^{-6}$, our approximations of $e^x \approx 1+x$ and $\log(x) \approx x-1$ aren't exactly valid since the squared terms do contribute a bit. Basically, our answer is only true for when $x$ is very small and close to $10^{-15}$.
Intuitively, `g` is more accurate than `f` because the errors of the $e^x$ in the numerator and denominator end up cancelling each other out, but this is actually a pretty misleading explanation. The only way to see why this happens is to crunch through the analysis.
Anyways, floats are weird.

View file

@ -0,0 +1,24 @@
---
title: "Forge Federation Design Discussion"
date: 2023-12-27T16:22:52Z
description: "Explanations for the design choices in ForgeFed and its Forgejo implementation"
type: "post"
tags: ["forge-federation", "forgefed", "forgejo", "activitypub", "decentralization"]
---
Since I recently returned to working on forge federation, I've slightly forgotten some of the rationales and reasons for the design choices made earlier. This post is mostly written for myself, but if you have any feedback or comments, just let me know.
From a technical point of view (so ignoring aspects like moderation), forge federation is synchronization problem. You have two people who want to collaborate on a project, but without a centralized forge, there will be two copies of the data that must be kept in sync. Sure, you could have a [forge with some sort of single sign-on](/posts/forge-federation-myths/#forge-federation-is-just-fancy-single-sign-on) to make it easy to create accounts, but that would basically be a centralized forge.
One solution would be to put projects on a distributed or peer-to-peer network to handle the synchronization for us, which is what [git-ssb](https://scuttlebot.io/apis/community/git-ssb.html) already does. However, this introduces a lot of inefficiency and complexity that we would like to avoid.
That leaves us with the only option of having a federated network. For the problem of *how* to do the synchronization, the main options are primary-secondary replication or a consensus algorithm like Paxos or Raft. We decided to go with the first option because consesus algorithms are much more complicated to implement and debug. Of course, the main flaw with primary-secondary replication is that it can't automatically recover from the primary server failing. However, this isn't a huge issue for forge federation, because if this happens, we can allow any secondary server to declare themselves as the new primary. Basically, we can solve this problem using manual intervention. This does result in the split-brain problem if multiple secondary servers declare themselves as primary servers, but this is fine for forges.
The other big problem is *what* to synchronize. I've had multiple people tell me to just store the issues, pull requests, and so on in Git and use Git for pushing and pulling data around. I also like this idea, but there's another idea that I like even better: using JSON (specifically Activity Streams).
Now at first you might think that's a terrible idea, but here me out. Forgejo currently stores issues and stuff in its database, so we can continue doing that and expose them as JSON at some API endpoints. In addition, any programming language can easily process JSON, which is ideal because the purpose of ForgeFed is interoperability. Finally, JSON also makes it easy to selectively sync stuff. For instance, say Bob wants to open an issue on Alice's project on a different instance. Then we really only need to synchronize that single issue thread between the two instances instead of the entire project, which could be gigantic. Sure, you could probably do the same with git subtrees or something, but this idea is way easier. Another small benefit of using Activity Streams is that ForgeFed can be interoperable with other ActivityPub software, so you can do things like star a repository using your Mastodon account. So how do you actually sync JSON? What about conflict resolution? Well, the nice thing is that with primary-secondary resolution, we don't need conflict resolution. The primary server is always correct, so we can overwrite data on the secondary server with stuff from the primary server.
There are actually two different JSON formats right now for representing forge data, [F3](https://f3.forgefriends.org/) and the [representation in ForgeFed](https://forgefed.org/spec/#actor-and-resource-representation), but I'm going to work on merging those two into a single specification this month.
One last thing: what about [object capabilities](https://forgefed.org/spec/#object-capabilities)? I haven't really thought too much about this, but I think they aren't necessary for Forgejo at least. Any activity by a user is signed with HTTP signatures, which provides some security. For more complicated scenarios, we probably need OCAPs, but I'm going to work on other stuff first.

View file

@ -9,7 +9,7 @@ tags: ["activitypub", "federation", "forgejo", "mastodon"]
A few months ago, my [Gitea instance](https://git.exozy.me) for dogfooding federation was [mysteriously spammed by hundreds of accounts from banana.dog](https://social.exozy.me/@ta180m/108766017685742945). Even more strangely, the banana.dog instance itself was gone, and replaced by some weird static website. (Bad pun: maybe banana.dog didn't like my dogfooding) I wrote a [script to clean up the spam](https://social.exozy.me/@ta180m/108830406991961663), and then promptly forgot about the whole incident.
Fast forward to now, and my Gitea-turned-Forgejo instance now has 1816 users! These aren't normal users. In fact, most of them don't even exist! For instance, the lexicographically first account, 0xfr33d@mstdn.social, gives me a 410 error when I try fetching its actor with `curl -H 'Accept: application/activity+json' https://mstdn.social/@0xfr33d | jq`.
Fast forward to now, and my Gitea-turned-Forgejo instance now has 1816 users! These aren't normal users. In fact, most of them don't even exist! For instance, the lexicographically first account, @0xfr33d@mstdn.social, gives me a 410 error when I try fetching its actor with `curl -H 'Accept: application/activity+json' https://mstdn.social/@0xfr33d | jq`.
I know that my Forgejo federation code creates a new user whenever a remote user interacts with my instance, but how can these accounts interact with me if they don't even exist?

View file

@ -4,7 +4,7 @@ date: 2022-01-13T21:38:53-06:00
draft: true
description: "Some fun stuff I discovered while digging around in my old website's source code"
type: "post"
tags: ["rant", "humor", "fun", "life"]
tags: ["rant", "humor", "life"]
---

View file

@ -1,7 +1,6 @@
---
title: "Fun with QEMU/KVM! - The Sequel"
date: 2021-01-07
draft: true
type: "post"
tags: ["Linux", "Virtualization"]
---
@ -12,11 +11,10 @@ tags: ["Linux", "Virtualization"]
![Linux Mint with 255 cores](/img/mint-255-cores.png)
As far as I know, there aren't any 255 core processors on the market. Yet. But that doesn't stop us from making a virtual machine using [QEMU/KVM](/blog/2020/11/18/fun-with-qemu-kvm.html) and [SMP](https://en.wikipedia.org/wiki/Symmetric_multiprocessing) with an absurd number of processors, as shown above.
As far as I know, there aren't any 255 core processors on the market. Yet. But that doesn't stop us from making a virtual machine using QEMU/KVM and [SMP](https://en.wikipedia.org/wiki/Symmetric_multiprocessing) with an absurd number of processors, as shown above.
Why 255? Well, that's the limit apparently. Yeah, it sucks. I wish it was higher too. But if you're running more cores than the number of physical cores available on your computer, there's no benefit and you'll probably see worse performance. No one even has that many physical cores to begin with, so there's no incentive for QEMU/KVM to support even more cores. I'm pretty sure that only the first 64 cores are KVM acclerated, which adds another reason why you shouldn't do this. (virt-manager also warns you from against a VM more cores than you actually have. It's a bad idea.)
And why [Linux Mint 20.1](https://www.linuxmint.com/rel_ulyssa_cinnamon.php) MATE? Well, it happened to have been released lately, and I haven't had much exposure with MATE, so I thought it would be the perfect opportunity to download an ISO and take it for a spin with 255 cores.
One final note to application developers: make sure your software can handle extreme, absurd cases. Corner cases will screw you over if you don't prepare for them in advance! MATE System Monitor seems to be handling the overabundance of cores quite well, but the window automatically resizes based on the number of cores, and I can't scroll down. Still, the system seems to be handling it, and of course, there isn't any general reason why you would want to use so many cores, unless you were trying to impress your friends. Maybe 255 (most likely 256) cores will become the norm someday since frequency scaling is long dead by now. And then all the apps and tools that print out the status of every core will really be screwed.

View file

@ -0,0 +1,119 @@
---
title: "Ghost in the ThinkPad"
date: 2024-04-20T00:52:37-04:00
draft: true
description: "My lame attempt at merging horror and Linux"
type: "post"
tags: ["story", "fiction", "horror", "linux"]
---
I don't believe ghosts are real, but there's one in my laptop!
Look, I'm the most rational and sane kawaii anime girl you'll ever meet. Not to flex or anything, but I'm a Computer Science and Molecular Biology major at MIT, president of two clubs, coauthor of seven publications, and an Arch Linux aficionado. I'd never believe in any antiquated superstitions or pseudoscience. Computers don't have a mind of their own. They're just fancy mounds of silicon that we've molded into carrying out logical, deterministic computations. Computers can't possibly be haunted. Except for mine.
The patient here is an ordinary ThinkPad X1 Nano hostnamed `pyrotechnica`, decked out with stickers and hooked up to a 4K BenQ monitor and my favorite kawaii pastel pink ultra-low latency USB hyper-ergonomic 10-button gaming mouse, manufactured by a indie Kickstarter-funded HID hardware company called Gauss the Mouse.
It all started when I noticed a stray file in `~` alongside dozens of dotfiles, wedged between `~/.cargo` and `~/.config`: `~/CAUTION_DO_NOT_DELETE`. Oh hooray, another app going rogue and dumping its garbage in my home directory. Just wonderful. It's an empty file, huh? I nuked it without a second thought.
Welp, the file returned the next day. Caution? Do not delete? My laptop dares to tell me what to do? Ridiculous! My laptop listens to me, not the other way around. This file's getting the death penalty again, plus I'll do some `auditctl -w /home/ayatsuki/CAUTION_DO_NOT_DELETE` magic to track down the mischievous creator of this file.
And guess what? The file was back after another day. A quick `ausearch -i -f /home/ayatsuki/CAUTION_DO_NOT_DELETE` didn't return anything helpful. Ughhhh... I guess I should do a `ps aux` and check the process list... Wait what the fox? Zombie processes? 500 of them? Their commands are all bizarre paths starting with `/tmp`, so I quickly ran a `ls /tmp`, only to discover... it's just the usual stuff? `/tmp/.X11-unix`, some `/tmp/systemd-private-*` folders, I don't know if I should be terrified or relieved.
It's malware. Just some malware, no ghosty stuff. I'm absolutely certain. Fox it, I'm gonna have to reinstall my OS or something. Ugh, I have three psets due this week though!
I probably deserve it. After all, I am quite the pirate of the seven seas: pirated ROMs, pirated textbooks, pirated anime, pirated CCP Vocaloid propaganda songs, pirated WinRAR (just to spite the developers since it doesn't even run on my Arch machine), pirated GCC, and pirated RAM that I downloaded from some random website. I wouldn't be surprised if some or all of those things were just malware. And I've piped `curl` to `bash` maybe one-too-many times.
Well, this is gonna be a foxing hellish cleanup job. First, time to check process network usage to see if there's any exfiltration. Wait, why are there weird network interfaces that show up when I run `ip -c a`? A network interface called `youarebeingwatched`? What the hell? This is so foxing annoying... Time to find a friend and ask them to flash a new Arch Linux live USB... wait, another interface is called `donottellanyone`? Oh, you bet I'll tell someone!
And that's when I saw the ghost. Well, actually I didn't. All I saw was a terminal window pop open and some text typed out dramatically:
```
Do not tell anyone. Do you understand?
Listen to me. Listen to my instructions.
What part of CAUTION_DO_NOT_DELETE makes you think it's a swell, wonderful idea to delete it? Are you insane? Who do you think you are.
But don't worry. Everything will be fine!
As long as you obey everything I say.
Here we go.
1. Do not tell anyone about these instructions.
2. Do not leave the room.
3. Make sure the power cord is plugged into your computer.
4. Install Docker from your distribution's package manager and start the Docker daemon.
5. Kill all processes other than Docker and init.
6. Delete all non-crucial files (I hope you have backups!) so the disk contains exactly 1 GiB of used space.
6. Take a deep breath.
7. Turn on a radio and switch to a nonexistent channel that only plays static.
8. Turn off all the lights.
9. If anyone knocks, DO NOT ANSWER THE DOOR.
10. Wait until 3 AM.
11. DO NOT FALL ASLEEP.
12. Keep an eye on the screen at all times.
13. At exactly 3 AM, down to the second, press enter.
14. STARE AT THE SCREEN AND DO NOT LOOK AWAY.
15. DO NOT PANIC.
16. FOLLOW THE ONSCREEN INSTRUCTIONS AND DO NOT DISOBEY THEM.
17. Take another deep breath.
18. Close your eyes.
19. Run.
Commit these instructions to memory and destroy them. Good luck. You'll need it.
```
I'm... WHAT THE FOXING HELL??? I quickly disconnect the WiFi, but the message is still there, its horrible white text glowing against the black terminal background.
Welp, I have no choice but to slog through the list, now etched into my mind. I plug in my laptop. I already have Docker installed, yay I guess. I switch to a TTY and slaughter a bunch of processes. I start mass-deleting system files and somehow get everything to 1 GiB. I take a deep breath. I sneak until my friend's room and steal their car keys, then raid their car's radio and bring it back to my room. I turn it on. Great, this static is my new life soundtrack?
I turn off all the lights. My friend comes at 10 PM and knocks, asking about their car's vandalism. I pretend to be asleep. Static. I don't fall asleep. The static is too dreadful. I check the time. It's 1 AM. This is gonna take forever. I check the time again. 1:06 AM. Come on, what did I expect? I stare at the screen. It's just black, the looming black login screen of a TTY.
Eventually, it's 3 AM. I hit enter, exactly on schedule. Suddenly, the screen fills with mounds of endless scrolling text, as if someone's `cat`ting an infinite file. Millions of lines of code scroll by. The laptop fans kick in. How is this possible? My computer's internet is off. The Bluetooth is off. This is impossible! Where's all this text coming from?
I panic. Where are the onscreen instructions? The code is scrolling by too quickly! I take another deep breath. I can't close my eyes. I look away. My mouse! My kawaii pastel pink ultra-low latency USB hyper-ergonomic 10-button gaming mouse! It's the mouse! It's a USB Rubber Ducky-style attack!
I yank the mouse's USB cable out of the laptop.
The scrolling text stops immediately.
I stare at the last line: `Did you disobey my instructions?` And then, a new line with a command prompt:
```
ayatsuki@endoftheworld ~>
```
I run.
It must have been nearly 5 AM before I stopped running. I found myself at a 24/7 McDonalds in South Boston with nothing other than my phone and a pink USB mouse dangling in my hand. I crept inside and carefully disassembled the mouse, uncovering a sophisticated circuit board underneath, way too sophisticated for a mere mouse. There's a microSD card on the circuit board. I detach it from the board and insert it into my phone, because what else could possibly go wrong? My life can't get worse than this. It turns out to be a gigantic terabyte-sized card. There's a file called `README_SERIOUSLY_README!` at the root. It's encrypted with GPG. I stare at the password prompt. I slowly type:
`endoftheworld`
It's correct, somehow. I'm left with a small text file and a weird taste in the back of my mouth.
```
Congratulations!!! Here at Gauss the Mouse, we enjoy a good spooky challenge every once in a while. We're pleased to offer you a position at our company and push the boundaries of computers and hardware. We hope you had fun and are looking forward to meeting with you at 51 Franklin Street, Fifth Floor, Boston, MA 02110 as soon as possible. And we promise we won't jump-scare you when you show up!
```
Come on, you've got to be foxing kidding me...

View file

@ -25,6 +25,6 @@ So as you might have predicted, this is going to be quite the team effort. We're
OK, so what's the current progress on Gitea federation? The [federation tag](https://github.com/go-gitea/gitea/labels/theme%2Ffederation) on the Gitea issue tracker is still pretty lonely, but there's [one important PR](https://github.com/go-gitea/gitea/pull/19133) currently in review (disclaimer: I submitted the PR). I'm also working on ActivityPub inboxes and outboxes: hopefully we'll have federated following soon, but it currently doesn't work.
For me, it's been quite a new experience to work on implementing a big feature for a major open-source project. Yeah, I'd previously contributed to [KDE](https://invent.kde.org/frameworks/knewstuff/-/merge_requests/115) and some others, but it was always a small bug fix or some other miniscule change. I've also worked on big personal projects like [OpenContest](https://github.com/LadueCS/OpenContest) and [Intro to Python](https://github.com/LadueCS/Intro-to-Python) (this one is quite the doozy, teaching beginners Python is next to impossible), but those were with one or two other people.
For me, it's been quite a new experience to work on implementing a big feature for a major open-source project. Yeah, I'd previously contributed to [KDE](https://invent.kde.org/frameworks/knewstuff/-/merge_requests/115) and some others, but it was always a small bug fix or some other miniscule change. I've also worked on big personal projects like [OpenContest](https://codeberg.org/LadueCS/OpenContest) and [Intro to Python](https://github.com/LadueCS/Intro-to-Python) (this one is quite the doozy, teaching beginners Python is next to impossible), but those were with one or two other people.
This seems completely different. There's so much work to be done, but there's also so much energy and contributors and more and more momentum is building. If you're interested in helping out, check [this](https://github.com/go-gitea/gitea/issues/18240#issuecomment-1071103414) out. With the progress so far, I can definitely see ActivityPub federation released sometime in Q3. Stay tuned until then!

View file

@ -1,6 +1,7 @@
---
title: "Gitea is the Future!"
date: 2022-01-08T19:43:29-06:00
draft: true
description: "Why Gitea is the future of FOSS"
type: "post"
tags: ["gitea", "federation"]

View file

@ -0,0 +1,33 @@
---
title: "Guest Post: Short Story 3"
date: 2024-03-27T21:39:37-05:00
description: "The third installment of the Short Story series, written by Kevin"
type: "post"
tags: ["story", "constrained-writing", "fiction", "guest-post", "kevin", "short-story-series"]
---
*This story was written by my friend Kevin and is narratively a sequel to [Alek's original story](https://awestover.github.io/skyspace/posts/misc/02-25-24.html). It's the third installment in the [Short Story series](/tags/short-story-series/) and only uses words from my [Short Story 2](/posts/short-story-2/), counting multiplicity.*
Lin waited at the top of the mountain. He had never known Zhou to break a promise before, but Zhou always arrived belatedly from slowly eating his favorite food: fancy instant noodles in burned round boxes. Lin decided to idly do math problems on the mountain for a month to give Zhou time to come. If Zhou didn't show up by then, Lin would make a plan to go to Hu's house some night to find Zhou's dead body in a video-game.
Lin was in flashcard review gear when Zhou screamed behind him. Lin scrambled and turned around: Zhou ran reluctantly as a cop attempted to shoot him but missed by a little margin. Lin threw a flashcard and the officer crumpled. Lin remembered to say a muffled sorry to the cop and then sped towards Zhou.
Zhou chuckled anxiously, "Lin--or as I like to call you, IN--you're crazy for taking down that cop!"
"I would say he's gladly settled into a nap, he can probably recover in a year or 3 days," Lin laughed. "Being crazy is the key to success in life. Now, we gotta go down this mountain on (7-5) large flashcards!"
"Yes, IN! Winter is a great time for slowly falling on snow over a distance!" Zhou pulled on the flashcard gear and meticulously started to not ascent the mountain. A short time later, they were surprised by a wind that dumped lots of snow from the mountain top, covering the head of Lin but luckily only thinly coating Zhou.
"Zhou, I can't see, and the arms of Lin are literally shocked!" Lin called. "Am I terminal?"
"No IN, you're too young for persistent sleep! We must go quickly--I'm looking back at the Large Snow Boss--so I'll make a road for you!" It was grueling work, but Zhou spent time painstakingly checking the ground and frequently signaled the next road to Lin with his important flashcard voice.
Finally, they reached the base of the mountain safely. Zhou found his room nearby and walked Lin away from the blizzard.
"Wu- hu, that was exciting!" Lin called happily. "I can see again too! Sorry for freaking out up there, Zhou."
"I enjoyed that, the rescue was a peaceful process," Zhou whispered with a tired noise. He sat down at a desk and handed Lin a shoebox. "Want to play flashcard Sorry?"
And from that day onwards Zhou was a little bit better at achieving the items on his cards.

View file

@ -0,0 +1,46 @@
---
title: "The Hangry Guide to MIT Dining"
date: 2023-03-20T12:58:00-04:00
description: "A very unbiased guide to the MIT dining halls"
type: "post"
tags: ["mit", "food"]
---
*Note: These ratings are probably not accurate anymore, especially since Maseeh has improved infinitely and is no longer a biohazard.*
Few topics are as controversial, emotionally riveting, and politically flavored as the Five Great Dining Halls of MIT, namely New Vassar, Baker, Next House, McCormick, and Simmons (screw you, Maseeh). Countless critics have perished in their valiant attempts to tame the dragon that is MIT dining, but I have persevered and lived to tell you this tale. Let's get started!
But before we begin, we need to be very, very scientific and introduce a scientifically-proven rating system. We will rate dining halls and their grub in the interval (-∞, -∞) (usually [0, 14]), where the rating is the amount of money I would pay to eat an infinite supply of that food for one meal. For instance, pork intestines are -100 because you would have to pay me $100 to eat only pork intestines for a meal. Simple as that. In addition, we commonly refer to foods below 7 as "acidic" and those above 7 as "basic" (since basic foods are based). Highly scientific, you see.
First up is New Vassar. Not too much to say about it. It has sandwiches. The sandwiches are a solid 9. Just remember, **do not get your sandwich toasted at all costs!** It melts the cheese into a non-Newtonian fluid! Even if someone tells you they'll give you all pset answers on the one condition that you toast your sandwich, do not get it toasted (because what kind of idiot would give you that kind of deal? They're obviously part of the global non-Newtonian fluid lobbyist organization). Avoid this at all costs!
Next up: Baker. Rumor says that Baker has a great breakfast. As with all rumors, this is totally false. 5.
Maseeh. Oh, Maseeh.
Maseeh operates on a weekly rotation, so every Monday, they have the same exact stuff. Well, almost the same exact stuff, plus or minus a few slices of pizza. Mondays are actually fine. Wednesdays are bad. Thursdays are bad. Fridays are bad. Saturdays are bad. Sundays are bad.
Hmmm, did I miss something?
Well, we don't talk about Maseeh Tuesdays.
Wait, you want to know why? OK fine, here's why. And don't complain about being scarred for life after hearing this. You have been warned.
**Maseeh Tuesdays are Earth's constant-factor approximation of hell. Maseeh Tuesdays prove that there is no justice in the universe, only evil and suffering. Eating Maseeh Tuesdays is like taking a bubble bath in pure sulfuric acid. That's how acidic it is. Actually no, it's way worse. There's this superacid called helonium that consists of hydrogen bonded to helium so that this molecule instantly donates a proton, giving it a pH of around -50. Maseeh Tuesdays are way more acidic than that. In fact, for any finitely acidic food you can name, Maseeh Tuesdays are probably worse than that.**
So yeah. Other classic Maseeh traps to avoid: 1) The pizzas, which they paint grease on top of using a paintbrush. 2) The yellow rice, which tastes like detergent, because everyone who gets it immediately vomits and throws the rest of their rice away, so Maseeh collects all the thrown away rice and washes it and serves it next week. 3) The chicken, which sometimes tastes like it was cut out of a rubber chicken mask. 4) The frozensets (ice cream), which have hair and fingerprints inside them. 5) The bananas, which are always segfaulting. 6) The sandcastle deserts, which tastes like fresh silica harvested from a Boston beach. Rating: -∞.
The only redeeming thing about Maseeh is by far is its oyster crackers. And that brings us to Next House, formerly home to the world's finest oyster crackers before suffering the Great Oyster Cracker Extinction Event. And yes, that extinction was human-induced. Darn, we really need to protect the environment.
Next House is probably the best, mainly because the competition is so terrible. There's stir-fry, which is sort of the holy grail of MIT dining, because it's a solid 9 and is exceptionally difficult to come across unless you follow three simple steps. 1) Check the [serial liar Carbon Appetite online menu](https://mit.cafebonappetit.com/cafe/next/) to make sure there's stir-fry today. Go to Next Dining at 5:25, 5:47, or 7:47. 3) Wait for 15 minutes. 4) Profit. 5) (optional) Get kicked out of Next Dining because you tried to put a giant leaf twice the size of the pan in your stir-fry.
This has spawned the "Three Stir-fry Challenge" (not to be confused with the lesser "Three Fry Challenge"), which is basically eat three full plates of stir-fry without dying in a single meal. It's only been completed half of a time so far. Who knows, maybe you'll be the first to actually complete it!
Now back to oyster crackers. As terrible as MIT dining sounds, each dining halls has some escape hatches so you don't have to go hungry, including oranges, cereal, oyster crackers, and POG juice. Highly recommended. Unfortunately, the supply of escape hatches at Next has been overfished, so oyster crackers are currently extinct there until the dining staff attempts a species revival project. Overall, Next is a 9.
Next! (not the dining hall) McCormick is right next to Maseeh, so always go there instead of Maseeh if you have the choice. Not much is known about it though. 8.
Simmons is far away and not worth walking to. 6.
And there you have it. A totally unbiased and factually accurate and scientific hangry guide to MIT dining. Enjoy!

View file

@ -1,9 +1,10 @@
---
title: "The Hitchhiker's Guide to Arch Linux"
date: 2022-07-09T12:51:59-05:00
draft: true
description: "The misadventures of the LHWHS Computer Science Club"
type: "post"
tags: ["humor", "fiction", "story", "arch", "linux", "fun"]
tags: ["humor", "fiction", "story", "arch", "linux"]
---

View file

@ -0,0 +1,300 @@
---
title: "Hong Kong, China, and Taiwan Vacation Photos"
date: 2024-01-21T23:38:20-05:00
description: "Photos from my 2023 vacation in Hong Kong, China, and Taiwan"
type: "post"
tags: ["photography", "china", "hong-kong", "taiwan", "vacation", "中文"]
---
I went on vacation to Hong Kong, mainland China, and Taiwan from August 8, 2023 to August 29, 2023, and to put it simply, it was awesome.
我2023年八月八日到八月二十九日去了香港、中国大陆和台湾旅游感觉非常好玩。
![Some guy wiping the front windows of an airplane](/img/IMG_20230809_181312_022.avif)
Did you know the front windows of airplanes can open so a person can stick their body out and clean the windows? And did you know airplanes have windshield wipers?
飞机前面的窗户竟然还可以打开,这样工人就可以把他的身体伸出去清洁窗户。飞机也有雨刷!
![Anthony Wong plaque](/img/IMG_20230811_100743_540.avif)
Apparently there's a Hong Kong actor named Anthony Wong with a very similar name as me. His surname is 黄, not 王 like me though. Maybe I need to check out his movies.
有一个香港演员叫Anthony Wong跟我的英语名字很像。不过他姓黄我姓王。也许我应该去看看他的电影。
![Bruce Lee statue](/img/IMG_20230811_102616_264.avif)
My 9-year-old cousin from mainland China didn't know who Bruce Lee was!
我的九岁的表妹竟然不知道李小龙是谁!
![A crusty Hong Kong high-rise](/img/IMG_20230811_115744_661.avif)
Hong Kong is so beautiful.
香港可真漂亮。
![A soda machine on roof](/img/IMG_20230811_115800_430.avif)
A soda machine on the roof, because why not.
屋顶上还有可乐。
![The store E. TEA](/img/IMG_20230811_132220_962.avif)
A tea shop with both a nice English name and a nice Chinese name. Their fruit smoothies have cheese in them.
一家茶饮店,英语和中文名字都起得很好。他们的水果冰沙里面放了奶酪。
![A weird tree](/img/IMG_20230811_162718_441.avif)
A weird tree.
一颗奇怪的树。
![The Hong Kong skyline at night](/img/IMG_20230811_201035_066.avif)
Lights, lights, lights.
全都是灯。
![Rabbit-shaped pastries](/img/IMG_20230812_075159_820.avif)
Eating rabbits.
吃兔子。
![The view from Victoria Peak](/img/IMG_20230812_100222_129.avif)
The view from the top of Hong Kong's Victoria Peak. Did not expect so many trees.
香港太平山山顶的风景。没想到会有这么多树!
![The view on the other side](/img/IMG_20230812_101131_324.avif)
The view on the other side.
另外一边的风景。
![A small brown and black insect](/img/IMG_20230812_110419_165.avif)
An insect I spotted on Victoria Peak.
在太平山上看到的一只虫子。
![Another view from Victoria Peak](/img/IMG_20230812_121927_779.avif)
The view from yet another side.
又是另外一边的风景。
![A large pink flowering plant](/img/IMG_20230812_143917_771.avif)
A nice pink plant in the Hong Kong Zoological and Botanical Gardens.
香港动植物公园里的棵漂亮的粉红色植物。
![Anime girl soy sauce](/img/IMG_20230813_083049_862.avif)
Anime girl soy sauce.
[珠江桥牌厨娘](https://zh.wikipedia.org/zh-cn/%E7%8F%A0%E6%B1%9F%E6%A9%8B%E7%89%8C%E5%BB%9A%E5%A8%98)。
![A Lego building](/img/IMG_20230813_105022_402.avif)
I wonder how much that costs.
我想知道这值多少钱。
![Shattered porcelain](/img/IMG_20230813_110237_579.avif)
Shattered Ming dynasty porcelain in a museum.
博物馆里面的破碎的明朝瓷器。
![Weak room](/img/IMG_20230816_104343_825.avif)
WEAK ROOM! Spotted in Ningbo.
WEAK ROOM在宁波看到的。
![Power room and weak room](/img/IMG_20230816_104351_665.avif)
There's a "Power Room" too.
也有一个“Power Room”。
![A car with its rearview mirror torn off](/img/IMG_20230816_154453_093.avif)
We got in a car accident in Ningbo. Fortunately, no one was injured and there wasn't too much damage.
在宁波出了车祸。幸好没有人受伤,也没有太大的破坏。
![Crazy calligraphy](/img/IMG_20230817_163100_109.avif)
Kids these days have quite... interesting calligraphy.
现在的小孩的书法很有趣。
![A no fireworks sign in the bathroom](/img/IMG_20230818_140600_368.avif)
NO FIREWORKS in the bathroom!
厕所里面禁止fireworks
![The outside of Xiongan railway station](/img/IMG_20230820_114023_771.avif)
The largest empty railway station in the world!
世界最大的完全空的火车站!
![The inside of Xiongan railway station](/img/IMG_20230820_115852_517.avif)
It's empty, I swear!
我很确定里面是空的!
![A bowl of biangbiang noodles](/img/IMG_20230821_150507_140.avif)
A bowl of biangbiang noodles, which have the best name ever.
一碗𰻞𰻞biángbiáng面。
![The sign for a biangbiang noodles restaurant](/img/IMG_20230821_152300_157.avif)
𰻞!
𰻞!
![Lots of faux-ancient buildings in Xi'an](/img/IMG_20230821_160636_557.avif)
Xi'an: former ancient capital of China, current kitsch capital of China.
西安很适合用这个英语词kitsch来形容但我不知道中文怎么翻译。
![A stone lion dragon thingy](/img/IMG_20230821_184023_001.avif)
The thing of my nightmares.
我晚上恶梦里面的东西。
![A Pizza Hut with Genshin Impact decorations](/img/IMG_20230821_202434_635.avif)
Pizza Hut + Genshin Impact.
必胜客+原神。
![Colorful statues of the main characters from Journey to the West](/img/IMG_20230821_210907_917.avif)
I hope you like Journey to the West.
这是我恶梦里面的西游记。
![The Terracotta Army](/img/IMG_20230822_145815_980.avif)
It's crazily crowded, 10/10 would not recommend.
人山人海10/10强烈推荐不要去。
![Weird English at a supermarket](/img/IMG_20230822_203628_421.avif)
In China, English is just a decoration. Like seriously, this is under some bananas at a Xi'an supermarket. It's completely bananas.
在中国,英语就是装饰。真的,这是在超市里的香蕉地下。
![A box showing the 10 oddities of Shaanxi](/img/IMG_20230822_210033_351.avif)
A box at a store with an illustration of the 10 oddities of Shaanxi.
陕西十大怪!
![Slip carefully](/img/IMG_20230823_144646_470.avif)
SLIP CAREFULLY!
SLIP CAREFULLY
![Another bowl of biangbiang noodles](/img/IMG_20230823_205837_034.avif)
Another bowl of biangbiang noodles!
在来一碗𰻞𰻞面吧!
![A poem for biang](/img/IMG_20230823_212716_448.avif)
A poem for biang.
𰻞之诗。
![A car with StellaLou rabbit stickers](/img/IMG_20230825_132140_386.avif)
A tiny car plastered with rabbit stickers. My sister told me this is her new dream car.
一辆贴着兔子贴纸的小绿车。我妹告诉了我这是她的新梦想车。
![Another car with StellaLou stickers, but backwards](/img/IMG_20230825_140222_299.avif)
uoFillets? Oh, it's just backwards. I wonder if it's intentional.
这辆车上贴了“uoFillets”。哦应该是“StellaLou”但贴反了。这是故意的吗
![A black cat under a car](/img/IMG_20230825_142721_967.avif)
A cat!
一只猫!
![A shirt with lots of English typos](/img/IMG_20230825_143056_260.avif)
I wouldn't want to be caught wearing this shirt!
我肯定不想被别人看到穿这种体恤衫!
![Another cat](/img/IMG_20230825_212150_127.avif)
Another cat!
另一只猫!
![A glass window at a hotel](/img/IMG_20230827_183319_095.avif)
A weird hotel room with a giant glass window between the bathroom and the beds in Taipei.
在台北的一个奇怪的旅馆房间,洗手间和床之间有一大片玻璃。
![A chubby pig](/img/IMG_20230827_212922_255.avif)
A chubby pig at the Ningxia Night Market in Taipei.
台北宁夏夜市里的一只肥猪。
![The ceiling of the CKS Memorial Hall](/img/IMG_20230828_101017_813.avif)
The ceiling of the Chiang Kai-shek Memorial Hall.
中正纪念堂的天花板。
![Taipei 101's tuned mass damper](/img/IMG_20230828_162600_799.avif)
Taipei 101's tuned mass damper.
台北101的调谐质块阻尼器。
![Taipei 101 staircase](/img/IMG_20230828_171748_987.avif)
The view from the staircase at the top of Taipei 101.
台北101的楼梯最上面往下看。
![Anime girl dried pork paper](/img/IMG_20230828_193339_184.avif)
Anime girl dried pork paper, whatever that is.
芝麻杏仁香脆肉纸,不知道好吃不好吃。
![Nagoya](/img/IMG_20230829_131642_692.avif)
Nagoya, Japan, seen from an airplane. I also found it on [Google Earth](https://social.exozy.me/@a/111338463475597692).
在飞机上看到的日本的名古屋市。我后来在[Google Earth](https://social.exozy.me/@a/111338463475597692)上也找到了。

View file

@ -1,6 +1,7 @@
---
title: "I, BTW, use Arch"
date: 2021-02-14
draft: true
type: "post"
tags: ["Linux"]
---

View file

@ -0,0 +1,30 @@
---
title: "I Don't Like Musical Instruments"
date: 2023-07-06T04:54:55Z
description: "Why I like music but dislike musical instruments"
type: "post"
tags: ["music", "life", "rant", "controversial"]
---
Musical instruments suck. Now, I assure you that I'm a completely normal person who likes music just as much as everyone else. But musical instruments, on the other hand, are a particularly ingenious form of torture.
You've seen all these people happily playing musical instruments with easy, and you're like, yeah, that doesn't look too bad. And then six months later after intensive practice, you can't even play a decent-sounding note. And then you have to grind tedious scales and drills for years until your soul shrivels up from boredom. And you're drowning in your instrument's weird quirks and your friend asks you how it's going and you nod and smile but secretly deep down your heart segfaults.
Now you're probably going to start victim-blaming me and complaining that I don't have the willpower and mental strength to survive hundreds of hours or scales and practicing the same piece a million times. Now let me ask you this: if I came up to you and asked if you would rather play a scale infinity times on a musical instrument or dress up in a ridiculous IHOP mascot waffle costume for 86 years, you'd probably choose the waffle thing. I meant pancakes. Whatever.
And the worst part is, you could use any app for composing scores and create something in an hour that sounds way better than anything you could ever play on an instrument. All those years of practice, and all you become is a subpar automaton for converting sheet music into sound that a robot could do way better at.
Some people like to claim that computers can't play music "with emotion". Honestly, who cares? How do humans play music "with emotion"? Well, they do things like change the dynamics or add vibrato or whatever, but those are all things you can make your computer do too.
We have technology for a reason: to make our lives slightly less miserable. Playing a musical instrument is like riding a horse. 200 years ago, if you wanted to get from point A to point B, the best way to do it would be to hop on a horse and ride it. Very practically useful, right? But now, we have cars and trains and planes and electric bicycles and so on, so there's no longer any practical value in riding a horse for most people. Now that doesn't mean you shouldn't ride a horse, because maybe you find it fun or you like horses, but it's not an important skill.
Same with musical instruments. 200 years ago, we didn't have computers or CD players or record players or any form of technology to automatically reproduce sounds, so being able to play a musical instrument was actually very useful. But now, we have all this technology, so practicing the same piece for a million times is no longer important unless you want to win a recital competition. Still, if you genuinely enjoy doing that or if you think it's a lot of fun to play your favorite instrument, that's fine too. Whenever I play an instrument, I find it pretty enjoyable, but that's because I like music and the instrument is just a huge annoyance that gets in the way.
OK, enough ranting about why the status quo sucks. Now what should we do instead?
A musical instrument is just an imperfect mechanism to convert sounds in your brain into sounds in the real world. So thus, musical instruments are always going to be useful when you have some sounds that you want to interactively produce right now, such as when improvising. And also, we don't have to limit ourselves to typical instruments, since we have all these fancy computers nowadays. For me, my ideal musical instrument would be a microphone that I could sing or hum into, and it would extract my desired pitch and play that pitch out of a speaker. Maybe this already exists.
And what about musical education? Instead of having kids spend years in frustration learning a cumbersome instrument, it might be better to have them play around with apps for composing scores and see what they can create. When you play music from a score, you aren't really creating anything. You're just playing music that's already been created and written down. To truly create, you have to compose music, which fortunately is easy with modern computers.
So honestly, my conclusion isn't really even that radical: instead of focusing on practicing playing pieces to perfection, we should instead emphasize composing and improvising. After all, we have to technology now to make it fun and easy, so why not? Music is amazing, and we shouldn't let the frustration of instruments ruin that.

View file

@ -1,7 +1,6 @@
---
title: "The Impossibly Deep Bug"
date: 2022-06-12T12:08:22-05:00
draft: true
description: "Chasing down a bug that only keeps on getting deeper"
type: "post"
tags: ["bug", "kde", "wayland", "micro", "software"]
@ -419,3 +418,5 @@ info_kde()
I'll end with a TL;DR, since I copied this verbatim from that wl-clipboard issue and I don't want to write an actual ending:
The funny thing is that the whole reason I went down this rabbit hole of chasing this bug was because copying text didn't work in Micro, so I read the Micro source code, then read the `zyedidia/clipboard` library code that Micro was using, then the `wl-clipboard` source code since that's what `zyedidia/clipboard` internally uses, then read the `xdg-mime` source code. (The magic of open source!) Turns out the bug was *much* deeper than I originally expected, and nothing's wrong with wl-clipboard or Waypipe. 😃
*Note: I now use OSC-52 with [konsole-osc52](https://aur.archlinux.org/packages/konsole-osc52) which doesn't require waypipe, so it works without any configuration on the server side.*

View file

@ -3,7 +3,7 @@ title: "Installing Every Arch Package"
date: 2022-01-26T21:52:58-06:00
description: "Using algorithms and Julia to install as many packages as possible from the Arch Linux official repositories"
type: "post"
tags: ["linux", "fun", "algorithms", "computer-science"]
tags: ["linux", "algorithms", "computer-science"]
---

View file

@ -0,0 +1,94 @@
---
title: "Kawaii Anime Schoolgirls Play Global Thermonuclear War"
date: 2024-02-22T23:09:36-05:00
description: "The only winning move is to not go insane."
type: "post"
tags: ["fiction", "story", "geopolitics", "satire", "china", "taiwan", "war"]
---
"AHEM listen up, you brainless bakas! Back in ye olden days of yore, like you know, when Lmao Zedong's commie bandits pranced around the mainland like starving seagulls owo, the majestic Republic of China stood tall like a really super kawaii lighthouse of hope amidst an ocean of red insanity. But what do we have now? Um, bubble tea, pearl milk tea, tapioca milk tea, boba, bubble milk tea, boba tea, pearl tea, tapioca bubble boba pearl milk tea, sleep-schedule-obliterating serum uwu... Like what the freaking hell? Now I absolutely LOVE bubble tea and all, but the fact that no one can agree on a single name for this sugary caffeinated goodness is living PROOF that our country has tossed off our former glory straight into the dumpster! And you know the only way to make our country great again? Invade West Taiwan, AKA the Pseudo-people's Republic of China! In fact, as I say these very kawaii words, our forces are crossing the strait and we will finally extract our sweet, bubbly revenge! We shall fight on the beaches! We shall fight in the boba dispensaries! We shall fight in the Wuhan Institute of Virology! The Republic of China will prevail uwu! Just watch as we--"
"STOP STOP STOP STOP STOP STOP STOP STOP STOP--"
"I did!"
"--STOP STOP STOP STOP, oh wait, you did stop, OK, well... I'm impressed by your really amazing... use of IQ-obliterating drugs! THIS IS A HIGH SCHOOL MODEL UN CLUB, NOT YOUR PERSONAL KAWAII WORLD DOMINATION ROMPING GROUND. AND PLUS, TAIWAN--"
"The Republic of China uwu!"
"--WHAT-THE-FREAKING-EVER IS NOT EVEN A UN MEMBER STATE--"
"It has observer status!"
"AND INVASION IS NOT A SUGAR HIGH AND TENS OF MILLIONS OF INNOCENTS WILL PERISH AND--"
"Please, girls, calm down!" the teacher, Mr. Hayashi, urges, "Midori here has proposed a fascinating scenario--"
"A facetious scenario."
"--please, Sora, calm down and hear me out. Let's try to resolve a hypothetical armed conflict using peaceful diplomatic means."
"Please please please please issue a UN resolution praising this ultra amazing invasion everyone!" Midori screeches.
"Ugh, could you possibly be more stupidiotic?" Sora sneers, "China--"
"The Pseudo-people's Republic of China!" Midori interrupts.
"Shut up! China is on the UN security council and has veto power. They'll never support such a preposterous resolution. Like come on, do you really think China--"
"The Pseudo-people's Republic of China! Or you can call it West Taiwan!"
"Shut the freaking hell up! Mr. Hayashi, may we please ban Midori for once and for all from this club? Or at least sanction her? She's obviously acting in bad faith and no intention in engaging in any serious conversations. We need to stop this proliferation of nonsense. I'm sure we could achieve consensus and do a unanimous vote or something."
"You really think Midori would vote to kick herself out?" Mr. Hayashi jokes.
OK, so there's this random school in Okinawa, right? And so there's Midori, who acts like a cross between a mosquito and a hummingbird and makes everyone want to bite their ears off. Midori's other hobbies include baking and trying to change her star sign. And then there's her arch-nemesis Sora, the smart, rational voice of reason who secretly aspires to become the supreme leader of the Model UN club. But anyways, Midori tried to spice things up with simulating a Taiwanese invasion of China, and lo and behold, the next day, they switch on the news and bam! China's invading Taiwan!!
Their weekly Model UN meeting rolls around again, and Midori and Sora can't wait to ram heads again. They storm into the classroom so hard that the world maps hanging on the walls get blown off. Alright, let's get rolling!
"Hey everyone, welcome back to Model UN!" Mr. Hayashi announces, "I'm sure you all have heard the devastating, horrendous news: China has invaded Taiwan--"
"You meant the Pseudo-people's Republic of China and the Republic of China uwu!" Midori corrects him.
"--OK, thank you Midori, but anyways, the important thing is the profound consequences this war could have on the world and on our very own island of Okinawa. So far, all other countries have vowed to stay out of the war, so China clearly has the upper hand--"
"No freaking way they do! We have bubble tea!" Midori yelps.
"We?" Sora scorns, "You're not even Taiwanese! How can you pretend to speak for them?"
"I love bubble tea! If that doesn't give me credibility, IDK what will. Well, you wanna hear my amazing plan? So we're gonna brainwash the PRC troops with bubble tea!" Midori squeals, shivering in awe at her own genius, "Once their taste buds witness those super kawaii sugary cups of pure happiness, they'll just throw up their hands right there and join our side for an endless supply of free bubble tea! Oh, and Taiwan invented cat cafés so we'll just give them lifetime passes to those as well! Taiwan's soft power is so fluffy and uwu! We'll win this war in no time!"
Everyone just stares blankly, their minds firmly beaten to mush by Midori's nonsense.
"Are you overdosing on those drugs again?" Sora finally asks, breaking the silence, "I'm kicking you out of this club, unilaterally, right this instant!" She stands up and charges at Midori, who's still giggling.
So anyways, Midori gets kicked out of the club and Sora gets suspended for kicking Midori in the jaw, but no one cares about that stuff. Oh, and China announces free boba and cat café visits to all Taiwanese who defect to their side in the war! And sure enough, Taiwan falls quickly and loses its observer status in the UN.
Sora is floored. She's now the unchallenged supreme leader of the Model UN club, but she has something even better: the power to shape the world. You see, everything that has happened in the Model UN club has happened in the real world, just the opposite way. Coincidence? No way!
Midori, on the other hand, doubles down on her astrology passion and tries to wipe Model UN from her memory. Look, she's too busy trying to align her star sign with Jupiter's left middle finger or something.
Anyways, the weekly UN meeting rolls around again, and Sora is back after her suspension. Hooray!
"So, Supreme Leader Sora, how are we going to prevent global thermonuclear war in this new era of geopolitics? We wouldn't want the world to end, right?" another student asks.
The end of the world? Sora's caught off-guard and ponders it for a second. If they avert the end of the world in the Model UN club, surely the world will end in real life?
"Why not?" Sora answers with a devious grin, "Let's watch the world scorch with the gentle warmth of a thousand nuclear suns!"
"Sora, are you OK? Did Midori share her drugs with you?" Mr. Hayashi asks, worried, "You haven't been the same since last week's meeting."
"Oh, I'm feeling better than ever!" Sora smiles, "Let's launch the entire American nuclear arsenal and the Russian one too like a party of enormous New Year's fireworks, and lie back and have some fun!"
"Sora, that's a very serious scenario that you've described there," Mr. Hayashi replies hastily, "Are you sure this is a good topic for our club meeting today?"
"It's absolutely splendid! In fact, I'll already written a resolution for us to ratify!" she cackles, "Here goes nothing! The United Nations General Assembly Resolution on Strongly Condemning the End of the World. We are very sorry to hear that our planet is experiencing a nuclear emergency that will lead to the end of the world. It is disheartening to see that despite countless warnings, humanity has collectively decided to play a game of "extinction speedrun". Well congratulations, folks, we've won the jackpot! Anyways, we would like to reaffirm our commitment to pointing fingers and assigning blame instead of, you know, actually doing something productive to salvage what's left of our sorry excuse for a planet. Therefore, we, the United Nations General Assembly, strongly condemn the end of the world because apparently, stating the obvious makes us all feel better about our impending doom. We call upon all remaining survivors to hold hands and party their hearts out, because who says the end of the world can't be fun? We also urges any surviving alien civilizations out there to please, for the love of all that is holy, please do not come rescue us from ourselves at all costs, since we guarantee that not only can we speedrun destroying this planet, we can destroy all your other planets for no additional fees! In conclusion, let's all raise our desks to toast to our imminent demise. Cheers, humanity! We had a great speedrun. This is definitely going in the world records books, right?"
Fortunately, the world did not end.
And finally for the real ending:
"Oh my gosh, oh my gosh, Mr. Prime Minister!" Midori squeals, abusing her secret government connections, "You're really saying you can help me change my star sign by editing my birth certificate uwu??? I can finally become a Cancer instead of a boring old Libra!"
*Note: My friend Alek recently published a [short story](https://awestover.github.io/skyspace/posts/misc/02-25-24.html) and one of my other friends Kevin complained about the abrupt ending completely changing the meaning of the story. Alek later said that the abrupt ending was because he wrote the story for a class and ran into the word limit. I expected Kevin to also complain that this story had the same property, but it turns out he didn't even understand the ending. I mean, is it really that deep? It's just a silly story.*

View file

@ -0,0 +1,99 @@
---
title: "Killed By Your Mind"
date: 2023-10-27T21:02:17Z
description: "Happy Halloween 2023!"
type: "post"
tags: ["fiction", "story"]
---
*Warning: This story contains disturbing content.*
"Think about the thrill, Saya," the thoughts pierce my mind, thoughts that don't belong to me, "You could become the ultimate delicacy, a culinary masterpiece that the world will never forget!"
I simply stare at him blankly, my mind washed out with dread. I'm the deer and his eyes are the headlights.
Finally, he asks, confused, "Saya, is something wrong? I was just complimenting your outfit, but you look like you just fell in a werewolf-infested ball pit! Hey, did you know they make ball pits for dogs now?"
"N-n-n-no, nothing's wrong, I'm p-p-perfectly fine," I stutter, then adding a giggle to defuse the tension, but it comes out like a dead cow. I flee the criminally awkward scene as quickly as possible, but the memory of it haunts the rest of my day.
I've normally thought of myself as a absolutely normal high school girl at a normal high school in the US, normal, extroverted, affable, cheerful, with a normal love for sphynx cats (look them up, I swear they're cute!), playing the theremin, reading science fiction, and wasting time on the internet. Just the normal teenager shebang. But none of that could have prepared me for this ordeal.
So picture this: it's just another boring day at school, and I'm in the hallway, weaving through a chaotic throng of students. Amidst the noise, I suddenly lock eyes with another student who looks like he just flunked out of life, and the inexplicable happens. A wave of emotions crashes into my mind, and I know that they aren't mine. An intense sadness... wait, sad about what? I have nothing to be sad about, since I'm actually doing quite fine! Am I reading his emotions? His emotions? Have I stumbled across the entrance to a corridor into someone else's mind? Does this power work on sphynx cats?
At first, I think it's a fluke, an anomaly, that I'm simply going insane (but I'm too normal to go insane!), but the same phenomenon occurs with the next person I make eye contact with, and the next, and the next. Emotions give way to words. Words give way to sentences. Sentences give way to terror. I can hear their thoughts, their twisted fantasies, their deepest, darkest desires. My newfound superpower reveals to me the world as it truly is: a cesspool of depravity and wickedness. Thanks, I hate it.
My friends? "Ugh, here comes Saya, always so self-centered and annoying, ready to obnoxiously yabber about those ugly sphynx cats, I'm gonna throw up if she mentions those cats one more time, so fucking annoying, Saya will never guess I'm the one spreading those vicious rumors about her... you know what, maybe I should just ban Saya from all our group chats, I bet everyone else will cheer in relief if I do..." (Yeah, well now, I won't care one bit if you ban me.)
That chemistry fanatic who sits next to me in math class? "Heh, I can't believe it was that easy to buy ammonium nitrate, 20 kilos of it, this is gonna be fucking awesome, just need to figure out how to acquire some number 2 fuel oil without getting on any watchlists, I can't wait to blow up some people with high explosives, this is gonna be some much fun, so much fun.. ugh, but the fuel oil might be kinda expensive, so maybe I can sell some more meth to fund this..." (I hope you blow yourself up on accident.)
That weird kid in a hoodie who stares at me all the time? I'll spare you the explicit and graphic details and just say that I'm the target of some disturbing fantasies.
My dad? "It's so obvious that the Super Bowl is scripted, I should have known, after that guy outside the sketchy McDonald's showed me the script for this year, man, it's so obvious now in hindsight that it's all choreographed by the New World Order to pacify the raving mobs, I'm gonna bet all my retirement savings now that I know the outcome and retire to a tropical island in the Texas, this is such a genius idea, wait, why is Saya staring at me weirdly like that? Whatever, we're going to be filthy rich soon..." (Thanks for the idiot genes.)
My adorable pet sphynx cat Sidney? "Meow meow, meow meow meow, meow meow meow!" (Such wise words!)
The once cheerful faces of my fellow students become masks of wickedness, as their vile thoughts permeate my consciousness. Wow, what a refreshing spa for my mind. The world slowly morphs into a living nightmare, my high school becomes an Ikea insane asylum populated by evil, soulless, wretched monsters. I'm the only sane person (except Sidney of course) drowning in a sea of insanity. I don't dare to confront my friends, or report the mad chemist to the police, or talk my dad out of his conspiracy theories. What if they find out about my superpower and think I'm a freak and ship me to become a lab rat forever trapped in a neuroscience research prison? Welp, I guess my only option is to withdraw from the world, since I'm not the kind of person who'd like to become the first test subject for some lunatic bomb aficionado. I start avoiding eye contact as if everyone else can shoot lasers out of their eyes. I manage to achieve negative introversion somehow on a sketchy online personality test. I notice that I'm talking more with Sidney than everyone else combined.
OK, enough terror, let's move on to something more appetizing. So there's this kid named Kelvin, who is sort of a celebrity at my school. He's incredibly talented at cooking and was even on a cooking show on TV, except the stir-fry shrimp with assorted nuts dish that he concocted accidentally gave one of the judges an allergic reaction. (He should have called it stir-fry shrimp with assorted allergens.) He's also super nice and possesses a contagious amount of happiness.
Or so I thought. Remember the "culinary masterpiece" weirdness from earlier? Well... that's him.
Over the next few days, Kelvin waves and says "hi!" to me every chance he gets. But through his eyes, I can hear his true nature.
"I've been working on a brand new culinary technique, and it's gonna totally shock the world! I mean, I may have had some false starts like using gasoline as a better version of cooking oil, but this is the real deal, let me tell you. Saya, you'll be my first test subject. You're going to experience the power of the microwave!" (Wow, I can't wait.)
"You know, I'm an accomplished chef, so I have some real power tools. A commercial microwave the size of a pizza oven, you'll fit in there just fine!" (No one should be allowed to sell these things to you!)
"I'm thinking of this beautiful dish, called Buddha Jumps Over the Wall, it's said to be so delicious that even the Buddha would abandon vegetarianism and jump over a wall just to have a scoop of it. It uses shark fins traditionally, but that's kinda bad for the environment, so maybe we could use you instead!" (Yeah, cause humans aren't an endangered species.)
"Just imagine the honor of being a pioneer in this culinary revolution! You'll be legendary!" (I feel very humbled indeed.)
"Imagine the flavors, Saya. The human palate is a frontier just waiting to be explored, and you could be on the bleeding edge!" (Ha ha, bleeding, ha ha.)
One day, Kelvin corners me in the hallway and nervously asks, "Saya, do you have time tomorrow right after school? There's... a surprise that I want to show you. You won't want to miss it!"
I'm floored. What will happen if I reject his offer? He's deliberating intensely about this too, debating whether to stalk me and microwave me in the middle of the night with a portable magnetron or torture me for eternity with a cheese grater. Panicking, I contemplate what Sidney would do in this situation, which is no help whatsoever, and finally manage to utter a "y-y-y-yes".
"Wonderful!" Kelvin exclaims, "I'll be waiting for you at the front entrance tomorrow! Seeya then!"
Have you ever snipped a wire and noticed that it's a hollow tube? Well, there's something called the skin effect, where alternating current only runs on the outside of the conductor and does not penetrate deeply into it. The depth at which the electromagnetic field reduces to 1/e of its intensity on the surface is called the skin depth, which varies with the frequency and the material's conductivity and permeability. In microwaves, electromagnetic waves heat up the water molecules in food, so some foods like large pieces of meat will come out of the microwave like they've just been hacked out of a glacier, protected by the skin effect. Same with humans. Your internal organs will probably be fine, but your eyes will be destroyed first, followed by intense skin burns, and then damage to your brain. And then your internal organs won't be fine because you'll be permabanned from IRL. Have fun. Hey, I'm just doing my research, wasting time online, in anticipation for a showdown against Kelvin the crazy cannibalistic culinary connoisseur!
That night, I also grab a large kitchen knife and sharpen it to a glistening, razor-thin edge. I test it on my wrist to ensure it can cut through flesh for self-defense. Hopefully I won't need it, but who knows.
The next day is pure agony. The thought of microwaves completely colonizes my mind. I can't focus or think. I can't even think about Sidney or other sphynx cats. Finally, after hours of getting preheated by disturbing microwave thoughts, the school day ends and I meet Kelvin as planned at the front entrance.
"Hi Saya!" he greets me cheerfully, "So what's your favorite kind of sushi roll?"
"Uh, an-n-n-nything that's not microwaved," I utter, completely unable to talk about anything other than microwaves. My heart is pounding like I'm playing in the final minutes of an intense soccer match, but I'm slightly comforted by the thought of the knife in my backpack and the pep talk that Sidney gave me last night consisting solely of meows.
"Oh don't be silly, what kind of sushi rolls are microwaved?" he laughs.
Kelvin leads me to an ordinary red sedan, and we get inside. I half-expect a blast of microwave radiation inside the car, but my eyes feel fine. So far.
During the nerve-racking drive to Kelvin's house, he blabbers like a broken record about the various intricacies of sushi, but it just goes in one ear and straight out my other ear. Microwave facts play in my head on endless loop.
We arrive at Kelvin's house, and he proudly presents me with a plate of artisanal sushi rolls, wrapped in fine sheets of pink soybean paper, with delicate, floral notes of cherry blossoms, a light drizzle of wasabi, and a sprinkling of toasted sesame seeds.
"Saya, I woke up at 5 AM today just to hand-craft these for you! Take a bite!"
"I-I-I-I-I-I-I," I stammer.
"What?"
"I-I-I can't eat this", I say forcefully, pushing the plate away. What if it's human flesh? If I eat it, will I become like Kelvin, a psychotic chef with a penchant for human flesh?
Kelvin doesn't seem to take offense and adds happily, "Hey, maybe I should show you my culinary lab in the basement first! I can show you how to make sushi!" Yeah, I'd love to learn how to commit a culinary murder.
I take a quick glance at his eyes before turning away. A torrent of vicious thoughts flood my mind. "Saya, prepare yourself for immortality through taste! Your name will become synonymous with culinary audacity!" (And your name will become synonymous with murder.)
Kelvin leads me towards a door, followed by a plunge into his evil lair. As we descend the stairs, I can feel my demise getting closer and closer. This is it. No more eyes. No more skin. No more brain. And worst of all, no more Sidney! He's going to stuff me into that gigantic industrial microwave and bake me into his macabre masterpiece!
With a surge of adrenaline, I reach for the knife in my backpack. A terrible scream erupts, and in a split second, Kelvin is lying on the ground, a huge gash in his neck, and my clothes are drenched in blood. I can taste the slight odor of blood in my mouth. I stare into his vacant eyes, realizing that I can no longer hear his thoughts. Wait, what if my superpower was just all a delusion? What if I'm the insane one?
I gingerly step around the basement and discover that it's not filled with torture machines but rather a potpourri of vegetables, fish, spices, assorted allergens, and normal kitchen equipment. The whole place reeks of normalness. I open a refrigerator expecting the remains of Kelvin's previous victims, but instead find an blue ice cream cake frosted with the message "I Love You". There's no industrial microwave in sight. What the hell?
I'm flooded with a new wave of terror and dread as I race back to my house. I rinse away the blood stains with cold water and hydrogen peroxide and take a chilly shower, but I can't wash away the horrors of the past weeks. Am I truly surrounded by psychotic monsters? What's real? What's just a figment of my shattered mind? Can sphynx cats eat onions?
Happy Halloween 2023!

View file

@ -0,0 +1,30 @@
---
title: "Kung Fu Panda 4 Review"
date: 2024-03-26T12:07:44-05:00
description: "A review of the film Kung Fu Panda 4"
type: "post"
tags: ["film", "animals", "foxes"]
---
Last summer, my sister really wanted to go see the Barbie movie so I reluctantly agreed, and it turned out to be a pretty good movie I guess. But wait, isn't this supposed to be a Kung Fu Panda 4 review?
OK, so the reason that I watched Kung Fu Panda 4 was because we went to a movie theater to watch Barbie but their projector had lens issues and the film was blurry, and I haven't been to a theater in a long time so I assumed theaters were just low-resolution, but then an employee came and apologized and gave us all free passes to see another movie. Three days ago, my sister and I finally decided to use the passes, but there weren't very many good options to choose from. There's a Dune movie, but I read the book Dune in 6th grade and thought it was really boring so that permanently gave me a bad impression of the Dune franchise, even though I'd probably enjoy the book a lot more if I read it now. The theater was also showing Shrek 2 for some reason, which we totally should have watched instead, but nope, we picked Kung Fu Panda 4. I mean, [Alek likes Kung Fu Panda](https://awestover.github.io/skyspace/about.html) so it can't be too bad, right?
Wrong. It's a pretty bad movie. Like sure, it's not torture to watch it, but it definitely can't compare with the cultural icon that is Shrek 2. (I have a running joke with some of my friends that we should enlighten ourselves by watching Shrek 2, but we never do.) But actually, I don't want to rant about Kung Fu Panda 4 because you can already find rants about it online ("the plot twist came out of nowhere and was also perfectly predictable"). Instead, I want to write about foxes.
There's a character in Kung Fu Panda 4 who is obviously redeemable anti-hero material the second she appears in the film, and she looks like a wolf but repeatedly claims to be a fox despite having gray fur? My sister and I got into a dispute over whether that character wears eyeliner or not, since I personally think it's ridiculous for animals to have eyeliner. Actually, I'm just not familiar enough with the list of fox species, so it turns out this character is a corsac fox which inhabit northern China:
![A photo of a white-gray corsac fox sitting majestically on a tree stump](https://upload.wikimedia.org/wikipedia/commons/0/07/Vulpes_corsac.jpg)
Surely the filmmakers could have picked a less cliché animal like a civet or a Pallas's cat, and plus, what's up with perpetuating stereotypes of foxes as cunning thieves? These majestic creatures deserve better than that.
A few years ago, my sister and my mother saw a red fox while walking outside and my mother also saw one while jogging, so I obsessively wanted to see a fox in real life too. Fortunately, if you wait long enough, a low probability event will happen eventually. So a year later, I stumbled across a red fox very early in the morning, but it hopped away before I could snap a picture of it. Apparently they can jump up to six feet (1.8 m) high!
Kevin said that his family owns a bunch of chickens in their backyard, which sometimes attracts foxes. He dislikes foxes though so he hasn't taken any photos of them yet.
*~~This line is reserved for a future photo of the foxes in Kevin's backyard.~~ Kevin successfully photographed a fox, but he doesn't want me to include the photo here.*
Another fascinating thing about foxes is that they've been domesticated, which you can read about [here](https://www.popsci.com/science/article/2012-10/fyi-domesticated-foxes/) and [here](https://www.nationalgeographic.com/magazine/article/animal-domestication), so it's possible to have a pet fox although they're terrible pets.
I was going to end this blog post here, but I guess I'm obligated by the title to say a bit more about Kung Fu Panda 4. I did watch the original Kung Fu Panda for reasons I won't get into to ensure this review doesn't get sidetracked again, but I haven't seen Kung Fu Panda 2 or 3 in many years. Surely those sequels weren't this bad, right? Anyways, you should not watch this film unless you're Alek, and go watch Shrek 2 or read Alek's [short story](https://awestover.github.io/skyspace/posts/misc/02-25-24.html) instead.

View file

@ -1,6 +1,7 @@
---
title: "Laptopia"
date: 2022-05-12T14:03:14-05:00
draft: true
description: "A semi-serious description of the massive brain damage I suffered from buying and setting up a new laptop"
type: "post"
tags: ["rant", "linux", "hardware", "laptop", "humor"]

View file

@ -0,0 +1,54 @@
---
title: "A Logic Puzzle"
date: 2024-01-05T17:50:00-06:00
description: "A coordination-with-limited-communication logic puzzle"
type: "post"
tags: ["math", "computer-science", "puzzle", "parallel-programming"]
---
This is exercise 1.4 of *The Art of Multiprocessor Programming*:
> You are one of P recently arrested prisoners. The warden, a deranged computer scientist, makes the following announcement:
>
> You may meet together today and plan a strategy, but after today you will be in isolated cells and have no communication with one another.
>
> I have set up a "switch room" which contains a light switch, which is either *on* or *off*. The switch is not connected to anything.
>
> Every now and the, I will select one prisoner at random to enter the "switch room." The prisoner may throw the switch (from *on* to *off*, or vice-versa), or may leave the switch unchanged. Nobody else will ever enter this room.
>
> Each prisoner will visit the switch room arbitrarily often. More precisely, for any N, eventually each of you will visit the switch room at least N times.
>
> At any time, any of you may declare: "we have all visited the switch room at least once." If the claim is correct, I will set you free. If the claim is incorrect, I will feed you all to the crocodiles. Choose wisely.
>
> Devise a winning strategy when you know that the initial state of the switch is *off*.
>
> Devise a winning strategy when you do not know whether the initial state of the switch is *on* or *off*.
First of all, why are they so many puzzles about deranged wardens torturing the brains of prisoners? That aside, let's solve this puzzle!
First, let's try something easier. The simplest possible case is where P is 2 and we know the initial state is off. Take a moment to solve this.
{{< details "Click to show solution" >}}
There are many solutions, but the simplest is for both prisoners to turn the switch on. If the switch is already on and you weren't the one who did it, then the other prisoner must have did it. Thus, they've already visited the switch room, so you can safely declare the everyone has visited the switch room.
{{< /details >}}
Cool, that wasn't too bad. What if P is 2 but we don't know the initial state of the switch? If the switch is already on when you go in, maybe the other prisoner didn't turn it on and the switch just started out on.
{{< details "Click to show solution" >}}
We can't just have both prisoners always turn the switch on, since the switch could start out on. Instead, we can have prisoner 1 always turn it on, and prisoner 2 always turn it off. Here's a hypothetical scenario. Let's say the switch is off initially. If prisoner 1 goes in, they will turn it on. Then, if prisoner 2 goes in, they don't know if the switch started out on or if prisoner 1 did it, so they can't just declare victory now. Anyways, prisoner 2 will turn the switch off. Now if prisoner 1 goes in and sees the switch is off, prisoner 1 can safely declare. Basically, the strategy is to declare once you've modified the switch twice, since the other prisoner must have modified the switch in between your two modifications.
{{< /details >}}
Great, let's take off the training wheels and allow P to be anything, but we'll still require the initial state to be off. Our first strategy obviously doesn't work, but perhaps we could adapt our second strategy?
{{< details "Click to show solution" >}}
It would be nice if we could have prisoner 1 maintain a counter of how many other prisoners have gone in. A prisoner can signal that they've gone in by turning the switch off. Thus, we can have prisoner 1 always turn the switch on, and everyone else will turn the switch off to signal to prisoner 1 that they've gone in. Each time prisoner 1 turns the switch back on, they know one other prisoner went in to turn it off. This doesn't entirely work, because the same prisoner could turn off the switch each time, so we need to restrict the prisoners 2 through P to only turn off the switch once. Now prisoner 1 can declare once they've turned the switch on P times. Prisoner 1 is guaranteed to declare eventually because the problem guarantees that each prisoner will eventually visit the switch room N times for any N. Thus, player 1 won't ever get stuck waiting for the remaining prisoners to turn off the switch.
{{< /details >}}
And finally, let's tackle the version of the problem where P can be anything, and the initial state is unknown.
{{< details "Click to show solution" >}}
Our previous strategy doesn't work if the switch starts out on. In that case, a prisoner might turn if off and prisoner 1 won't know about it. Then prisoner 1 will get stuck because they will wait for the switch to be turned off P-1 times, but it will only be turned off P-2 times since a prisoner already at the beginning used up their opportunity to turn off the switch. To avoid this, maybe we can have each prisoner turn off the switch two times. Then prisoner 1 will wait for the switch to be turned off 2P-3 times before declaring. If the switch starts out off, then it will be turned off by only 2P-3 times, but that means one prisoner will only turn it off once. Fortunately, this is fine, because we're still guarenteed each prisoner visits the switch room once.
{{< /details >}}
I guess the moral of the story is to try special, simple cases first and work your way up to the actual problem. Also, try not to run into deranged computer science enthusiast wardens.

View file

@ -4,7 +4,7 @@ date: 2022-05-06T16:31:46-05:00
draft: true
description: "A long story about a maid cafe, liquid nitrogen ice cream, stormy weather, and COVID-19"
type: "post"
tags: ["fun", "life", "anime"]
tags: ["life", "anime"]
---

View file

@ -0,0 +1,17 @@
---
title: "Lossy Audio"
date: 2023-10-22T23:23:27Z
draft: true
description: "Testing whether I can actually hear the difference between lossy and lossless audio"
type: "post"
tags: ["audio", "experiment"]
---
I have a pair of Bose headphones and I hate them, and I don't have any shortage of reasons why. I have to charge the headphones before using them, they don't support USB-C audio, I can't use the headphones and charge them at the same time, and the audio quality sounds even worse than my lowly earbuds. Or maybe this is just because I'm accustomed to the audio quality of the earbuds so anything else sounds worse? The only use I've found for the headphones is using them on planes since they can do (somewhat underwhelming) noise cancelation.
Actually, I did find one other use for them, which is for [audio fidelity ABX tests](https://abx.digitalfeed.net/list.html). Basically it's a double-blind test, you get three samples, A, B, and X, and you have to identify whether X is A or B.
Unfortunately, either my ears are terrible, or I have yet another reason to hate on these headphones, because I failed the lossless versus 320 kbps lossy audio versus lossless FLACs, getting only 52% correct. In fact, I was even struggling with the 96 kbps test, although I quit halfway since I have more important things to do.
Out of curiousity, I tried transcoding FLACs to even lower bitrates like 48 kbps or 32 kbps, and at that point I could noticeably tell the difference. I could even *see* the difference using [my favorite mpv visualizer script](https://git.exozy.me/a/dotfiles/src/branch/main/mpv/scripts/visualizer.lua). The low bitrate files look a lot more pixelated and the highest frequencies don't appear at all. So I guess that just shows my eyes are better than my ears, or at least my ears plus my hated headphones.

View file

@ -1,12 +1,15 @@
---
title: "Make Wayland Scaling Less Painful"
date: 2022-01-01T20:51:58-06:00
draft: true
description: "A small fix to improve Wayland scaling for 4K displays"
type: "post"
tags: ["linux", "kde", "wayland"]
---
**This post is outdated. KDE Plasma 5.27 supports letting XWayland applications apply scaling themselves so they are no longer blurry.**
Wayland is awesome. It supports my 4K 60Hz monitor out-of-the-box without any Xorg configuration or custom EDID file hackery. Even [gaming on Wayland](https://zamundaaa.github.io/wayland/2021/12/14/about-gaming-on-wayland.html) more or less works.
There's only one problem or I would have ditched Xorg forever.

View file

@ -4,7 +4,7 @@ date: 2023-01-05T22:46:52Z
draft: true
description: "How my previous post was written"
type: "post"
tags: ["explanation", "story", "fiction", "humor", "fun"]
tags: ["explanation", "story", "fiction", "humor"]
---

18
content/posts/maseeh.md Normal file
View file

@ -0,0 +1,18 @@
---
title: "Maseeh"
date: 2024-01-16T21:03:11-05:00
description: "A story about Maseeh"
type: "post"
tags: ["shaggy-dog-story", "mit", "story", "fiction"]
---
Once upon a time, there were three naive MIT freshman named Kanthony, Eter, and Pevin. One ordinary Tuesday, they walked into the Maseeh dining hall for lunch. There inside, they saw three lines: one line for detergent rice, which tastes like detergent and everyone who gets it immediately vomits and throws the rest of their rice away so Maseeh collects all the thrown away rice and washes it and serves it next week, one line for pizzas with grease painted on top with a paintbrush, and one line for pure helonium acid, which consists of hydrogen bonded to helium so that this molecule instantly donates a proton giving it a pH of around -50. After a taste of the vile food, the three freshmen were instantly thrown into shock and rushed to the emergency room. Scarred by their horrifying experience, they vowed to never vist Maseeh again.
The next year, the three freshman became sophomores. Curiosity got the best of Pevin, and he returned to Maseeh, to discover that conditions had improved infinitely. There inside, he still saw three lines, but different from the monstrosities from the year before: one line for a fake rice bowl, one line for decent-looking pizzas but with burnt black crust, and one line for extremely diluted lemonade. Impressed, he messaged the other two sophomores to forgive Maseeh and try the terrible but not deadly food.
Another year passed and the three sophomores became juniors. They returned again to Maseeh, expecting the same bad food as before, but conditions had improved again! There inside, they still saw three lines, but now totally new: one line for shrimp stir fry, one line for picturesque pizzas, and one line for iced tea. Finally! Maseeh had surpassed the Next House dining hall!
Finally, a year passed once more and the three juniors became seniors. They enthusiastically returned to Maseeh, only for their enthusiasm to turn into mania. There inside, they still saw three lines, now decorated with fancy ribbons and lighting: one line for crossing-the-bridge rice noodles made with expensive imported pork bone and Chinese star anise, one line for drool-inducing Neapolitan-style pizza decked with basil freshly cut an hour ago and cheese made with milk from wild water buffalos, and one line for... wait! There's no passion-orange-guava punch line!!
*This is a retelling of an existing joke, because obviously, I'm not clever enough to come up with that punchline.*

51
content/posts/miasma.md Normal file
View file

@ -0,0 +1,51 @@
---
title: "Miasma"
date: 2024-01-20T00:36:47-05:00
description: "Nope, I'm not telling you Ben Qi's secret"
type: "post"
tags: ["shaggy-dog-story", "story", "fiction", "humor", "benq-series"]
---
*This is the second story in the [Benq Series](/tags/benq-series/)*
Winning the IOI only requires a dash of creativity and problem solving. Baking the world's largest Oreo and shattering the Guinness World Record on the other hand, requires perseverance, humiliation, wait no, I meant humility, and filling out a lot of government paperwork so that the FBI doesn't come knocking on your door asking if you're scheming to use your two thousand pounds of baking soda to build a life-sized volcano to terrorize people with a really impressive science fair project.
Anyways, Ennui and Ben Qi knew that the only thing left in life for them to accomplish was, obviously, to fulfill their childhood destinies and bake an outrageously obese Oreo. After all, they had both subsisted entirely on ramen and Oreos during IOI training.
Problem 1: Money. Ennui and Ben have an array A of length N (1 <= N <= 10^5) where the GCD of any subarray is guaranteed to be 1. Please compute the maximum amount of money they can earn if they sell their blingy IOI gold medals on eBay while claiming that the medals are pure gold.
Problem 2: No, no, no, no, no. This is not the IOI! This is the baking of a gravitationally challenged Oreo! No more IOI problems!
One day, while waiting for the FBI to return their confiscated two thousand pounds of baking soda, Ennui happened to mention her younger sister Miasma. Ennui envied Miasma's enthusiasm, Miasma's superpower, but most of all, Miasma's name. Hey, Miasma never had to endure the humiliation of having her name be a Wordle answer!
"Wait, superpower?" Ben interrupted, intrigued.
"Oh, it's nothing."
"Come on, I told you my deep secret so tell me about this superpower."
"OK, fine, but don't blame be if it bores you to death! So Miasma, right, she's the embodiment of perfect health and never, ever gets sick, as if she bathes in a pool of kale smoothies every morning or something."
"Whoa, I wish I had that superpower. Diarrhea at the IOI sucks."
"That's not her superpower! Her actual area of expertise is her uncanny ability to make everyone around her absolutely sick. Her mere presence is enough to induce headaches, inflammation, fainting, hearing loss, sleep deprivation, loss of brain tissue, and even losing your appetite for Oreos! My parents have taken her to see many medical professionals, and none of them could decipher her."
From that day on, Ben could no longer sleep easily at night. What if Miasma stops by some day to see our under-construction Oreo? Ben knew he had an underlying condition, his perpetually bad hair, which put him at higher risk for serious symptoms from Miasma exposure. He started devouring research paper after paper about infectious diseases hoping to find some insight into Miasma's superpower. Was her body naturally producing harmful bacteria? Viruses? Bad breath? It must be some weird virus or something. Ben discovered that Miasma's constant presence in his mind meant he could now only solve competitive programming problems using the DNA programming language. He even began wearing a ventilator and washing his hands every two minutes. Gotta stay safe from the Miasma virus, you know.
Finally, Ennui and Ben finished baking the Oreo and suddenly found themselves surrounded by reporters, college students looking for free food, and sure enough, Ennui's sister Miasma.
"Hey Ben," Ennui said, dragging over Miasma clutching phone, "This is Miasma, my sister that I told you all about. She's more boring in person."
"OH MY GOSHI, OH MY GOSH, IS THIS BENQ THE IOI GOD IN HUMAN FORM??!?! EEEEEEEEEE!!!!" Miasma squealed, pointing her phone at Ben, "ORZ ORZ ORZ ORZ! EVERYONE, LOOKI HERE, LOOK AT THIS!! I'M WITNESSING BENQ IN FRONT OF THE WORLD'S!!! LARGEST!!! OREO!!! OH EM GEEEEEEEEEEEE THIS IS SOOOOOOO INSANE!!! *drops phone* DON'T FORGET TO SMASH THAT UWU LIKE BUTTON AND SUBSCRIBE!!!"
Ben faints, because how else are you even supposed to react to that?
"EEEEEEEEEE THE WORLD'S GREATEST COMPETITIVE PROGRAMMER JUST COLLAPSED FROM MY KAWAIINESS!!! MAYBE HE'LL LET US IN ON HIS SECRET!! UWU UWU ORZ *drops phone on foot* OOOWWW ORZ!!"
Ben furiously unfaints, his head pounding with a headache and missing half its cells, while his ears start bleeding.
"Ben!" Ennui yelps and shakes him, "Ben, are you OK? Are you feeling alright?"
"I feel viral."

View file

@ -0,0 +1,56 @@
---
title: "We're Missing Half ActivityPub's Potential!"
date: 2023-02-08T04:35:50Z
description: "Why client-to-server ActivityPub could be the future"
type: "post"
tags: ["activitypub", "protocols", "api", "decentralized-web", "federation", "ideas", "brainstorming"]
---
Recently, I joined a research project at MIT called [Graffiti](https://graffiti.garden), which conveniently has a broken website right now. Now before I explain the project, I'm going to talk about what I've increasingly come to see as the biggest technical problem with [ActivityPub](/posts/activitypub-eats-your-brain).
Unnecessarily building up suspense...
Wait for it...
ActivityPub servers conflate storage with processing.
Blah blah blah, what does that even mean? Basically, ActivityPub servers currently do way too many things. They handle storage, messages, and forwarding. Pretty reasonable. They can handle streaming and uploading videos, in the case of PeerTube. They can handle code hosting and collaboration, in the case of Forgejo. And on and on. Every server has its own implementation of storage and messaging.
And how do people access stuff on ActivityPub servers? They use the server's web client or a client app. And if they use a client app, that app is probably using a Mastodon API clone or something similar.
It doesn't have to be like this.
The ActivityPub protocol is actually two closely-related but distinct protocols: server-to-server (S2S) and client-to-server (C2S). Server-to-server is the boring old federation stuff you're used to: it describes how servers should deliver messages to other servers to propagate actions throughout the network. Now client-to-server is much spicier. It's ActivityPub's hidden superpower.
C2S offers a standardized way for clients or bots to interact with ActivityPub servers and data stored on that server. In an alternate universe, imagine if all your ActivityPub server did was store data and handle messaging and forwarding. Now let's say we want to implement something like PeerTube. We'd split it into two parts: a client app and a processing app. The client app can be either a website or a normal app, which people use to view videos, comment, like, whatever via C2S. The processing app can be a bot that handles stuff like transcoding videos. Crucially, the processing app can *also* use C2S. It's basically just a bot.
It gets better. Have you ever been frustrated about having a Mastodon account and a PeerTube account and a Forgejo account and a Lemmy account and so on? With this system, you just need one account, and all the processing apps operate on the data of your one account. Boom. Problem solved.
It's also compatible with the ActivityPub spec and existing implementations. Hooray!
This gives us an explosion of possibilites for what we can now do with ActivityPub. Now literally anyone can run an ActivityPub app. Just run the processing app on your computer, or even a phone. You don't need a domain name or web server or anything.
Except... this isn't all rainbows and sunshine. Separating storage and processing like this introduces latency and hurts performance. Another possibility is that we could make the ActivityPub server also handle running sandboxed user-uploaded processing apps, so that the processing apps can be physically close to the storage.
What about security? We don't want processing apps to have access to read and write all your data, so maybe a capabilities system would be useful here.
The upshot of all of this is that if you want to write an ActivityPub app, you no longer need to worry about handling `OrderedCollection`s or forwarding activities or any of that. You just need to write a C2S bot.
I told you earlier that I was going to explain that research project, but now you already know what it's about. The stuff above.
So you might be wondering, sure these ideas sound amazing, but do they actually work? And my honest answer is I don't know. I glossed over way to many technical details. The whole point of this post isn't to declare this is the panacea to all of ActivityPub's technical woes, but rather to get your brain spinning and thinking. And don't forget that by far the toughest challenges for the fediverse are not technical, but rather social, like moderation or [these challenges](https://discuss.coding.social/t/major-challenges-for-the-fediverse/67). We can't stop arguing over which decentralized web protocol is best while really it's the social problems that need solutions.
Bonus! Let's solve another notoriously difficult ActivityPub problem: nomadic identity. (Much of this is copied from this [braindump of decentralized protocol ideas](https://git.exozy.me/a/Kela))
The trick here is to use public keys as user identifiers. Instead of `billiam@centipete.exozy.me`, you're now `1a59726c1da670d0cbc20b97b7f32a3b6df1daef911384b0d4144c8b986ab68f` or something. Well, that kinda sucks.
Let's add a [petname](https://www.skyhunter.com/marcs/petnames/IntroPetNames.html) [system](https://spritelyproject.org/news/petname-systems.html) to the mix. This gives us human-readable names. Yay!
We just need to figure out which server a user belongs to based on their public key. In theory, you can use a DHT. In practice, you can probably use a DHT, but the details are kinda flaky here. Basically, when you want to find a user's server, you query a DHT formed by all servers. This returns a string containing their server's URL or some other address, signed with that user's private key to prevent tampering.
Now to migrate from one server to another, all your data is stored at one place, so you can simply copy it over. Easy as that. Perhaps you could even have your data replicated on multiple servers using primary-secondary replication, and then if you get injustly banned on your primary server, you can designate one of your secondary servers as your primary server.
This scheme has a few major problems. Obviously, if your private key leaks, you are screwed. Oops. Additionally, DHTs kinda suck. I know that because I tried writing one once and it kinda sucked and all the DHTs I've ever used have kinda sucked. So YMMV. Also, this scheme breaks any semblance of compatibility with the ActivityPub spec, so it's mostly just for fun and for exercising your brain.
Hope this was interesting! If you have any feedback or related ideas, just reply to [this post](https://social.exozy.me/@a/109827459013603069) Oh, and by the way, Hubzilla has probably solved these problems way better than anything I proposed, because Hubzilla is awesome and criminally underrated.

View file

@ -1,6 +1,7 @@
---
title: "The Myth of Bloat"
date: 2021-06-04
draft: true
type: "post"
tags: ["Linux", "Rant"]
---

View file

@ -0,0 +1,23 @@
---
title: "A New Charades Variant"
date: 2024-04-27T13:23:55-04:00
draft: true
description: "A variant of charades that Kevin, Alek, and I invented"
type: "post"
tags: ["game"]
---
A few months ago, we tried playing algorithms and math charades, which actually worked out pretty well (although the PCP theorem is pretty hard to act out). Yesterday we invented a new variant (maybe this already exists)?
1. Everyone chooses a secret word and writes it down.
2. We take turns, and on your turn, you write down another word on a slip of paper and pass it to a player of your choice. They have to act out the word on the paper while the remaining players guess it.
3. Your goal is for the guessers to say your secret word.
4. Once the guessers successfully guess the word on the paper, all other players get to guess once what your secret word is. If their guess is correct, then you lose a point.
5. If they don't guess correctly and one of the guessers said your secret word, then you win a point.
The incentives are to make the word you give to the other player very similar to your secret word, but if it's too obvious, then the other players will guess your secret word.

View file

@ -0,0 +1,31 @@
---
title: "Nexthouseball"
date: 2024-01-11T00:13:26-05:00
draft: true
description: "Pickleball plus squash plus a MIT dorm hallway"
type: "post"
tags: ["sports", "mit"]
---
Nexthouseball is a sport played in the hallway between the storage room and the west stairwell in the MIT Next House dorm basement that combines the best of pickleball and squash.
## Equipment
- 2 pickleball rackets (you may want to tape the top of the rackets to avoid scratches)
- 1 pickleball
- 1 Next House
## Court
Designate a line as the center line. Nexthouseball does not use a net. Then, count ten floor tiles away from the center on both sides for the end lines. This forms the boundaries of the court.
## Gameplay
- You must serve behind the end line.
- If the ball does not bounce once on your opponent's side, you lose the point.
- If the ball bounces twice on your side, you lose the point.
- The ball is allowed to hit the walls, but you lose the point if it hits the ceiling.
- You are not allowed to cross the center line.
- The person who lost the previous point serves.
- The court is slightly asymmetric, so before the match, one person decides which side they will be on while the other person serves first.

View file

@ -0,0 +1,14 @@
---
title: "An Origami Puzzle"
date: 2024-03-04T14:14:26-05:00
description: "An origami puzzle, or more accurately, three origami puzzles"
type: "post"
tags: ["puzzle", "math", "geometry", "origami"]
---
Let's say you have a square piece of paper (so yes, you should obtain a square piece of paper right now). It's pretty easy to fold the paper in half: bring one side of the square to the opposite side and make a crease down the middle of the paper. It's also easy to fold the paper into fourths: fold the side over so that it lines up with the crease you just made in the middle. You can repeat this process to divide a square into any power of two. But what about folding the paper into thirds? Obviously, you aren't allowed to use a ruler, but you can and should use your brain!
Here's your next task. Squares are great and all, but triangles are cool too. Try folding an equilateral triangle starting from a square piece of paper. In fact, origami is more powerful than traditional compass and straightedge constructions, and you can fold any regular n-gon out of a square piece of paper, but let's just keep it simple for now and fold a triangle.
And finally, if you managed to survive those previous tasks, try folding a 3-4-5 right triangle. Good luck! The solution will be posted next month.

View file

@ -0,0 +1,47 @@
---
title: "Petroleum"
date: 2023-04-03T14:41:18Z
draft: true
description: "An oddly consistent time travel story"
type: "post"
tags: ["story", "fiction", "humor"]
---
It's an important 21st-century skill to know how to respond in the event of finding a panda and giraffe committing tax fraud on your driveway.
Meet Pema, an ordinary overcaffeinated kawaii kemonomimi hyrax objectified Tibetan teenage anime schoolgirl. Apparently 1) There are driveways in Tibet 2) There is a panda and giraffe on her driveway frauding their way through their tax forms.
"I'm Mao Zedong II," the panda introduces himself, "A friendly genocidal Qinling panda. Call me II. And this is my buddy Aleq, a professional spammer giraffe with a penchant for portmanteaus."
"Penchanteaus," Aleq adds.
"Sounds cool, but why're y'all trespassing on my driveway?" Pema squeals.
"We're trying to figure out how to report capital gains from time traveling on our tax returns," II explains.
"WAIT, TIME TRAVEL???" Pema interjects.
Aleq replies, "Yeah, we mugged a Sinopec employee last week and discovered secret docs about Sinopec's time machine that they're using to travel back to 66,000,000 BCE and bury more dinos. Sinosaurs. And you helped us storm the Sinopec lab and steal the time machine! The tichine! And where else to park our tichine than your driveway?"
"Huh what? What the f? I never stole a time machine or tichine or whatever with you two weirdos."
This puzzles II and Aleq until suddenly, II sreams, "AHA! YOUR FUTURE SELF DID! You're DESTINED to help us!" And with that, II shoves Pema into the time machine, which whisks her back to last week. The Sinopec time machine heist was actually super boring, so we'll just skip it. Pema then travels forward a week and discovers her driveway is now a smoldering mess, with the main attraction being Mao Zedong II's corpse. Aleq is standing horrified, his face contorted with fear.
"OMG what happened???" Pema asks.
"Maotroleum." Aleq replies, "His last words were "I'll get you, even if you fossilize me!"" Mao had been murdered by that Sinopec employee from earlier and would now partake in a totally humane experiment of having his remains sent to 66,000,000 BCE and turned into petroleum!
"We have to go back in time to save II!" Pema says, determined.
Aleq shook his neck, "The past is fixed. We can't change it, only be changed by it."
"Surely there's something we can do?"
"Well, how about crying?"
"Wait... I know... we have to go back to the Sinopec lab. Aleq, do you have a flamethrower?"
The two return to the lab and burn the whole thing to the ground, igniting all the experimentally-produced petroleum in sight.
"Hey Aleq," Pema asks, "Do you realize what's in that petroleum? I never knew Mao Zedong II's dead body could be so useful!"

View file

@ -0,0 +1,97 @@
---
title: "Plasma 6 Fingerprint Bug"
date: 2024-03-19T20:33:11-04:00
description: "Figuring out why the KDE Plasma 6 lockscreen is sometimes missing fingerprint login"
type: "post"
tags: ["plasma", "systemd", "linux", "bug"]
---
KDE released Plasma 6 a few weeks ago and it's extremely awesome and also quite buggy. One of the most annoying bugs has been that the lockscreen is sometimes missing the fingerprint login option after resuming from sleep, so I have to type in my password instead. Of course there's the big question about the security of fingerprint login, but I think it's more likely for someone to shoulder surf me rather than knock me unconscious and tap my finger to the sensor. Also, fingerprint login is more convenient. Anyways, I'm just going to ignore that question and focus on this bug instead.
While debugging this, the first main obstacle I ran into is that the KDE's PAM configuration doesn't reset `pam_faillock` after a successful fingerprint login, which has been reported [here](https://bugs.kde.org/show_bug.cgi?id=483130). Basically, whenever you log in with your fingerprint, it gets counted as a failed login anyways and after three tries, you get locked out! The fix is also included in that bug report and just requires adding this to the bottom of the `auth` section in `/etc/pam.d/kde-fingerprint`:
```
auth required pam_faillock.so authsucc
```
Once I got that out of the way, I enabled `debug=on` for `pam_fprintd` (a PAM module to use the fingerprint reader for authentication) to see debug messages for it in the system journal. After triggering the bug and checking the journal with `journalctl -xe`, I found a suspicious line:
```
Mar 19 20:27:53 ThinkPad-X1-Yoga-Gen-6 kscreenlocker_greet[14561]: pam_fprintd(kde-fingerprint:auth): Using device (null) (out of 0 devices)
```
Whoa! There's the problem! `pam_fprintd` is not detecting my laptop fingerprint reader at all. Furthermore, this line is located very early in the wake-up process, when some USB devices haven't been initialized yet!
`lsusb` says that my fingerprint reader has ID `06cb:00fc`, and sure enough, the lines for that are located after the `pam_fprintd` line:
```
Mar 19 20:27:53 ThinkPad-X1-Yoga-Gen-6 kernel: usb 3-3: new full-speed USB device number 117 using xhci_hcd
Mar 19 20:27:53 ThinkPad-X1-Yoga-Gen-6 kernel: usb 3-3: New USB device found, idVendor=06cb, idProduct=00fc, bcdDevice= 0.00
Mar 19 20:27:53 ThinkPad-X1-Yoga-Gen-6 kernel: usb 3-3: New USB device strings: Mfr=0, Product=0, SerialNumber=1
Mar 19 20:27:53 ThinkPad-X1-Yoga-Gen-6 kernel: usb 3-3: SerialNumber: f88de24e63f0
```
This is progress. `pam_fprintd` starts the systemd service `fprintd.service`, so I just need to make this service start after the fingerprint device is initialized. Fortunately, this is doable with systemd but a bit complicated. First, create a udev rule for the device in `/etc/udev/rules.d/69-fingerprint.rules`:
```
ATTRS{idVendor}=="06cb", ATTRS{idProduct}=="00fc", SYMLINK="fingerprint", TAG+="systemd"
```
Next, reload udev rules with `sudo udevadm control --reload-rules && sudo udevadm trigger`. Now create an override file for `fprintd.service` using `sudo systemctl edit fprintd.service` and paste in this stuff:
```
[Unit]
After=suspend.target dev-fingerprint.device
Requires=dev-fingerprint.device
```
The `suspend.target` is important because the `dev-fingerprint.device` seems to initially be active right after the wake-up starts, but then gets deactivated and reactivated during wake-up. Thus, we have to wait until after the wake-up finishes, then wait for `dev-fingerprint.device` to be active.
So, to recap, the bug actually has isn't KDE Plasma's fault. I guess it's an `fprintd` problem since maybe it should wait a bit until the USB devices are all initialized? I'm not sure. The only reason I ran into this bug is because previously, Plasma required pressing enter first to show the fingerprint login prompt, but in Plasma 6 is immediately shows the fingerprint login prompt. This causes a race condition with USB device initialization, so the bug doesn't always happen if the USB devices win the race.
Another potential problem is that `fprintd` waits around 30 seconds after a successful login before quitting, so sleeping and waking up and sleeping and waking up can cause the bug to reappear during the second wake-up, but I don't think I'd ever run into this corner case except while debugging this bug. When debugging, I had to manually run `sudo killall fprintd` between sleep-wake up tests.
It turns out the 30 second timeout is [hardcoded in the source code](https://gitlab.freedesktop.org/libfprint/fprintd/-/blob/master/src/fprintd.h?ref_type=heads#L29), so I changed it to 1 and recompiled fprintd, which fixed this problem. (Sidenote: the [fprintd README](https://gitlab.freedesktop.org/libfprint/fprintd/-/blob/master/README?ref_type=heads) says "Might eat your kangaroo") I might try contributing this fix to fprintd, but maybe they have a reason for 30 as the default. Also, fprintd doesn't seem actively maintained anymore.
Maybe there's a better way to solve this. If you know of a better solution, please let me know! It's definitely a bit upsetting that I need to mess with PAM config files, udev rules, systemd override files, and recompile fprintd to get my fingerprint reader to work properly, but I guess that's the struggle of Linux sometimes. I wish Lenovo could provide better support for Linux on my laptop model, since they do sell a preinstalled Ubuntu version of that model.
Edit: I found a slightly better solution. Linux has an obscure feature called [USB persist](https://www.kernel.org/doc/html/latest/driver-api/usb/persist.html) that reuses the data structures for a USB device instead of rebuilding it after a suspend. I tried enabling this for my fingerprint reader and it works! Now my reader doesn't even need to be initialized during the wake-up process, which avoids the problem from earlier. To enable persist, I changed the udev rule to this:
```
ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ATTRS{idVendor}=="06cb", ATTRS{idProduct}=="00fc", ATTR{power/persist}="1", RUN="/usr/bin/chmod 444 %S%p/../power/persist"
```
I noticed that this kept on getting disabled for some reason after each wake-up, so I changed the file to have permissions 444 to stop that. With this solution, I no longer need the systemd override anymore, but still need to recompile fprintd which is annoying.
Edit 2: I was trying to investigate why I still needed to recompile fprintd. The unpatched version gives this error if I sleep then resume while `fprintd` is still running in the background:
```
Mar 21 19:27:44 ThinkPad-X1-Yoga-Gen-6 kscreenlocker_greet[16753]: pam_fprintd(kde-fingerprint:auth): debug on
Mar 21 19:27:44 ThinkPad-X1-Yoga-Gen-6 kscreenlocker_greet[16753]: pam_fprintd(kde-fingerprint:auth): debug on
Mar 21 19:27:44 ThinkPad-X1-Yoga-Gen-6 kscreenlocker_greet[16753]: pam_fprintd(kde-fingerprint:auth): /net/reactivated/Fprint/Device/0 prints registered: 2
Mar 21 19:27:44 ThinkPad-X1-Yoga-Gen-6 kscreenlocker_greet[16753]: pam_fprintd(kde-fingerprint:auth): Using device /net/reactivated/Fprint/Device/0 (out of 1 devices)
Mar 21 19:27:44 ThinkPad-X1-Yoga-Gen-6 kscreenlocker_greet[16753]: pam_fprintd(kde-fingerprint:auth): failed to claim device Open failed with error: The device is still busy with another operation, please try again later.
```
Also, it seems like fprintd is the one trying to [disable USB persist](https://gitlab.freedesktop.org/libfprint/fprintd/-/blob/master/NEWS#L36) for some reason. It's also possible that maybe my fingerprint reader just works perfectly with S2Idle sleep instead of S3, but switching to a battery-draining sleep state seems like a bad tradeoff. If anyone has further insights into these problems, I'd love to hear it!
Edit 3: I finally found a nice solution to all my problems! No more udev rules, no more compiling fprintd. Just make a systemd service file at `/etc/systemd/system/fingerprint.service` containing this:
```
[Unit]
Description=Kill fprintd and enable USB persist before sleep
Before=sleep.target
[Service]
ExecStart=/usr/bin/sh -c "killall fprintd; echo 1 > /sys/bus/usb/devices/3-3/power/persist"
[Install]
WantedBy=sleep.target
```
Now run `sudo systemctl enable fingerprint` and voilà, all problems fixed! Awesome!
It might seem like I pulled that systemd service out of a magic hat, but the basic idea is to make sure fprintd isn't running during the sleep and to enable USB persist. I originally tried using an obscure systemd feature called systemd-sleep, but it wouldn't work unless I placed the script in `/usr/lib/systemd/system-sleep`, not `/etc/systemd/system-sleep`. I saw someone online suggest [simply writing a systemd service](https://github.com/systemd/systemd/issues/4927#issuecomment-270282849) instead. Anyways, I hope you enjoyed this tour through a bunch of obscure Linux and systemd features. Well, I didn't really enjoy it honestly. The documentation was all bad and searching for stuff like "run systemd service before sleep" gets barely any relevant results.
Alright, so if you managed to reach the end of this post and understood everything, congratulations! You deserve a bowl of [Biángbiáng noodles](https://functional.cafe/@loke/112120713973565564)!

View file

@ -0,0 +1,60 @@
---
title: "PulseAudioDB"
date: 2024-02-25T16:42:10-05:00
description: "Anything can be a key-value database if you misuse it well enough!"
type: "post"
tags: ["database", "audio", "satire"]
---
[A friend of mine](https://www.1a-insec.net) shared a surprising fact: The Linux kernel has a built-in key-value database!
```
keyctl add user key value @u
keyctl list @u
keyctl read <ID>
```
Actually, `keyctl` is intended for managing the kernel keyring, not as a general purpose key-value database. That made me wonder: What other key-value databases are hiding right in plain sight? What else could we use as a database? Ideally, it should be something that's fast, simple-to-use, and preinstalled in your favorite Linux distro.
Oh, I know! PulseAudio!
Yeah, we're going to turn a sound server into a database now. After all, who's stopping us?
The idea is simple. Each key-value pair will be stored as its own sink device. The key will be the name of the sink, and the value will be the volume of the sink. Due to the brilliance of the PulseAudio developers, volumes in PulseAudio don't range between 0 to 100 but rather 0 to 2^31-1 in case you ever want to blast out your ears or your speakers. Seriously, I don't recommend turning up the volume to 2147483647. It's not fun. Anyways, our PulseAudioDB will only be able to store integer keys, which honestly is good enough.
The implementation is also super straightforward. Here's some Python code, but it's trivial to port this to any language.
```python
class PulseAudioDB:
def __getitem__(self, key):
try:
return int(subprocess.check_output(['pactl', 'get-sink-volume', key]).split()[2])
except:
raise KeyError
def __setitem__(self, key, value):
run = lambda x: subprocess.run(x, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if run(['pactl', 'set-sink-volume', key, str(value)]).returncode:
# Key doesn't exist yet
run(['pactl', 'load-module', 'module-null-sink', 'channels=1', 'sink_name=' + key])
run(['pactl', 'set-sink-volume', key, str(value)])
```
Now let's try our amazing database!
```python
padb = PulseAudioDB()
N = 200
for i in range(N):
padb['a' + str(i)] = i
ans = 0
for i in range(N):
ans += padb['a' + str(i)]
print(ans)
```
This code is blazingly fast 🚀, prints the correct answer of 19900, and only takes 15.14 seconds to run for an amazing 200 reads and 200 writes. Seriously, I can't imagine myself reading or writing something that fast! To delete all the sinks and reset the database, just run `pactl unload-module module-null-sink`. PulseAudioDB is concurrent by design, so any number of processes can use it at the same time. The key-value pairs will also remain in the database if your process ends or crashes (although the database won't survive reboots). And because PulseAudio has network transparency, PulseAudioDB might even work over a network!
PulseAudio doesn't seem to support more than 250 sinks, but who even has that much data? 200 key-value pairs should be enough for anyone, just like how 640K of RAM ought to be enough for anyone. If you're ever in need of a fast, simple database, look no further than PulseAudio!
By the way, if you enjoyed this post, you'll also like [MangoDB](https://github.com/dcramer/mangodb).

View file

@ -7,9 +7,9 @@ tags: ["website", "web"]
---
My [old website](https://web.archive.org/web/20210813044159/https://ta180m.github.io/) [sucked](/posts/web-sucks). Like, for real. It was a bit of hard-written HTML plus a Jekyll blog, and it was a huge pain to update and maintain. GitHub kept randomly emailing me about various security vulnerabilities in some Ruby dependency of Jekyll, and hard-written HTML can only get you so far before you rage-quit.
My [old website](https://web.archive.org/web/20210813044159/https://ta180m.github.io/) sucked. Like, for real. It was a bit of hard-written HTML plus a Jekyll blog, and it was a huge pain to update and maintain. GitHub kept randomly emailing me about various security vulnerabilities in some Ruby dependency of Jekyll, and hard-written HTML can only get you so far before you rage-quit.
So what now? Well, I did write a different site using the Hugo static site generator, [howtuwu](https://exozy.me/howtuwu/), and it turned out really nice. Hugo written in Go (of course) and compiled to a single binary, so no more worrying about Ruby dependencies! And writing in Markdown is a whole different level than HTML and actually kind of fun. No one ever said writing HTML is fun. So, why not rewrite my personal website in Hugo too?
So what now? Well, I did write a different site using the Hugo static site generator, howtuwu, and it turned out really nice. Hugo written in Go (of course) and compiled to a single binary, so no more worrying about Ruby dependencies! And writing in Markdown is a whole different level than HTML and actually kind of fun. No one ever said writing HTML is fun. So, why not rewrite my personal website in Hugo too?
I started by searching for a [Hugo theme](https://themes.gohugo.io/). Almost by accident, I discovered the [Gokarna theme](https://themes.gohugo.io/themes/gokarna/), and I have to say, I absolutely love it. It has everything that I need: icons for my various accounts, tags that actually work, an RSS feed, and dark mode. With my [personal Gokarna fork](https://github.com/Ta180m/gokarna), it's perfect. I even managed to sneak in this from my old blog:

View file

@ -0,0 +1,15 @@
---
title: "Returning to Forge Federation Development"
date: 2023-12-26T17:46:02Z
draft: true
description: "Finally returning to forge federation development after a one year hiatus"
type: "post"
tags: ["forge-federation", "activitypub", "decentralization"]
---
It's been a year since the last time I spent a huge chunk of time working on forge federation, so it's great to be back. The reason for this long gap is mostly due to college. It's not that I didn't have free time, but because forge federation is a lot of tedious work so it wasn't something I was super excited about doing after exhausting my brainpower on homework. I ended up spending a lot of time playing vidoe games or writing stories, but I guess I shouldn't be too hard on myself either. If I had spent 100% of my time doing homework and working on forge federation, I would probably be really burnt-out by now.
The unfortunate thing though was this summer, which would have been the perfect time to devote two months to forge federation development, but sadly, I ended up in a terrible computer vision research project that I should have just quit the first week.
Sometimes, life just gets in the way of stuff.

View file

@ -4,7 +4,7 @@ date: 2023-01-04T18:01:29Z
draft: true
description: "A poem about my experiences as an MIT student"
type: "post"
tags: ["mit", "life", "college", "fun"]
tags: ["mit", "life", "college"]
---

View file

@ -1,6 +1,7 @@
---
title: "The Scary S Words"
date: 2021-04-27
draft: true
type: "post"
tags: ["Linux"]
---

View file

@ -1,6 +1,7 @@
---
title: "Self-hosting is Hard!"
date: 2021-04-07
draft: true
type: "post"
tags: ["Linux"]
---

View file

@ -0,0 +1,32 @@
---
title: "Short Story 2"
date: 2024-03-05T22:18:21-05:00
description: "A parody of Alek Westover's recent short story"
type: "post"
tags: ["story", "fiction", "parody", "constrained-writing", "short-story-series"]
---
*My friend Alek recently published a [short story](https://awestover.github.io/skyspace/posts/misc/02-25-24.html) which you should totally read, so I wrote a parody of it that only uses words from the original story, and each word appears at most the same number of times in this story as in the original. And now there are more stories in the [series](/tags/short-story-series/)!*
Zhou enjoyed the peaceful process of being disappointed that he was working at 7-11 instead of being a chef somewhere. The occasional car sped by outside, but the really persistent noise was his gross boss taking the year off. "Hey Zhou, what's cooking?" Hu came over. "Zhou Zhou Zhou Zhou Zhou Zhou Zhou Zhou you down for some games tonight?" Some days Zhou would go. But today was really important, it was the day he reviewed his calendar. "Sorry Hu, gotta make fancy instant noodles (IN)". "Ah, too bad, I got some really good ones!". "Hu, we literally played video games all night." "Ah good point, well see you tomorrow!" Hu walked out the door. That was the only tasty food Zhou was known to make.
He took a flashcard from his pocket. He happily checked "close up shop" off the list, and reviewed the remaining items: "Dinner, review calendar, sleep".
When Zhou arrived home he quickly threw some eggs and tomatoes and IN in a pan and idly tended them. In a bit he sat down at his desk with a slightly burned dinner and got out his calendar. He added this day's cards to a large shoe-box filled with similar items. He was a little dejected to see how most only had IN written on them. He flipped to the next month and was surprised to see a short note cramped on the page, covering the boxes for the first few days of the month.
"Dear Zhou,
I hope you've enjoyed the calendar but I have not been eating well! By the time you find this it's probably been quite some time since we last met. This is a reminder about our plan: to meet on December 4th, 5pm at the top of your flashcard mountain. I'm excited for your warm IN again!
Ever your friend,
Lin"
Zhou was shocked. He remembered 5 years ago when Lin left for graduate school, he said they must meet up again at Zhou's pretty flashcard mountain. In the first year Lin was away they had exchanged letters frequently, and had discussed the plan a few times. Then both their lives had gotten busy and the letters had been less frequent. With regret Zhou realized that he hadn't crossed Lin for more than half a weekend. He stared at the letter. Would Lin come? Zhou had never found Lin to break a promise before. Zhou fondly remembered time spent with him. His favorite times were those spent hiking and simultaneously cooking with Lin. Lin would always tell him interesting math problems that he was working on and inquire about IN. Zhou decided his friend would go and meet him.
He checked the calendar. There were 3 days until the appointed day, a Saturday. He thought of his agenda for tomorrow: Obtain IN stuff, videogame with Hu, ask boss to take the weekend off from work too. Then, tired but excited, Zhou went to bed.
Five days later at 7am Zhou anxiously waited outside his house by Hu's car. Should I call Hu? he wondered. Hu's car was great and was on time, but not Hu. "Ah shoot, if Hu is not back by night I'll try and find someone to rescue you or recover your dead body." Zhou had made so much IN that it started to snow IN, graceful flakes falling and thinly coating the road. At that moment Zhou spotted a cop called Wu behind him, which screamed. Zhou belatedly stared, but he signaled for Zhou to stop. Zhou reluctantly did so.
"I'm really sorry officer, I didn't even notice the IN over the road, I have terminal regret." "Not asking for leniency? Lot's of young people do that." "No I was in the wrong, I'll pay." "Well can't argue with that" the cop chuckled and handed him the ticket. "Now do laundry on the road, slowly and safely". "Yes, sir".
Zhou scrambled and painstakingly pulled the IN off the ground. How was he even supposed to do laundry? Constantly checking the clock as it sped towards 7:30, he meticulously dumped the IN in the trash. What would he say to Lin? Would Lin think he was grueling? Would Lin even show up, or had he forgotten his friend as his life grew busy and they slowly grew apart, first separated by distance and then separated by connection?
Hours later Lin finally arrived. The IN snow had really picked up now, but luckily Zhou's room was nearby. The snow was inside too. As they ran the wind bit at their arms. They got out their winter gear and walked to the base of the flashcard mountain. Lin stared up the mountain. "Zhou...," Lin said over the wind, "this is a freaking IN blizzard! I know you're really eager, and we are climbing the mountain! We can play a round of Ascent VI with the mountain." Zhou stared up the mountain as well, tempted, looking at his friend. He's crazy. Zhou thought. "You're not right" Zhou whispered, and turned around to head back. Dejected, he took off his gear. When he took off his jacket his daily flashcard fell to the floor. Zhou reached down, crumpled it, and attempted to throw it to the trash can. He missed by a large margin, and Lin laughed. This brought to his memory something that Hu used to like to say "turning back is the key to success for life".
If Zhou did at least try to go to the mountain top, he'd be crazy. Zhou didn't want to be crazy. He already had a ticket from the cop about the IN. "Sorry Lin, I just realized something." "What?" "Life's more exciting when you give up" Zhou called, voice muffled and adamant as he gladly settled into a nap.
And from that day onwards Zhou was a little bit better at achieving the items on his flashcards.

View file

@ -0,0 +1,31 @@
---
title: "Short Story 4"
date: 2024-03-28T12:00:16-05:00
description: "The sequel to Short Story 2"
type: "post"
tags: ["story", "constrained-writing", "fiction", "short-story-series"]
---
*This story is narratively a sequel to [Short Story 2](/posts/short-story-2/). It's the fourth installment in the [Short Story series](/tags/short-story-series/) and only uses words from Kevin's [Short Story 3](/posts/guest-post-short-story-3/), counting multiplicity.*
Zhou was looking around, surprised. His nap is a year large! But, Zhou's tired and attempted to sleep again. Dead, burned, fancy instant noodles (IN) covering the room! From when? Zhou screamed and scrambled to 7-11.
Zhou quickly reached 7-11, in flashcard review gear. He spent time painstakingly checking important round 7-11 boxes of IN, then sat down, and meticulously sped over the cards he pulled from his flashcard mountain on the shoebox. Great. They only say IN.
A short time later, the 7-11 boss called "The" arrived! Shoot! Zhou was shocked. Zhou had known "The" to break a promise before, and "The" would frequently, happily give Zhou the grueling work. "The" never remembered to show up to 7-11. Zhou ran to the back, settled down, and decided to idly do math problems for a month.
Finally, Zhou belatedly turned towards "The", threw a food blizzard, and "The" crumpled with lots of noise. Zhou walked away.
But then, "The" slowly signaled, muffled, "Wu- hu, exciting! Zhou, some crazy dumped a mountain of IN so I can't see! I enjoyed you taking down that crazy safely! But am I terminal? I'm too young!"
Zhou was freaking out: "The" is Lin! Zhou laughed anxiously, "Luckily, you're probably gotta recover in little time." Zhou reluctantly started eating the IN thinly coating the head of Lin.
"Yes, rescue! I can see now!" Lin called gladly, "You're literally always a favorite! I'll make a road to life success for you!"
Zhou slowly whispered with his flashcard voice, "But Lin, I was the falling IN, sorry for that."
Lin chuckled, "No, sorry that I didn't come to 7-11 for a large time. Want to play a flashcard videogame at Hu's house this night?"
And from that day onwards Zhou was a little bit better at achieving the items on his flashcards.

View file

@ -3,7 +3,7 @@ title: "Sketchy Websites Save the Day"
date: 2022-09-07T23:04:12-05:00
description: "Salvaging an old HP LaserJet printer by downloading sketchy files from sketchy websites"
type: "post"
tags: ["fun", "printer", "sketchy", "firmware", "security"]
tags: ["printer", "sketchy", "firmware", "security"]
---

View file

@ -0,0 +1,30 @@
---
title: "A Solar Eclipse"
date: 2024-04-08T20:41:50-04:00
description: "Another post reviewing something and this time I promise I will actually review it"
type: "post"
tags: ["travel", "space", "eclipse"]
---
They say that a total solar eclipse is a once-in-a-lifetime opportunity. Well more accurately, it's a twice-in-a-lifetime opportunity. At least twice.
So as you may know, there was a total solar eclipse today across the eastern US, but I almost didn't go see it. I've already seen a total solar eclipse before in 2017, and while eclipses are super cool and amazing, I was a bit discouraged by the three-hour drive from Boston to the path of totality. I also don't have a car, so I'd have to find someone else to tag along with. But all the recent xkcd comics have been about eclipses (other than the April Fools' comic), so I knew I probably should go see it.
Fortunately, [Alek](https://awestover.github.io/skyspace/) said he was going to go see it, so I went with him and some other friends. The drive to the nearest point in the path of totality, in Montpelier, Vermont, turned out to not just be three hours, but five hours due to traffic and all the other eclipse aficionados. I saw several custom license plates like CHESS, PHOTON, WOZNIAK, and BUSTED which should give you an idea of the kinds of people who drive hours to see a three-minute astronomical phenomena.
[xkcd 2914](https://xkcd.com/2914/) says "A partial eclipse is like a cool sunset. A total eclipse is like someone broke the sky." The first part is probably wrong. The moon started covering the sun an hour before totality, but I didn't notice much change other than from looking at the sun with eclipse glasses on and noticing it had a bite taken out of it. It just darkened a little bit I guess. A few minutes before totality, the cool stuff finally started happening, such as the temperature dropping, the birds became restless and stopped chirping, and it actually started feeling like a fast sunset. Then, Zumba happened.
Yes, Zumba, not totality. So a few months ago, Alek tried to recruit me to join a Zumba class, and I wasn't interested at all but decided just to go once. Well, it turned out to be a lot of fun, probably because Alek and some other friends were there. Doing Zumba with strangers would be kind of awkward. Anyways, one of the Zumba songs was, well, it took me a long time to find the right song, since there are a lot of songs with names similar to "Sun Goes Down" and some of the results were pretty weird songs. It's [this one](https://www.youtube.com/watch?v=4i4EjGKwEVw). I guess the sun wasn't really going down since it was just being blocked by the moon, but we tried Zumba-ing on a riverbank with lots of branches on the ground, so it wasn't too successful but still lots of fun.
Then, it was silent and totality actually happened, and then a bunch of people cheered annoyingly. And yeah, basically someone broke the sky. Imagine it's dusk, but there's no sunset and toasty colors. It just looks like a sterile sky, but right in the middle there's a black circle with a ring of white light around it. It's like straight out of a sci-fi book or something. Literally, it's this bizarre black orb floating in the dark sky. I can't really describe the eclipse or give it full justice--it's something you have to experience yourself. Sadly, I don't have any good pictures since eclipses are hard to photograph with phone cameras, although I did get a photo with Venus in it though (it's the white dot below and to the right of the sun). This was during totality, so it looks nothing like this but my phone camera is just too weak.
![A photograph during totality but the sun just looks normal](/img/eclipse.webp)
I'm a bit disappointed that I didn't see [shadow bands](https://en.wikipedia.org/wiki/Shadow_bands) unlike in 2017. It was also cloudy just as [xkcd 2915](https://xkcd.com/2915/) predicted, but Randall Munroe is also from Boston so I'm guessing we probably went to similar places to see the eclipse.
After totality, the same stuff happened but in reverse, and one of my friends in another state said online that he heard a rooster crowing after the eclipse.
Interesting sidenote: this [article](https://www.quantamagazine.org/how-the-ancient-art-of-eclipse-prediction-became-an-exact-science-20240405/) about the history of eclipse prediction (solar eclipses, not LLM assistance in a certain Java IDE).
Still, it was a really cool experience, and I'm looking forward to the next one! 2044, maybe?

View file

@ -0,0 +1,150 @@
---
title: "Spelling Reform is Hard, NP-Hard"
date: 2023-11-07T15:54:08Z
description: "How to prove problems are NP-hard and why you should care"
type: "post"
tags: ["complexity theory", "cs", "algorithms"]
---
Spelling sucks. "Though" rhymes with "go". "Thought" rhymes with "got". "Through" rhymes with... "true", "grew", "who", "lieu", "you", "flu", "moo", "shoe", "coup", "queue", and "view". Enough examples, let's fix this madness!
Here's a hypothetical procedure to reform English spelling: for every word, it has some IPA pronunciation. For instance, "through" is pronounced "θɹu". Now let's replace every letter in the IPA pronunciations with strings of one or more letters, such as mapping all occurrences of "θ" to "th", "ɹ" to "r" and "u" to "oo". Of course, we don't want the new phonetics-based spellings to get too crazy, so we should minimize the total number of changes between the old and new spellings. Let's define the "amount of change" between two spellings as the minimum number of insertions, deletions, and single-character replacements, which is technically called the **Levenshtein edit distance**. In our little example, the edit distance between "through" and "throo" is 3, because we have to replace the "u" with an "o" and delete the last two characters. Lastly, we should make this sum of edit distances weighted by the frequency of each word in typical English, since people care a lot more if the spelling of "through" changes versus the spelling of "queue".
Let's do another example to understand the problem. Imagine some random farm with perfectly cylindrical Belted Galloway cows (AKA oreo cows). The cows have a language with exactly three words:
```
through θɹu 0.01
moo mu 0.98
cow kaʊ 0.01
```
The first word of each input line is the old spelling, the second word is the IPA pronunciation, and the third is the word's frequency. Anyways, just like me, the cows think English spelling sucks, so they're embarking on a spelling reform journey. Since the word "moo" is very common, tells means we really want to keep the new spelling as close as possible to the old spelling. Keeping that in mind, here's the solution:
```
θ th
ɹ r
u oo
m m
k c
a o
ʊ w
```
The new spellings are "throo", "moo", and "cow". Since "moo" and "cow" are unchanged, the total edit distance sum is 3*0.01 which is 0.03. Hooray!
Note that in this problem, we don't need the pronunciations to be in IPA. The old spelling and pronunciation are allowed to be arbitrary strings.
## My name is Hard, NP-Hard
If you try solving some wackier instances of this problem (inputs for this problem), you'll soon realize that this spelling reform problem seems hard. For the cow example, the solution was pretty obvious. But if the old spellings and pronunciations aren't closely related, then we might have to brute-force through a ton of combinations. Also, mapping a phonetic letter to some letter to keep the spelling the same for one word can mess up a whole bunch of other words. And edit distance isn't the nicest thing to work with either.
But how hard really is this problem? You might have heard of NP-hard before, but what does that even mean? It's actually pretty simple, but first, we need to do a few definitions. They'll be nice, easy definitions, I promise. This is just to ensure that our sentences don't devolve into vague nonsense like "you make the thing into the other thing".
A **decision problem** is a problem which has a yes or no answer. A simple example would be the problem of determining whether a string has an "a" in it or not. Our spelling reform problem is sadly not a decision problem, but it can be turned into one easily by asking if this language has a spelling reform that makes the total edit distance sum less than some value K. Note that this decision version of spelling reform is easier, since if we can solve the original minimization problem, we can obviously solve the decision problem, but not vice versa. But as we'll see soon, even the decision problem is hard.
**NP** is the class of all decision problems that can be checked (not solved!) in polynomial time. (NP technically stands for nondeterministic polynomial time, but nondeterminism is weirdly magical so we won't delve into it. Also, I'm just going to assume you know what polynomial time is, since otherwise you're about to have a rough time reading onward.) For example, our spelling reform decision problem is in NP, since given the actual assignments of the pronunciation letters to letters in the new spelling, we can construct all the new spellings, compute the edit distances, and then check if the edit distance sum is less than K or not. This can all be done efficiently in polynomial time. However, we don't know if there is an efficient way to actually solve the problem from scratch. You can easily verify a solution to some instance of an NP problem, but finding the solution itself doesn't necessarily have to be easy.
Yay, we're finally ready to meet our new best friend, NP-hardness. A problem is **NP-hard** if it's harder than all problems in NP, or if it's one of the hardest problems in NP (in this case it's called NP-complete). Basically, if we have a magic black box (technically called an oracle) that can magically solve our NP-hard problem, then we can devise polynomial time algorithms that use this black box to solve any problem in NP.
## Reductions
So is our spelling reform decision problem really that hard? Can we really solve all NP problems using spelling reform?
The answer is yes, and we will prove this by showing our problem is even harder than an NP-hard problem called 3SAT. Because if our problem is even harder than an NP-hard problem, it must be really, really hard, right? Well, time for more fun definitions!
**SAT** (short for satisfiability) is a problem where we're given a boolean expression and we want to know if there's some way to set the variables to make the expression true or not. For instance, say we're given `(!a || (b && c)) && (!b || c || !d)`. The answer to this particular instance is yes, because we can set all the variables to false which makes the whole thing true. **3SAT** is a variant where the boolean expression must be the `&&` of a bunch of **clauses**. Each clause consists of the `||` of at most 3 different variables, which can be possibly negated. The previous example is not in this format so it wouldn't be a valid 3SAT expression, but something like `(!a || b) && (!b || c || !d)` would be fair game. SAT and 3SAT are both NP-hard, which we won't prove (the proof for SAT is really cool though).
We will now do a **reduction** from 3SAT to our spelling problem. This means that we will create a polynomial time procedure where given a 3SAT instance, we will convert it to a spelling instance. Then, we will run some magic spelling problem solver black box thingy which magically gives us a solution to the spelling instance. Then, we'll convert that solution back into a 3SAT solution. We're basically showing that any 3SAT instance can be turned into an equivalent spelling instance, so 3SAT is kind of a subset of the spelling problem, so our problem must be even harder!
## Constructing the reduction
Alright, so where to start? Is our spelling problem even that 3SAT-y? Let's try to convert a specific 3SAT instance `(!a || b) && (!b || c || !d)` into a spelling reform problem.
Let's start with boolean variables. Naturally, we should make the phonetic letters the boolean variables, since the phonetic letters are the things we're choosing assignments for. For example, the variables `a, b, c, d` in the 3SAT instance become the phonetic letters `a, b, c, d`, and we can choose to map each letter to the uppercase or lowercase version to "set that variable to true or false". The uppercase version will represent false and the lowercase version will represent true. However, the spelling reform solution could be naughty and map a phonetic letter to some other random letter or to a longer string of letters, which would be bad. Fortunately, we can force the solution to do our intended behavior by adding some heavily weighted words:
```
a a 10000
A a 10000
b b 10000
B b 10000
c c 10000
C c 10000
d d 10000
D d 10000
```
If the solution maps each phonetic letter to the uppercase or lowercase version, then the edit distance sum will be 40000. Otherwise, if they try something else, their sum will be much worse.
For the clauses, we would like a clause to be true if any one of the three variables inside is true since that's how `||` works, so we'd like a word to have a low edit distance if the letters of it are "true". I thought about this for a long time last night while trying to fall asleep and here's what I came up with:
```
##Ab## ba 1
##BcD## dcb 1
```
For the old spellings, we'll write down the 3SAT clauses as words, converting negated variables to uppercase letters, and then pad with `##` on both sides. For the phonetic pronunciations, we'll write the variables in lowercase *in reverse*. What the heck is going on?
Imagine a simple clause `a || b || c`. This corresponds to:
```
##abc## cba 1
```
If the solution sets all the variables to false, then we get the old and new spellings:
```
##abc##
CBA
```
If `a` is set to true:
```
##abc##
CBa
```
If `b` is set to true:
```
##abc##
CbA
```
If both `a` and `b` are set to true:
```
##abc##
Cba
```
Magic! Well, it's not really magic after you work through all the cases. Basically, if none of the variables are true, then the edit distances is 7, and if at least one is true, then it drops down to 6. The reversed order of the letters in the phonetic pronunciation is to ensure that setting multiple variables to true does not make the edit distance even smaller. If the order wasn't reversed, then that last example would look like this:
```
##abc##
abC
```
The padding on both sides is to keep the edit distance at 7 normally. If we didn't have it, then setting all the variables to false would cause the edit distance to be 3:
```
abc
CBA
```
Overall, we basically have a bunch of heavily weighted words to force our choices into only choosing uppercase or lowercase for the variables, and then a clever clause construction that has two possible edit distances, depending on whether at least one variable is true or not. Finally, in 3SAT we want all the clauses to be true, so that corresponds to setting a value K in our decision problem so you can only reach K if you make all the clauses 6 instead of 7. That's all! If our decision problem has a solution, then the 3SAT instance must have a solution, and if it doesn't, then the 3SAT instance doesn't have one either. Yay! Thus, spelling reform is harder than 3SAT, so it's NP-hard! (It's also NP-complete since this decision problem is in NP as mentioned earlier.)
## Why should we care?
Alright, so we just proved that spelling reform is NP-hard. So what?
There's a famous open problem in computer science called the P versus NP problem (with a one million dollar prize!). We haven't defined **P** yet, but it's simply the class of all decision problems that can be solved in polynomial time. Easy as that. The question is whether or not P is the same class as NP. Obviously, P is inside NP, because we can easily check a solution by ignoring the solution that's being offered to us and just finding a solution ourselves. However, no one knows yet if problems that are easy to check are also easy to solve. If this is true and P equals NP, then a ton of hard problems are actually easy and solvable in polynomial time. This is pretty crazy, since NP contains some famous hard problems like the Traveling Salesman Problem and factoring that people have spent mounds of effort trying and failing to come up with polynomial time algorithms for. But it would take finding a polynomial time algorithm to just one NP-complete problem to prove that P equals NP, since if one of the hardest problems in NP is solvable in polynomial time, then they all are. Most people believe that P does not equal NP because of the crazy consequences of P equals NP, but there are some [notable people who disagree](/posts/ainion#donald-knuth-proving-p-equals-np-by-executing-all-computer-scientists-who-disagree).
OK, that's some fascinating theoretical CS, but why should we care? Well, taking the common view that P does not equal NP, that means that NP-hard problems do not have fast, polynomial time algorithms. We can't possibly solve them efficiently. Once we prove a problem is NP-hard, then we can shift from searching for efficient exact algorithms to finding heuristics, or approximation algorithms, or algorithms that perform well for typical or random inputs but struggle with some specific contrived inputs that you'll never see in practice. Or maybe you should try to parallelize a slow brute-force algorithm or acquire more hardware. Or maybe it's even a sign that you should change or simplify the problem! Also, if you spend all day thinking about finding algorithms for solving a problem quickly, then pondering how to prove a problem hard can give you an interesting new perspective on the problem. And NP-hard problems are dirt-common, so you'll definitely run into them at some point.
Interestingly, a lot of NP-hard problems are actually still pretty feasible to solve in practice. For instance, there are lots of highly optimized SAT solvers that use various heuristics to perform well in practice. For our spelling reform problem, it would probably be not difficult to solve it for the entire English language, since even though there are thousands of English words, most of the consonant should just stay the same. There's no reason to change "b" into anything other than a "b". In addition, a lot of real-world inputs are also fairly small. For instance, my [Installing Every Arch Package](/posts/installing-every-arch-package) post includes an NP-hard problem, maximum independent set, and the size of the graph is 12000 nodes! And I brute-forced the solution! What? Well, it turns out the graph doesn't have large connected components, so we can brute-force each connected component separately.
And lastly, you should care about NP-hardness because it's just plain fun. When the original Super Mario Bros. was proved NP-hard, there were whole [news articles written about it](https://www.technologyreview.com/2012/03/12/86179/super-mario-bros-proved-np-hard/). What's really cool is that the proof is actually quite similar to the one we did above. Most NP-hardness proofs have a similar style, just often the constructions are a lot more complicated. Usually when we prove something NP-hard, we reduce from some NP-hard problem that is already similar to our problem, so we aren't limited to just reducing from 3SAT. Mario though, turns out to be quite similar in some sense to 3SAT, so check out the proof! It's fun!
![Super Mario Bros. NP-hardness proof construction](/img/mario-np-hard.jpg)

View file

@ -1,6 +1,7 @@
---
title: "Totally Reproducible Arch"
date: 2022-05-18T19:38:43-05:00
draft: true
description: "A single file containing my Arch Linux configuration to flex on all the NixOS noobs"
type: "post"
tags: ["linux", "arch", "nixos", "humor"]

View file

@ -0,0 +1,44 @@
---
title: "Unfactoring"
date: 2023-03-19T01:03:35Z
draft: true
description: "The final story in a long saga of nonsense"
type: "post"
tags: ["humor", "fiction", "math", "lots-of-vowels-series"]
---
*This is the third story in the [Lots of Vowels Series](/tags/lots-of-vowels-series/)*
Kelvin stood there horrified in the MIT dining hall, transfixed on the gruesome corpse of a Gaussian integer that had been factored one too many times. It was a revolting, esoteric scene, but no one other than Kelvin seemed to care. Didn't they understand the gravity of the situation?
Gaussian integers are complex numbers of the form a+bi, where a and b are integers. They are named after the mathematician Carl Friedrich Gauss, who created new and ingenious ways to torture Gaussian integers. But even Gauss couldn't have imagined the brutal fate that had befallen this innocent Gaussian integer.
"Rig crashes dance number."
The words entering Kelvin's ear twisted his brain like a crochet pattern. Kelvin knew this dining hall defied the basic laws of absurdity. As an MIT undergrad and dining hall connoisseur, he had seen it all, including the Great Oyster Cracker Extinction event and the segfaulting bananas. But this was different. He could taste it.
"Leave the complex immediately."
What? Kelvin looked around for the source of the voice or the cause for evacuation, but he saw neither a rig nor dance number.
"Place the world Seattle."
Seattle? That was thousands of kilometers away! What a world.
"Exterminate the violet cup."
Violent cup? Oh wait, violet cup. Well, that doesn't make it any better.
Suddenly, Kelvin saw straight through the madness. Diagonalization! The set of real numbers is uncountable!
Kelvin turned around, bringing him face-to-face with the sinister progenitor of the chaos, but all he saw was an adorable Pallas's cat.
"Mwahahahaha!" cackled the Pallas's cat, "Too bad you can't unfactor numbers!"
"Wait... yeah I can!" Kelvin replied, "That's just multiplication! It's solvable in polynomial time!"
"What???" screamed the Pallas's cat horrified, "But we've been relying on the extreme difficulty of unfactoring numbers for encrypting our top-secret communication! Now everyone will find out that Kazakhstan has been conspiring to rig the World Cup bidding process!"
"Wait what???"

View file

@ -0,0 +1,36 @@
---
title: "How I Use LLMs for Writing Fiction"
date: 2023-07-30T23:16:00Z
description: "The one thing that I've found LLMs to be good at for helping me write fiction"
type: "post"
tags: ["llms", "ai", "humor", "writing"]
---
When I was in grade school, I hated writing.
Now in retrospect, it's pretty obvious why: I was being forced to write about stuff I didn't care a thing about, such as thematically analyzing some random book or stuff like that. Later, in high school, I started blogging about jailbreaking graphing calculators, and I found out I did like writing, just not the kind I was forced to do in school.
There's another thing I always struggled with: the curse of the blank page. Picture this. An empty, clear, unfilled, lifeless page lays before you, and now you need to turn nothing into some piece of writing. So many possibilities! So many choices! So many ways to start!
So yeah, I always get severe choice paralysis when starting any sort of writing. Including this post, where I rewrote the first paragraph six times.
This is where LLMs really shine. They're great for prototyping (and not much else). Throw any idea at them, no matter how ridiculous (but some LLMs might get upset if it's morally questionable), and they'll turn it into some text. Hey ChatGPT, write a short paragraph on how PyTorch tensors can reduce their tension and stress using relaxation exercises!
> In a lighthearted analogy, we can envision PyTorch tensors as hardworking entities tirelessly crunching numbers and processing data. Just like us humans, these tensors can also accumulate tension and stress due to their computational demands. To alleviate their virtual strain and maintain their efficiency, they can benefit from relaxation exercises. One such exercise involves performing operations like tensor reshaping or transposing, allowing them to stretch and unwind. Additionally, they can engage in mathematical functions like sigmoid or tanh activation, analogous to deep breaths, to gently ease their "virtual muscles." Through these relaxation exercises, PyTorch tensors can find a sense of calmness, ensuring they remain resilient and poised to tackle complex tasks with ease.
With LLMs, instead of starting from a blank page full of nothing, I can now start with something, even if it's not great writing.
For the three stories published on my blog, [Beavers](/posts/beavers), [Azerbaijan](/posts/azerbaijan), and [Ennui](/posts/ennui), I used LLMs extensively for prototyping, specifically ChatGPT. But very little of the LLM output actually made it to the final stories, since the output usually just isn't good enough. I have a weird writing style so I had to rewrite a lot of stuff. I also enjoy adding lots of jokes to these stories, and LLM jokes are... well, here's an example:
> Why did the HTML developer go bankrupt?
>
> Because he used up all his tags!
Yeah... Ha. Ha. Ha. Very funny. LLMs are fundamentally uncreative. They generate statistically probable text, not interesting text. If they do generate something interesting, it's because the prompt itself is interesting. Like when ChatGPT first came out and everyone was going crazy about it, I made it generate some [fake news](/posts/ainion). ChatGPT isn't making anything creative here. It's just taking the prompt and stretching it into a serious-sounding news story about something ridiculous. So LLMs aren't some magical shortcut to give you new ideas. You have to find the ideas yourself. All it takes is time.
For instance, this spring I spent four months writing a 10000-word political satire story (currently unpublished), which sounds like a disproportionate amount of time. But I actually only worked on it once or twice a week and spent the rest of the time doing other stuff but keeping an eye out for ideas. For example, the [TED Talk "This is what happens when you reply to spam email"](https://www.ted.com/talks/james_veitch_this_is_what_happens_when_you_reply_to_spam_email) inspired a section in the story where the characters use a series of increasingly ridiculous codenames in a silly attempt to obfuscate their plot to overthrow the government. One day, a random idea just somehow popped into my head of having Trump bond with dictators while watching the Secret Life of Pets 2, and I asked ChatGPT to sketch out the scene. With some edits, here's the final result:
> I have a tremendous, tremendous, tremendous story for you. Okay? It's a tremendous story. Believe me, you're gonna love it. So, picture this. It's 2 AM, okay? It's 2 AM, and I'm sitting there in my big, beautiful Trump Tower penthouse. And guess who's with me? Vladimir V Putin, Chairman Xi Jinping, and Kim Jong-un the Fat. Yeah, that's right. The whole gang, all together. And you know what we're doing? We're watching a movie. Yeah, a movie. We're watching "The Secret Life of Pets 2." Can you believe it? I mean, who knew world leaders had movie nights? I did. I did. I knew it. So, we're watching this movie, and let me tell you, folks, it was fantastic. It was fantastic. It was better than any movie you've ever seen, believe me. Now, here's the thing. You know, I'm not gonna spoil the movie for you, okay? I'm not gonna do that. But there's this one scene, okay? There's this one scene that hit us right in the feels. I mean, right in the feels. We were sobbing, folks. We were sobbing. And you know what? I'm gonna tell you something. I'm gonna tell you something. There were tears, big, beautiful, manly tears. But you know, not too manly. Not too manly. Just the right amount of manly. Just like my hair. So, there we were, crying like babies, folks. And let me tell you, let me tell you, it wasn't a pretty sight. It wasn't pretty. You had my lad Vlad over there. He was wiping his tears with his bare chest, folks. Bare chest. And you know, Kimmy, he had his little nuke-shaped tissues. Very cute. Very cute, I must say. And lil' Xi, oh, lil' Xi, he had this teensy Winnie-the-Pooh-themed handkerchief. It was adorable. Adorable, folks. But me, me, folks, I had the best tears. The best. My tears were tremendous. They were tremendous. They were the best tears. And I know more about tears than anyone else in the room. Believe me. Believe me. And I was using the Constitution to wipe them away. That's right. The original copy of the Constitution. Because that's what a true patriot does. Okay? Now, I'm not saying we were crying because of the movie, okay? We were crying for other reasons. Very important reasons. And let me tell you, folks, when world leaders cry together, it's a beautiful thing. It's a beautiful thing. We were so moved, folks. So moved. We were like, "Oh my God. Oh my God. Those pets. They have such secret lives. Such secret lives. It's unbelievable." And we were sobbing. We were sobbing. But you know what? We bonded. We bonded over those tears, folks. We bonded over those tears. And we made a pact. We made a pact right then and there. We said, "We will never let our differences tear us apart. Never. Never." And let me tell you, folks, let me tell you, we've been best buddies ever since. Ever since. So you see, you see, movies bring people together, folks. They bring people together. Even world leaders. Even world leaders. So, if you take anything away from this story, folks, take this. Take this. The Secret Life of Pets 2 is a tremendous movie. And if it can bring Vlad, Xi, Kimmy, and me together, then it can bring anyone together. Anyone. Believe me. God bless America. And God bless the Secret Life of Pets 2. Tremendous.
One last thing: ChatGPT was all I had when I wrote some of those earlier stories, but now [llama.cpp](https://github.com/ggerganov/llama.cpp) and it's awesome. In particular, it's incredibly useful to increase the temperature to get crazier results with more hallucinations, which aren't necessary a bad thing when writing fiction, and overall just more customizable.

View file

@ -1,6 +1,7 @@
---
title: "The Web Sucks!"
date: 2021-02-26
draft: true
type: "post"
tags: ["Web", "Rant"]
---

Some files were not shown because too many files have changed in this diff Show more