Side Project: Wordle Solver

TLDR: a side-project Wordle Solver, and the GitHub repository (with files/lines specifically linked throughout the rest of this post).

A New Side Project

“Side projects are good and fun.  So is Wordle.”

I always try to have a side-project in the mix.  In software development it’s quite important to stay pliable (a la Tom Brady), adaptable, and stay current to the latest in software languages, frameworks, and hosting paradigms (not necessarily Cloud just for the sake of ‘Cloud’).  It’s also important from a Product aspect.  With a side project you (as an engineer/technologist) have total control over the direction of the implementation.  The act of organizing/prioritizing what you want to implement can vastly help in your professional life where there is not as much control over the direction of Product (but on your own you will have recognized pitfalls, best-practices, or tools.)  And the value goes 4x when you collaborate on a side-project with 1+ other people.

Wordle Trie Search

“Using less electricity is good.”

One day my former roommate from college (Alex, a very bright computer scientist) sent me a text with a link to his Github repository.  He had a very advanced start on a Wordle guess validation algorithm, implemented using a recursively traversable trie structure containing ~all/most of the English words in the 5 character space.  (What’s nice about search trees is that search operations are much more efficient than a naive/linear approach.)

From the Wikipedia article Trie
Credit: Booyabazooka (based on PNG image by Deco).  Modifications by Superm401., Public domain, via Wikimedia Commons

Immediately I’m mentally committed.  This Wordle thing had taken off, I had played it a couple times and I loved the idea of being able to work with Alex again and build something in the Wordle arena. 

Updating the Algorithm

“He will win who knows when to fight and when not to fight.”— Sun Tzu

Alex had the algorithm at an 80% complete state.  Though we recognized it was not using all the information of a guess which had a correct letter but wrong location.  This code change/commit fixed the algorithm and would preclude unnecessary traversals of the trie.

For the Internet

Real artists ship.”— Steve Jobs

(No I’m not claiming to be an artist.  Just a technologist.)

I didn’t start this project, so I went looking for how I could bring extra value (i.e. enter a space for implementation that wasn’t being served yet).

Software is useless unless you have a channel to distribute it.  That’s why the Internet is so valuable.  Professionally I was already very familiar with the Java Spring framework, so I committed myself to creating a REST API to expose the underlying algorithm.

I created a Spring sub-project within the same repo, and referenced the algorithm and supporting files using symlinks which actually worked with the build!  I thought this was a neat way to include Alex’s code.  (I don’t know if I would recommend this approach professionally, it’s a little hacky.)

Automated Testing

They test it.  Exactly.

A nice addition by our third collaborator, Tyler, brought in some github workflows driving some unit tests.  This helped identify if anything was broken by a feature/bugfix branch.  Bonus: the unit tests in the ‘sub-project’ Spring application could be run consecutively after the root level tests.

For the Internet, take two

Wrapping the algorithm in Spring was not the correct idea.  I had not thought through on how I wanted to host the application.  An executable jar could have been compiled, but would have needed a virtual host or container to run on.  So instead I spent a weekend to wrap the algorithm a second time but using the AWS Lambda Handler so it could be run serverless.  (This could cut low-traffic hosting from $20/month down to about $2.)  Also some AWS ClouFormation automation helped (from an AWSDocs repo) with the iteration and deployments.  Though I manually integrated an API GW to the Lambda.

Front End

“If there’s a ‘trick’ to it, the UI is broken.”— Douglas Anderson

A little Bootstrapv4 CSS can go a long way, visually.  I’m not a front-end developer but being able to sling together some bare HTML, Bootstrap, forms and JQuery:ajax makes possible a lot of webapp creation.

I also included a fun animated background from a codepen project.

The HTML page is completely static and I uploaded to AWS S3 and aliased a Route53 record for a domain I own.

Lastly, it’s not quite a security thing (rather towards exclusivity), I modified the application to include an Access-Control-Allow-Origin in the header for every request to the API/algorithm.  This will instruct browsers to stop other websites from using my API, though anyone could curl against it if desired.  Or the repository is public, someone could deploy their own Lambda!

Thanks, and Wordle on!

Advent of Code 2020: Day 18 Order of Operations (Arithmetic)

As I had written in a previous blog post, I participated in the Advent of Code, 25 programming problems to help improve my skills. I maintained really good momentum through day 20 before holiday activities forced me to pause. (Bonus: I have 5 really solid problems to play with for the next month.)

One of the best aspects of such a side activity is discussing the problems with some of my colleagues, and seeing the different approaches. It was important we treated the discussion as a open and safe space. Of course there are wrong answers, the underlying problem needs to be solved. But there are many different ways to approach and implement the solution including non-optimal ones. It was not meant to be a code golf challenge: rather by experimenting with unfamiliar aspects of our programming languages and solving abstract problems, we deepened our expertise.

I particularly enjoyed problem Day 18. Perhaps you remember your PEMDAS (order of arithmetic operations) from junior high. The Day 18 problem jumbled the notion of PEMDAS and asked to evaluate expressions if operations were evaluated “strictly left to right” or “addition comes before multiplication.” (The horror…)

My solution involved mapping the ‘depth’ of an expression wrt parentheses, then building a method to do the custom expression evaluation. Wrapping the two in iteration, I could then slice, divide, and conquer the expression to obtain the final result. Here’s an example of an expression, where the updated depth map is followed by the sliced expression selected for evaluation and finally replaced. This keeps drilling down until the entire expression has been evaluated:

### addition before multiplication ###

 (3+6+7+9)*(2+(4*7*6+9+3+5)+9+(2+3+7+4+3)+9)+8

"(3+6+7+9)*(2+(4*7*6+9+3+5)+9+(2+3+7+4+3)+9)+8"
 111111111011122222222222221112222222222211100
               4*7*6+9+3+5
               644
              ___
"(3+6+7+9)*(2+644+9+(2+3+7+4+3)+9)+8"
 11111111101111111112222222222211100
                     2+3+7+4+3
                     19
                    __
"(3+6+7+9)*(2+644+9+19+9)+8"
 11111111101111111111111100
  3+6+7+9
  25
 __ 
"25*(2+644+9+19+9)+8"
 0001111111111111100
     2+644+9+19+9
     683
    ___
"25*683+8"

line_value: 17275 

How did my colleagues approach this?

  • David – used a clever regex to find the ‘deepest’ pair of parentheses, then evaluated the contained expression, and repeat as long as there was a ‘(‘ character remaining in the expression.
  • Josh – employed a similar regex recognition, but wrapped his solution in a very tidy `map()` for an almost minified look. By using less memory, Josh is minimizing his electricity consumption and saving the environment!

Advent of Code 2020: A Challenge Ahead of the Holidays

It’s important to continually hone your own skills true to being a true professional. Credit to my colleague David Lozzi for bringing Advent of Code 2020 to my attention, to which I immediately knew I had to partake.

Daily coding challenges are posted while the site interweaves some stats, socialization, and leader boards. My personal goals:

  • Complete all 25 challenges
  • Try a new language for at least one challenge

For example, the Day 3 challenge: ‘ski’ down a grid thousands of lines long and count the number of trees encountered for a specified slope…

Please check out my solutions on GitHub (all JS so far, and my solution to the Day 3 challenge) or follow along. After only three days I’ve already found it incredible revealing to see how my fellow Slalom colleagues have solved the same problem with different languages, approaches, and personal coding style.

Happy Coding!

Merry Christmas!

Happy New Year!