The Big Book of Small EK9 Programs
Adapted from Al Sweigart's The Big Book of Small Python Projects: 81 Easy Practice Programs (No Starch Press, 2021; copyright © 2021 Al Sweigart), which he makes freely available under a Creative Commons Attribution-NonCommercial-ShareAlike licence at inventwithpython.com/bigbookpython. Changes were made: each program was ported from Python to EK9 and remodelled in EK9's idioms.
Project 40 — Leetspeak
This is project 40 of the book, ported to EK9. Its chapter is still being written; until then, this page shows the port itself: a run of it, the whole program, and how it keeps to the original.
A sample run
The program is random, so the run fixes it by setting BIGBOOK_SEED=1.
Run it with:
BIGBOOK_SEED=1 ek9 leetspeak.ek9 "elite hacker"
It prints:
elite ]-[a(]<3r
The program
#!ek9 defines module bigbook.leetspeak defines constant ReplaceChancePercent <- 70 defines class //THE OUTPUT: everything the reader sees goes through here. The port shows no words of its //own, only the translation, so there is no Say; the message is a program argument, so //there is no LineInput. Console stdout as Stdout: Stdout() //The translation is computed, not worded: it is shown as the game made it. showTranslated() -> translated as String stdout.println(translated) override operator ? as pure <- rtn as Boolean: true defines function //THE GAME: the translation, with no output. //The book's table: the leetspeak spellings each letter may become. leetTable() as pure <- rtn as Dict of (Character, List of String): { 'a': ["4", "@", "/-\\"], 'c': ["("], 'd': ["|)"], 'e': ["3"], 'f': ["ph"], 'h': ["]-[", "|-|"], 'i': ["1", "!", "|"], 'k': ["]<"], 'o': ["0"], 's': ["$", "5"], 't': ["7", "+"], 'u': ["|_|"], 'v': ["\\/"] } //A letter with spellings is replaced ReplaceChancePercent of the time, by one of them //chosen at random; anything else is kept. `and` stops at the first false operand, so a //character with no spellings draws no random number - the sequence matches the book's. leetOf() -> original as Character spellings as List of String rng as Random <- rtn as String: original if not spellings.empty() and rng.next(1, 100) <= ReplaceChancePercent rtn: spellings.getOrDefault(rng.next(0, length spellings - 1), rtn) leet() -> message as String rng as Random <- rtn as String: "" table <- leetTable() noSpellings <- List() of String for ch in message rtn += leetOf(ch, table.getOrDefault(ch.lowerCase(), noSpellings), rng) defines function //THE source of randomness, copied unchanged from lib/RandomSource.ek9: SystemRandom(), or //SeededRandom(seed) when BIGBOOK_SEED holds a number (run-and-diff.sh sets it from seed.txt). randomSource() <- rtn as Random: SeededRandom(Integer(EnvVars().get("BIGBOOK_SEED"))) ?: SystemRandom() defines program //Leetspeak (Big Book project 40). Rewrites the message argument in leetspeak, choosing at //random which letters to replace and with which spelling. The game decides; the Console //shows it. The golden replays a seeded run (seed.txt). Leetspeak() -> message as String console <- Console() rng <- randomSource() console.showTranslated(leet(message, rng))
About this port
- Behaviour: as in the book, leetspeak is random: a letter in the table is replaced about
70% of the time (
random.random() <= 0.70), and then by one of its spellings chosen at random (random.choice). Letters not in the table, and every other character, are kept. - Idioms:
- The table is a
Dict of (Character, List of String)literal returned by a pureleetTable(); a missing letter reads as an empty list (getOrDefault), so there is no separatecontainscheck. leetOftakes one character and returns its replacement.andstops at the first false operand, so a character with no spellings draws no random number and the random sequence is consumed exactly as the book consumes it.- The message is a typed
Stringprogram argument.
- The table is a