Creating a 150 Year Old Soap Box

Have you ever heard of ACME soap? I can’t say definitively if the company still exists, but it was a soap brand from the early 1800’s. Growing up, my grandma’s bathroom was wallpapered with ACME Soap themed wall paper. It had various advertisements, pictures, logos, etc all representing the ACME Soap brand. I have memories of looking at the various artwork while doing my business there.

One of the most memorable ones was a four panel story of a boy that falls in a well. He is holding a bar of ACME Soap, and it lathers up so much that it lifts him to the top, thus saving him. Below are the four panels as seen in the official trading cards.

When the bathroom got remodeled, each grandchild was gifted this four panel advertisement framed for us to put in our own bathrooms, which we did.

I felt that the picture frame looked a little lonely on its own, and thought that making a soap box to accompany it would be appropriate. Although not at all historically accurate, I took the dimensions of a modern soap box, and styled it appropriately.

I found a graphic that was actually used on the antique soap boxes that depicts a man holding a bar of soap. I recreated the ACME logo and added some verbiage and legal text that I could find on various images of their products. According to what I found they were founded in 1811, and the trademark was registered in 1875.

I used an old paper texture to make it look more aged.

I printed it out on card stock, cut it out, and glued it up.

Now it sits and complements the original wall paper that sits on display in the bathroom.

1 Hour Coding Challenge

I had an hour to spare, and decided that I would try challenging myself. I wanted to make a clone of Minesweeper that my kids could play. I thought it would be fun to see if I could make a fully working version of Minesweeper in one hour without any reference.

I grew up with Macintoshes, and as such never actually had a Windows machine on which I could play Minesweeper, so I know it mostly by reputation, and not hours of playing it as an adolescent.

I had a starting point that I used; my implementation of Hopeless already had a canvas and some functions to draw beveled tiles.

Working from memory, I morphed hopeless into how I pictured Minesweeper in my head. In just about an hour, I had a playable game completed. Honestly, the most complicated part of the game is uncovering blank tiles when you click on them. I made a recursive function to do that, which at first was very inefficient and took too long!

With my playable game completed within the time limit, it was time to score myself on how it turned out.

While the basics of the game were correct, I got the look completely wrong! I made the tiles raised after being clicked. Thinking about it after the fact, it made sense that the buttons would be raised until clicked. I also got the colors wrong, as well as the size of the fields/number of mines. I didn’t mind these issues, so I showed it to my wife who spent a lot more time playing Minesweeper growing up. She was annoyed at the discrepancies.

So I spent another hour or two cleaning it up and making it more true to the original. This included more accurate colors, correcting the beveled blocks, making the same difficulty options, and also adding the ability to click on already-revealed numbers and having it automatically toggle it’s neighbors if the mine conditions had been met. This was actually a feature I didn’t know about!

So in the end, I think I ended up with a pretty good representation of Minesweeper.

Why would I bother doing this though? Aren’t there plenty of places to play this game already? Well, yes. One of the reasons I make the simple games I do is because I grow frustrated by free apps available on the iPhone and on websites that are laden with ads. Sometimes I want to show my kids a game, and not have the annoyance of ads.

It can also just be a fun challenge. I enjoyed doing this and am quite happy with the result. Please feel free to play it here!

Project Euler 174

We shall define a square lamina to be a square outline with a square “hole” so that the shape possesses vertical and horizontal symmetry.

Given eight tiles it is possible to form a lamina in only one way: 3 × 3 square with a 1 × 1 hole in the middle. However, using thirty-two tiles it is possible to form two distinct laminae. If t represents the number of tiles used, we shall say that t = 8 is type L(1) and t = 32 is type L(2).

Let N(n) be the number of t <= 1000000 such that t is type L(n); for example, N(15) = 832.

What is sum of N(n) for n=1 to 10?

This question turned out to be fairly straight forward, and is solvable using a brute force method.

Basically, we want to arrange tiles in laminae that are symmetrical, and don’t use more than 1,000,000 tiles. The largest lamina we can arrange would then be 250,000 tiles per side, with a wall thickness of 1.

The way I set this up was to iterate through all lamina side lengths (L) from 3 to our limit, 250,000. Then, for each, iterate for different hole sizes (H) in the middle from L–2 down to 1. (The evenness of L and H have to match.)

Calculating the number of tiles is an easy prospect; t = L² – H². A dictionary then keeps track of how many tiles are used for each combination. Once we’ve brute forced all the combinations, look through the dictionary to count up all the tile values that have 10 solutions or less!

let history = {};
let limit = 1000000;

for (let L=3; L<250000; L++){
    let L2 = L * L;
    // Hole (H) size must be at least 1, smaller than or equal to l-2
    for (let H=0; H<=L-2; H++){
        // Calculate number of tiles (t) in lamina
        let t = L2 - (H * H);

        // L and H evenness must match
        if (L%2 != H%2) continue;
        
        // Ignore answers over limit
        if (t > limit) continue;

        // Store result in history
        if (history[t] == undefined)
            history[t] = [];

        history[t].push(L);
    }
}

let count = 0
for (let i in history)
    if (history[i].length <= 10)
        count++;

console.log(count);

The first time I ran this, it was much slower than anticipated. I let it run overnight, and was happy to see the correct result when I checked on it the next day. I wondered what I needed to optimize to make it run better. It turns out that I had typed the upper limit, L, as 2,500,000! By decreasing that to the proper value, that reduced the compute time to 17 seconds.

I was able to find one more low-hanging optimization opportunity. By iterating through the H values from largest to smallest, the number of tiles, t, would increase. Once that value got over the 1,000,000 limit, I can break out of the loop, and go to the next value of L. This saves a lot of time computing out of bounds answers!

for (let L=3; L<250000; L++){
    let L2 = L * L;
    // Hole (H) size must be at least 1, smaller than or equal to l-2
    for (let H=L-2; H>1; H-=2){
        // Calculate number of tiles (t) in lamina
        let t = L2 - (H * H);

        // Break once we get over limit
        if (t > limit) break;

        // Store result in history
        if (history[t] == undefined)
            history[t] = [];

        history[t].push(L); 
    } 
}

This optimization pushed the compute time down to .278s! That’s a very reasonable time for Project Euler.

© 2007-2015 Michael Caldwell