George V. Reilly

Exploring Wordle

Unless YOUVE LIVED UNDER ROCKS, you've heard of Wordle, the online word game that has become wildly popular since late 2021. You've probably seen people posting their Wordle games as grids of little green, yellow, and black (or white) emojis on social media.

Wordle 797 4/6

โฌ› โฌ› โฌ› โฌ› ๐ŸŸจ
๐ŸŸจ โฌ› ๐ŸŸฉ โฌ› โฌ›
โฌ› โฌ› ๐ŸŸฉ ๐ŸŸจ โฌ›
๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ

The problem that I want to address in this post is:

Given some GUESS=SCORE pairs for Wordle and a word list, pro­gram­mat­i­cal­ly find all the words from the list that are eligible as answers.

Let's look at this four-round game for Wordle 797:


Regex Conjunctions

Most regular expression engines make it easy to match al­ter­na­tions (or dis­junc­tions) with the | operator: to match either foo or bar, use foo|bar.

Few regex engines have any provisions for con­junc­tions, and the syntax is often horrible. Awk makes it easy to match /pat1/ && /pat2/ && /pat3/.

$ cat <<EOF | awk '/bar/ && /foo/'
> foo bar
> bar
> barfy food
> barfly
foo bar
barfy food

In the case of a Unix pipeline, the con­junc­tion could also be expressed as a series of pipes: ... | grep pat1 | grep pat2 | grep pat3 | ....

The longest regex that I ever en­coun­tered was an enormous al­ter­na­tionโ€”a true horror that shouldn’t have continue.

Python Enums with Attributes

Python enu­mer­a­tions are useful for grouping related constants in a namespace. You can add additional behaviors to an enum class, but there isn’t an easy and obvious way to add attributes to enum members.

class TileState(Enum):
    CORRECT = 1
    PRESENT = 2
    ABSENT  = 3

    def color(self):
        if self is self.CORRECT:
            return "Green"
        elif self is self.PRESENT:

Patching a Python Wheel

Recently, I had to create a new Python wheel for PyTorch. There is a cyclic dependency between PyTorch 2.0.1 and Triton 2.0.0: Torch depends upon Triton, but Triton also depends on Torch. Pip is okay with installing packages where there’s a cyclic dependency. Bazel, however, does not handle cyclic de­pen­den­cies between packages. We use Bazel ex­ten­sive­ly at Stripe and this cyclic dependency prevented us from using the latest version of Torch.

I spent a few days trying to build the PyTorch wheel from source. It was a nightmare! I ran out of disk space on the root partition on my EC2 devbox trying to install system packages, so I had to bring continue.

Bram Moolenaar RIP

I woke up on Saturday to read on Bram Moolenaar’s Facebook page an an­nounce­ment of his death. I knew Bram online for nearly 30 years and I was one of his relatively small number of Facebook friends, but we never met in real life. I knew that he had retired from Google Zurich to Tenerife, but I hadn’t been aware that he had been ill.

Bram was known to the world for his signature creation, the Vim text editor, used by millions of developers on Linux, macOS, and Windows. Vim stands for Vi IMproved, but it outgrew the original vi long ago.

I was an active con­trib­u­tor to Vim in the 1990s: I wrote a continue.

Cold Brew Coffee Recipe

I often enjoy cold brew coffee in summer. I bought an Oxo Cold Brew Coffee Maker one winter when it was on sale at Bed, Bath & Beyond. Before that, I used a nut milk bag in a jar. I like the Oxo and it gets high marks in many reviews, such as Home­Grounds or Wirecutter. It’s easy to use, easy to clean, and makes a good brew.

The only downside to making your own cold brew coffee is that you must plan ahead. You can make hot coffee in a few minutes, but cold brew takes hours.

I have used this recipe for a number of years. It makes a smooth, less acidic coffee.


Compressing Tar Files in Parallel

TL;DR: use tar -I pigz or tar -I lbzip2 to compress large tar files much more quickly.

I in­ves­ti­gat­ed various ways of com­press­ing a 7GiB tar file.

The built-in --gzip and --bzip2 com­pres­sion methods in GNU tar are single-threaded. If you invoke an external compressor with --use-compress-program, you can get some huge reductions in com­pres­sion time, with slightly worse com­pres­sion ratios.

You can use pigz as a parallel re­place­ment for gzip and lbzip2 as a parallel version of bzip2. Both of them will make heavy use of all the cores in your system, greatly reducing the real time relative to the user time.

Single-threaded com­pres­sion timing: gzip is a lot faster than bzip2:

$ time tar --bzip2 -cf 

Implementing the Tree command in Rust, part 2: Printing Trees

In Part 1, we saw how to walk directory trees, re­cur­sive­ly using fs::read_dir to construct an in-memory tree of FileNodes. In Part 2, we’ll implement the rest of the core of the tree command: printing the directory tree with Box Drawing characters.

Let’s take a look at some output from tree:

โ”œโ”€โ”€ os
โ”‚   โ”œโ”€โ”€ wasi
โ”‚   โ”‚   โ”œโ”€โ”€
โ”‚   โ”‚   โ”œโ”€โ”€          โžŠ
โ”‚   โ”‚   โ””โ”€โ”€ net             โž‹
โ”‚   โ”‚       โ””โ”€โ”€
โ”‚   โ””โ”€โ”€ windows
โ”‚       โ”œโ”€โ”€    

Implementing the Tree command in Rust, part 1: Walking Directories

I’ve been learning Rust lately. I started by reading several books, including Rust in Action, Code Like a Pro in Rust, and most of Pro­gram­ming Rust. Now, I’m starting to actually write code.

I read the Command-Line Rust book last month, which challenged readers to write our own im­ple­men­ta­tions of the tree command.

I decided to accept the challenge.

At its simplest, tree simply prints a directory tree, using some of the Unicode Box Drawing characters to show the hi­er­ar­chi­cal re­la­tion­ship, as in the image at right.

I’ve split the code into two phases, which will be covered in two blog posts.

  1. Walking the directory tree on disk to build an in-memory tree.
  2. Pretty-printing the in-memory tree.

While it’s certainly possible to print a continue.

fsymbols for Unicode weirdness

My display name on Twitter currently looks like @ษขแด‡แดส€ษขแด‡แด ส€แด‡ษชสŸสŸส@แด›แด‡แด„สœ.สŸษขส™แด›, an attempt to route around Twitter’s apparent censorship of Mastodon in­for­ma­tion.

I used the FSymbols Generators to produce several variants.

@๐•˜๐•–๐• ๐•ฃ๐•˜๐•–๐•ง๐•ฃ๐•–๐•š๐•๐•๐•ช@๐•ฅ๐•–๐•”๐•™.๐•๐•˜๐•“๐•ฅ
@๐”ค๐”ข๐”ฌ๐”ฏ๐”ค๐”ข๐”ณ๐”ฏ๐”ข๐”ฆ๐”ฉ๐”ฉ๐”ถ@๐”ฑ๐”ข๐” ๐”ฅ.๐”ฉ๐”ค๐”Ÿ๐”ฑ

Many of these variants come from Unicode Block “Math­e­mat­i­cal Al­phanu­mer­ic Symbols”.

There are a lot more things you can do with Unicode than just upside-down text.

Previous »