More filler

I noticed some HTML5 crossword construction apps have sprung up over the last year, so I no longer have first mover status on that. Also their UIs are generally better and I dislike UI work, so it seemed reasonable to join forces. Thus, I sent some PRs around.

It was surprising to me that the general SAT solver used by Phil, written in C compiled to asmjs was so much slower than a pure Javascript purpose-built crossword solver (mine). I assumed the SAT solver might make certain search optimizations that could overcome the minor optimizations related to mine being only a crossword solver. So, yay, my code is not that bad?

In these apps the filler runs as a web worker so even when slow it isn’t too noticable (except for hogging a core).

Anyway you can try out my filler today with Kevin (filler code is here, which is exactly the code in my own app except with some janky whitespace because I stripped out all flow annotations).

Peak 2018

I almost let the second half of 2018 go unblogged (are people still saying blog?). It’s not that nothing interesting happened in all of that time, but real life has been ultra busy. Did I mention that Sammy turned one and is on the verge of walking?

The garden delivered tons of produce this year, enough that I didn’t really keep up. I gave myself a crash course in canning, making four jars of tomatillo salsa and six jars of habanero jam. Maybe fewer peppers next year?

I harvested around five bowls of tomatoes, many of which are taking up space in the freezer right now.

And at least four of these basil bowls, mostly frozen pesto at the moment:

This is what it is all about: pizza with homegrown basil, homegrown tomatoes, and sourdough crust from locally cultured yeast.

Anyway, happy New Year!

Another one about plants

Here’s what the garden looks like right now. Compare to this time last year.

We had our backyard professionally landscaped last fall, and the landscaper decided to put in an empty bed next to the house instead of incorporating my unsightly DIY planter box into the design. But that area gets sun only half of the day, so I planted both this year, reserving the landscaper-approved bed for the experimental plants (mostly tomatillos and some extra basil). In the photo you can see the tomatillos in the background on the right: they have grown as tall as I am, with plenty of flowers but no fruits yet. Still, the pollinators are visiting so that could change:

Meanwhile, there are baby tomatoes and baby peppers everywhere, and lots and lots of basil. Having eight basil plants means making pesto every other week just to keep up. I picked my first jalapeno yesterday. Although I tried hard to label all my plants this year, I found that one of my intended habeneros was a mislabeled poblano. No worries, poblanos are great. Looking forward to stuffed peppers next month.

We have a family of wild rabbits living near the house, so I stayed away from lettuces or other rabbit-friendly fare. Perhaps I’ll try lettuce in the planter box next year since it is high enough it might evade their grasp. I planted a few onions in the lower bed to keep the rabbits away from the other plants, having heard that they hate the smell of onions. Naturally, onion stalks are the only thing they’ve eaten so far.

This is still the quiet times before the Japanese beetles. Once they show up a few weeks from now, they will require thrice-daily purges, a not so fun task.

Posting on posting

After several years of working at popular infosec startup, I’ve now moved on to giant tech company. It was pretty crazy watching the former grow from “hey, we have a cool idea” to a company with hundreds of developers — at turns gratifying to see people describe your software as life-changing, and incredibly stressful when a bug landed on the top of Hacker News.

In the new gig, I’m working on Linux wifi again, so, apologies in advance. Hopefully, I’ll be able to do a bit more work upstream now that it is kind of my job. And yes, this post exists just to break up what would otherwise be a long string of consecutive garden blogs.

Garden 2018

I’ve started my seedlings for the 2018 gardening season. On March 24, I planted jalapeno, habanero, roma tomato, green onion, and basil seeds into jiffy pods. A few days later I planted some tomatillos and poblanos in another tray. By this time everything has sprouted and the plants are under grow lights for 15 hours a day on a timer (an innovation since last year the plants got a little leggy on the windowsill). The first tray is about a week ahead of the other tray, so it’s been getting full light for a week and had its first watering this morning. The tomatoes have their first true leaves as of today.

I’m targeting planting out sometime in mid to late May. I can’t remember when I potted up the plants last year but it must’ve been some time in late April / early May. That’s at least a couple of weeks away for these 2-week old seedlings.

This year I hope to have better tomatoes by planting fewer of them and giving them more space. I was originally planning to do just two roma plants with two-foot spacing, plus one tomatillo plant. Then I learned that tomatillos won’t self pollinate so I’ll need to do at least two of those also. If those plus all the pepper plants work out, we’ll have way more than we can eat. Of course, the rabbits may still have other plans.

Crossword digest

This month my age incremented again. On the very anniversary of my birth, I received an email from Will Shortz’s assistant, saying (nicely) that the puzzle I submitted back in November didn’t make the cut. I was prepared for this: a puzzle with a similar theme came out a couple of weeks after I mailed mine in, and well, it’s not exactly that unique in the first place. Also the middle section of my puz is a bit of a stretch. And, I felt bad about not trying to excise 23-A from the puzzle.

But anyway, their loss is your loss! Click here to try it.

The 2018 American Crossword Puzzle Tournament starts this coming weekend. Last year, I complained that the online crossword tournament used a Java applet and would have almost no browser support by this time. This year, the online solver is running a version of my own XwordJS, customized (by me) for the ACPT’s backend (which I had nothing to do with). Here’s hoping it works.

After the 2017 tournament, I hoped to increase my solving speed to be more competitive this time around. In reality, I didn’t put much effort into this goal, so I expect to be about the same. My best NYT Monday time, for that one month when I tracked it, was a hair over 7 minutes, far from the front of the pack.

Meanwhile, I did make a bit of progress in solving cryptics, having done the puzzle a few times in the Toronto Star and actually finishing last week’s. I have to say they aren’t as fun as American style crosswords due to the arbitrariness of the cluing, or so I tell myself so that I can feel less dumb.

Making copies

One of my early goals this year has been to revamp the backup regime at the old homestead. Previously, I have relied on rotating external drives connected to my main desktop, and putting most content on a samba share that also got backed up. But it was a bit ad-hoc and things not on the share only got backed up sporadically. I’d rather not use a cloud backup service because reasons, so I bought a NAS, and now it looks like this:

  • Daily:
    • download cloud assets (google photo)
    • backup all disks to NAS (borg backup on Linux, Windows backup). Incrementals of 7 days / 4 weeks / 6 months
    • backup NAS to external drive (rsync)
  • Weekly:
    • borg check the latest backup
    • swap external disk with one in fire safe
  • Monthly:
    • swap external disk with off-site disk

I think this should work well enough until I use up enough storage to outstrip the individual external disks, then I’ll have to rethink things. Too far, or not too far enough?

New Year, Old Me

2018 is finally upon us, and now is the time one would usually look back at the wonderful events of the previous year, and look forward to what great things one might accomplish in the next.

Instead of that, I’ll just write a meandering blog post.

In 2017, I leveled up on pizza and bread making, capturing and raising my very own colony of hyper-local, non-GMO, swimming-in-gluten yeast. The colony still thrives as it approaches its first birthday, and has fed us many delicious loaves. I think I have the basic no-commercial-yeast dough down now, so it is time to start tinkering with the bulk fermentation and proofing times to get different flavors and textures out of the bread.

Speaking of cooking, after 20-something years of preparing the same three proteins with not so much variation, I feel like I could use more inspiration in the kitchen. So I’ve started working my way through an Asian cookbook someone gave me for Christmas. Tip: homemade Thai sweet chili sauce (using peppers from our garden) turns out to be amazing on roast beef and aged cheddar sandwiches. Who knew?

We’re still working our way through the garden vegetables in the freezer, so I can say that the garden worked out and I will have to do it again this year. This time I probably won’t plant so many tomatoes right next to each other, and I think I’ll select pepper varieties rather than doing a mixed seed blend. I might play around a bit with controlling irrigation through an SBC or some such just to bring some nerdiness to the party.

Six years into my consultancy, things are going well enough, but this year I may start looking around for the next big gig. Lately I’ve been doing mostly infosec work and it is ridiculously draining in the age of we-can’t-even-get-hardware-right. If you’re one of the three people reading this and whose programming team needs an old, feel free to reach out. Bonus points if you are working in a language that has a compiler, and infinity points if you are sending code into space.

The crossword construction hobby grew a bit in 2017, culminating in my submitting a crossword to the NYT for publication. That one will probably get rejected, but even so it was fun to make (and perhaps as fun making the software to make it). I think with just a bit more practice and some theme inspiration, I’ll have the hang of this nascent hobby. Meanwhile, my javascript puzzle solving SPA is getting used in a few more places, including on some commercial puzzle sites; I hope that trend will continue.

Of course the biggest news in 2017 was growing our family once more. In addition to the usual resolution to be the best parent I can be to Alex, Ian, and now Sam, I also hope we can get more sleep in 2018. That would be kind of great.

Router redux

I had just a little bit of downtime over the last few weeks while Angeline and I reacquainted ourselves with how to take care of an infant. It’s like riding a bicycle: there are tons of things you forgot since last time.

One of the long-on-my-todo-list items finally got completed: I upgraded all of my wifi routers. I have 5: an old dual band 11n router and four TP-Link 11ac units, all of which were running some oldish build of OpenWRT.

I decided the 11n router’s time has come for the trash-heap, so I put the latest stable LEDE build on one of the TP-Links and swapped it out.

The other three are just access points without the router: they just have all the ports on the unit bridged together, connected to the router via a wired switch. I also have a mesh wifi interface up on each unit so that I could place the unit anywhere regardless of wired connectivity (though, in practice, I have wired drops everywhere so I don’t really use this.) For these, I build from source with just the required bits. I added a serial port to one of the units so I can test builds there before rolling out to the other two.

In all it was pretty painless since the LEDE build is more or less the same as OpenWRT. I did go through (LEDE) recovery once and found this fun issue:

root@(none):/tmp# sysupgrade -n lede-ar71xx-generic-archer-c7-v2-squashfs-sysupgrade.bin
Image metadata not found
killall: watchdog: no process killed
Commencing upgrade. All shell sessions will be closed now.
Failed to connect to ubus
root@(none):/tmp#

…because sysupgrade has different paths for failsafe vs not; and for some reason $FAILSAFE is not always set. Do this to work-around:

root@(none):/tmp# export FAILSAFE=1
root@(none):/tmp# sysupgrade -n lede-ar71xx-generic-archer-c7-v2-squashfs-sysupgrade.bin
Image metadata not found
killall: watchdog: no process killed
Commencing upgrade. All shell sessions will be closed now.
root@(none):/tmp# Connection to 192.168.1.1 closed by remote host.

On board the rebus

My most recent post, for those too lazy to follow the link and hit the “Reveal All” button, is a crossword puzzle announcing the birth of our third son, Samuel Yit-Mun Copeland. We’re over the moon with this new guy in our family. Here he is nearly asleep in my arms as I type this.

But now for something more boring.

I decided months ago that my typical geeky announcement would take the form of a crossword since I’ve been playing in that area recently (previous announcements: a manpage for Alex, an ascii-art crypto program for Ian). And why not make this puzzle interesting by constructing my first rebus puzzle?

A rebus puzzle is one in which a single square can have multiple letters. Part of the fun of solving is realizing at some point that an answer must be right, yet it cannot fit the available cells, so something really weird is going on. Then one curses the constructor and starts with a new set of assumptions.

Constructing such a puzzle is not too much harder than any ordinary puzzle, since all the rebus squares will be part of the themers that the constructor selects up front. Because of this, the fill software doesn’t even really need to care about rebuses — one can use any placeholder for the rebus squares and then edit the final crossword file to add in the full string.

Having lots of theme squares does constrain the grid somewhat, as does having a number of circles on top of that (in this case the circles spell out our new son’s name). But I cheated a little bit: I decided having any old separation between circles was fine as long as the components were all on the same line, and his name is short so that was no major obstacle. In the end I’m pretty happy with the fill considering the 55 theme squares + 20 circles.

Each time I make a puzzle, I also make a number of improvements to my filling software. I’ve long since forgotten whether the goal is building puzzles or building a puzzle builder.

I mentioned before that I had optimized the javascript filler to the point that it was potentially usable in a webapp; this webapp is now a thing. For this puzzle, I used that app as well as my interactive python command-line filler, which has some additional features like estimating the number of eventual solutions using more levels of look-ahead. Finally, I also used a version of the python filler that will take a completed grid and try to optimize it by repeatedly clearing sections of the grid and refilling it randomly.

There is still a good deal of performance work to do on the filler itself. The basic structure is still similar to the backtracking algorithm in QXW: bitmaps are used to filter available words for each cell, and we fill each entry starting with the entries with fewest fills. I made two minor changes in my version: the word list is initially sorted by score and indexed on length so that we can try highest scoring words first and eliminate comparisons against words that will never fit; and entire entries are filled instead of single cells so that score of an entire word is maximized.

I implemented my current algorithm from scratch in C, and it clocks in under half a second for my test puzzle: a little faster than QXW’s implementation and some 30x faster than the very same algorithm in javascript. In terms of LOC, they are roughly the same: 573 (python), 696 (javascript), 763 (C). You can watch them compete below.

So the javascript implementation is frightfully slow. Getting it down to the level of, say, two times the C code, would be a major win, but beyond my current level of js optimization know-how.

Besides that, there is likely some algorithmic optimization that could bring larger gains. Knowing that the “crossword fill problem” is an instance of SAT, I went off to read what Knuth had to say about it (Vol 4 fascicles 5-6), and, as usual, came away with a lot more to think about. The “word square” section is very similar to crossword filling, and indeed the algorithm is close to my existing search, except that it uses trie data structures to cut down on the number of possible words visited at each level. It’s unclear to me at present whether tries would be a win here given that we don’t always start filling with a prefix or suffix, but it could be worth an (ahem) try. Also I may look at branch-and-bound search pruning and parallel search at some point.