Created
June 17, 2026 03:39
-
-
Save Xevion/61ba6d434c203174c55d5c049b5d8b28 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // How long would it have taken Hector Salamanca's nephews to transcribe his | |
| // letter off the bell board, one character at a time? (bun run this file) | |
| // | |
| // Short answer: roughly an hour and a half. Output's at the bottom if you'd | |
| // rather not run it. | |
| // | |
| // The letter is from Better Call Saul "Fun and Games" (S6E9), where Bolsa reads | |
| // it to the cartel. He reads it in Spanish; the English on screen is a subtitle, | |
| // so the Spanish is what the cousins actually spelled out. I lifted the words | |
| // off the scene audio with whisper. | |
| // | |
| // The board is the 6x6 grid Hector points at. It's not A-Z in order: every row | |
| // starts on a vowel, with the digits crammed into the two short rows. (Row 6 | |
| // past "5 6" is a guess - there's no clean shot of the whole board - but it | |
| // doesn't matter here, the letter has no numbers.) | |
| // | |
| // Method, as shown on screen: someone reads the first letter of each row until | |
| // Hector rings, then reads across that row until he rings again. Two rings, | |
| // and (row + column) reads, per character. | |
| const board = ["ABCD12", "EFGH34", "IJKLMN", "OPQRST", "UVWXYZ", "567890"]; | |
| const at = new Map<string, [number, number]>(); | |
| board.forEach((row, r) => [...row].forEach((c, i) => at.set(c, [r + 1, i + 1]))); | |
| const letter = `El atentado contra mi sobrino en su hacienda falló. Lalo le ganó a los | |
| asesinos. El día después del ataque, Lalo me llamó. Escuché la verdad de sus | |
| propios labios. Fue Fring quien mandó a los asesinos, no a los peruanos. | |
| Mantuvimos en secreto que Lalo sobrevivió. Mi sobrino estaba a punto de | |
| vengarse del traidor. Frente a frente. Pero desapareció. Esto fue obra del | |
| pollero. Don Eladio, mire a Fring a los ojos. Allí verá la verdad. El pollero | |
| lo odia. Es nuestro enemigo. Él conspira en contra de nosotros. Yo exijo | |
| sangre por sangre.`; | |
| // Cadence never made it on screen, so these are guesses: [read, ring, perChar, perWord]. | |
| const speeds: Record<string, number[]> = { | |
| brisk: [1.0, 1.5, 0.5, 0.0], | |
| realistic: [1.5, 2.0, 1.0, 1.0], | |
| deliberate: [2.5, 3.0, 2.0, 2.0], | |
| }; | |
| // The board is an English one (Hector spells "SUCK MY" at the DEA in English), | |
| // so accents come off and anything not on the board is dropped. | |
| const text = letter.normalize("NFD").replace(/[̀-ͯ]/g, "").toUpperCase(); | |
| let reads = 0; | |
| let chars = 0; | |
| let words = 0; | |
| for (const ch of text.replace(/\s+/g, " ")) { | |
| if (ch === " ") words++; | |
| else if (at.has(ch)) { | |
| const [row, col] = at.get(ch)!; | |
| reads += row + col; | |
| chars++; | |
| } | |
| } | |
| const hms = (s: number) => `${Math.floor(s / 3600)}h ${Math.floor((s % 3600) / 60)}m`; | |
| console.log(`${chars} characters, ${reads} reads, ${chars * 2} rings\n`); | |
| for (const [name, [read, ring, perChar, perWord]] of Object.entries(speeds)) { | |
| const s = reads * read + chars * 2 * ring + chars * perChar + words * perWord; | |
| console.log(`${name.padEnd(11)} ${hms(s)} (${Math.round(s / 60)} min)`); | |
| } | |
| // 423 characters, 2388 reads, 846 rings | |
| // | |
| // brisk 1h 4m (64 min) | |
| // realistic 1h 36m (97 min) | |
| // deliberate 2h 39m (159 min) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment