Friday, November 01, 2013

New Home

I've been actively developing a new blogging engine titled Dinghy, designed to work with Google App Engine. I'm using it to host my new Blog, Stories for Outcasts, which is also included on the "feeds worth following" widget here.

This blog will remain up, as it still generates plenty of traffic, particularly from some oddball search topics such as Roman numerals and mainframe arcana, and I will add major announcements here occasionally, but "Medicine for the Sky" will be largely inactive.

Oh, speaking of major announcements, about 7 weeks ago, my daughter Emrys was born, bringing the total in our brood to 4 girls!

Sunday, August 25, 2013

Translucent text on a Bootstrap 3 cover image

I'm close to debuting a lightweight blogging engine using Go, App Engine, and Bootstrap 3, and I wanted to share a quick solution I found to what seems to be a common problem: putting text on top of a cover image without contrast problems, and without having to explicitly line up a translucent background color with the parent div's corners.

In this case, I'm using a simple Bootstrap 3 jumbotron with a background image declared with the css "background-image: url()" syntax. The jumbotron div has a child H1 element with a sample blog name ("Stories for Outcasts", which I thought was pretty funny, but [probably] won't be the final blog name I choose).

The background image is of my Tom Baker Dr. Who action figure peering at some API or other I was toying with on my laptop. It's mainly a dark image, so I chose white for the superimposed text. Here's the HTML stub:

<!DOCTYPE html>
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <meta charset="utf-8">
 <link href="Blog_files/bootstrap.min.css" rel="stylesheet">

 <style type="text/css">
  #cover {
   background-size: 100% auto;
   background-image: url(static/cover.jpg);
   margin-top: -20px;

  #cover h1 {
   color: #fff;
 <div class="container col-md-8">
  <div id="cover" class="jumbotron">
   <h1 class="text-center">Stories for Outcasts</h1>

...and what the result looks like:

Friday, July 19, 2013

Minimum wage isn't a living wage

I stopped making minimum wage in 1991, when I was 20 years old. I was working for Donatos pizza at $4.25 per hour as "inside help", a position typically reserved for part-time highschool workers. My car was donated to me by my grandmother, as I couldn't afford a car payment, and she wanted to help me out. I shared an apartment with a friend from a previous job, Steve, and the two of us scraped by, kept our $435/month rent more or less paid on time, ate a lot of pizza at work to curb the grocery bill, and played a lot of Zelda in lieu of entertainment requiring cash.

I look back on that time fondly, but I was close to poverty, and wouldn't have been able to manage without the free car, living in a time where filling a car's gas tank cost just $10, and having a co-conspirator to share expenses with. If I'd have gotten sick, it would have been very problematic for both of us; I had no health insurance at all, and I couldn't afford to miss any work. If my car had broken down, I would have been running back to family for help to get back on my feet.

I was lucky, though, in that the pizza store noticed my quickly improving skills and work ethic, and offered me a position in management. A couple months after that, I leveraged the extra cash that position brought into my own apartment, (Steve ended up moving back to his hometown of Youngstown, settling affairs after his ex-wife died, and trying to build a good life for his son - that story deserves a better treatment, and provided Steve doesn't object, I'd like to tell it from my point of view some day) where I slowly accumulated furniture, a stereo, a set of books I'd been meaning to get to some day, and a modest cash reserve for car repairs, doctor bills and whatnot. The management job came with a 45 hour work week (minimum), a week of vacation, insurance, and a small monthly bonus if the store hit it's "numbers". Most of that is laughable by the standards of a software developer, but at the time I felt like I was living it large.

Tuesday, May 28, 2013

First impressions of WordPress

For reasons that may become significant, I began my first install of WordPress yesterday evening. My install was under CygWin, and most of the challenge was getting WP's dependencies met, PHP being the most frustrating. Eventually I found apt-cyg and, both from Victor Miti's excellent primer Installing and Configuring Apache, PHP & MySQL on Cygwin, which had most of what I needed.

After getting Apache2, MySQL, and PHP working, the WP install itself was a breeze, and the content management features seemed straightforward and mature out of the box. On day 2, I've stumbled onto the WordPress Console plugin, and the P2 theme, both being fairly snazzy:

I can see from this brief exposure, and from an interview with a VideoPress developer, why they have such a thriving community. Good stuff all around, folks... whether or not you end up hiring me.

Tuesday, May 14, 2013

Ignoring the tyranny of official widgets

...and a small explanation of why that's important to me.

In 2009 I became immersed in the world of check image files, often referred to as "Check 21" files, in reference to the Check Clearing for the 21st Century Act, which gives a scanned image of a check legal credibility as a financial instrument. In our modern world of online bill pay, web 2.0, and pizza boys with credit card scanners that plug into their mobile phones, paying utility bills by mailing a check is slowly becoming anachronistic... or so you might think.

In reality, over 300,000 physical checks per month get mailed to our Canton remittance center, many from businesses with multi-thousand dollar electric bills - businesses large enough to employ an IT department to do ACH transactions, wire payments, what have you. But the physical checks keep being printed and mailed, for much the same reason that companies that have ever used a mainframe continue to use them despite the cool kids shouting "dinosaur!" or "RESTful!" or "node.js!!" at them: It's well understood and works reliably.

Tuesday, April 30, 2013

Base Eighteen on a Chinese Abacus

For the sake of simplicity, my use here of number words (ten, hundred) instead of digits (10, 100) will refer to decimal values. "Ten" =

I've been interested in arithmetic on the abacus for a while now, although I'm still quite the amateur. Last year I wrote a (not yet officially adopted) plugin to the Khan Academy Exercises engine to allow practice exercises on a 4x1 soroban, which helped me improve my speed and accuracy with basic addition, and I've acquired these two real-world abaci:

The top abacus is a cheap Chinese 5x2 Suanpan I bought in Chicago's Chinatown a few years back when my wife and I vacationed there, and the bottom abacus is a better quality Japanese 4x1 Soroban that Liberty ordered for me as a Christmas present last year (along with a book on the Haskell programming language I've been wanting - best wife ever!). "Suanpan" and "Soroban" are language variants on the same word, which roughly translates to English as "counting tray", and neither name implies a specific number of beads.

Monday, April 08, 2013

Stripping a UTF-8 byte order mark with Go

Recently I've been watching some videos on the Go programming language, and I was impressed enough to go install it and start tinkering. Right out of the gate, I ran into trouble getting the code on's first page working locally. The code is simply:

Google's goal in this case seems to be illustrating to seasoned coders on their first visit that the language has UTF-8 support built-in. Notepad on Windows 7 does display CJK characters correctly out of the box, without needing to play around with language options in the control panel. It also lets you save files in a few unicode-friendly formats, one of which is UTF-8. Unfortunately, Notepad always writes a byte-order mark (BOM) at the beginning of files saved in UTF-8 format, and this can't be disabled:

The UTF-8 standard is ambiguous about whether the BOM should be accepted in all cases, but regardless of how you read the standard, the Go compiler does not support them, and throws this error when I attempt to compile the same program:

Saturday, March 23, 2013

Screen-scraping a .NET site with App Engine/Java

My impetus for developing this was the desire to populate a hidden page on my blog with live data from a pair of funds, namely an ebay merchant account used as a rollover fund for donations, and a 529 account from an Ohio provider.

There is an excellent API for ebay merchant accounts that I was able to integrate quickly with App Engine. The blog page performs a poor man's AJAX call to an servlet, which in turn queries the ebay API for a current balance, and in the end the dollar amount is returned to the blogspot XMLHttpRequest, where a simple DOM .innerHTML replace populates the browser window with the balance. Here's a quick rundown of the code:

Blogger hooks

Rollover account balance: <span id="pcfBalance">??</span><br />
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
  if(xmlhttp.readyState == 4){
    document.getElementById('pcfBalance').innerHTML = xmlhttp.responseText;
};"GET","http://[my application]",true);

App Engine servlet

Wednesday, March 13, 2013

Why Sheffer's Stroke is NAND instead of NOR

As a young boy, diving into mathematics was a great release for me. I often manipulated numbers in my head, independently discovered cross-multiplication, and found the gradeschool introduction to logic fascinating. Logic, of course, one needs to understand intuitively in order to be an effective coder.

Famous science personalities were my heroes. From Newton himself playing with equations of planetary motion in his giant Principia tome, to Godel showing with marvelous simplicity that all mathematical investigation will be (hopelessly?) incomplete, to Hoffstadter's work on artificial intelligence (and from whom I first heard the word "meme"), to Feynman picking locks at Los Alamos for kicks and investigating what he found interesting with little regard to its future practical value.

These were the giants to be revered, the Atlases holding the world on their shoulders. If only we could all be like them, forgoing our petty disagreements, cults of personality, and clanishness... or so I thought. Later when I realized that the science and maths world contained all of these things, it was quite disillusioning. Yes, even the greats stepped on each other's work, stole each other's credit, and disagreed on basic notation and phraseology of important concepts, particularly as a new field was being developed.

"Sheffer's Stroke" is an example of this kind of thing. Denoted by "|" (or "pipe" as we techies call it), in modern notation it refers to the logical NAND function. a|b is true in all cases where a and b are not both true. However, Henry Sheffer explicitly refers to his proposed function as "neither-nor", false in all cases where a and b are not both false. In his 1913 paper "A set of five independent postulates for Boolean algebras, with application to logical constants", he has this to say:

Thursday, February 28, 2013

HTML5 logic circuit builder using NAND gates

This blog entry won't serve as an introduction to Boolean Algebra or logic gates, but rather just to illustrate an HTML5 widget I wrote that lets you manipulate NAND gates. In fact, before you begin, you should understand what these tables mean:

NOR = f(a,b)    NAND = f(a,b)
a b  f           a b  f      
0 0  1           0 0  1      
0 1  0           0 1  1      
1 0  0           1 0  1      
1 1  0           1 1  0      

If that makes no sense, start with this Wikipedia article on logic gates.

In the early 20th century, the maths world went wild trying to expand on George Boole's work on logic. Ernst Schröder, Edward Huntington, and Alfred Whitehead each developed conflicting notation systems and postulate sets, each with published works that were pretty arcane. For instance:

Tuesday, February 05, 2013

Tax tables from 1998 to 2013 at a glance

The form below is the result of combing through PDF files from to get an accurate picture of how federal payroll withholding tables changed through the years. I later tacked on tax tables to compare with the payroll tables to see how they lined up (which they do pretty well... with a couple exceptions that I'll get to). I've populated data from the years 1998 to 2013, and added a simple HTML5 interface for charting the results.

Choose a salary from the slider (if you don't see a slider control, the charts won't work with your browser - the HTML5 "range" input type currently only works in Webkit browsers and Opera), and then click married or single, to see the chart for that salary.

The code makes some basic assumptions for the sake of simplicity. First, the salary is taxable income, after other deductions such as 401k, social security, etc. Second, the tax line adjusts the salary down by the standard deduction (twice that for the "married" category, assuming "married filing jointly" is the filing status), where the withholding line does not. This appears to be the intent of the descrepencies between withholding and tax tables, that is, separating what your employer knows about you from what the government does. Your employer doesn't know about your mortgage interest, whether you'll file joint or separately, whether the child tax credit applies to you, how much you spent for college tuition, or any of the hundreds of other deductions or credits you'll talk to Uncle Sam about. They know what you contribute to 401k, how many dependants you intend to claim, and that's about it.

Tuesday, January 15, 2013


So Scout and I stopped into the grocery store to buy a couple extra things for her lunch. We got to the checkout area, and decided to use a real lane instead of self-serve, since cashiers are much nicer to me when I have Scout in tow. (When I'm alone, it's self-serve only, unless the guy who looks like he just got out of prison is on duty at my local Kroger, he's alright.)

"Do you have your Kroger card?"

"No, but here, let me type in the number." I grabbed the giant rubber stylus, and poked at the "Alt ID" button, heard the reassuring click... and then nothing. So I poked at it a couple more times, and noticed that the button on the opposite side was occasionally gaining focus, and the language kept switching back and forth between Spanish and English.

"Oh, looks like your touch-screen is misaligned..." she mashed some buttons on the register, "...or something, you should probably shut this lane down until that gets re..."

"Try it now," she interrupted. Poke, poke, poke... Hello, Hola, Hello. Same thing.

Friday, January 04, 2013

Manhandling Gentran for fun and profit

About 10am on Wednesday, an instant message window pops up on my workstation, from my buddy and coworker Jim. "Hey, you see all those Gentran errors?"

"Ah crap," I thought, "there goes my day."

I work as a software developer, but in a specialized role: my group writes software to support a production electronic commerce and energy trading system, fitting it with new regulatory requirements, feeds to new vendors, retrofitting logging and administrataion solutions, and our current nightmare, making our code compatible with new vendor frameworks, and migrating it en masse. (Vendor lock-in, in my opinion, is the biggest scam played out on American businesses, and 9 years of bellyaching about that in my job has netted me very few victories.)

In short, I write code, but for the purpose of keeping an enterprise integration system running. In my group, we rotate who is assigned for "production support", where you try to work on your coding tasks as you can, but when there are any hiccups in the system, you're suddenly in a system admin role instead, complete with (justifiably) panicked business users worrying about the status of their million dollar wire transfer, or avoiding regulatory fines for processing data late, etc.

Tuesday, December 25, 2012

Pufftygraph, an HTML5 Spirograph with touch-driven gears

First, thank you, now defunct Kenner, for the most excellent Spirograph toy. I had a Kenner 401 Spirograph set as a boy, and I fondly remember the joy of trying to drive the gears with a pen, and watching as the hidden shapes were revealed.

About a year back, I did some searches for online spirograph apps, thinking little Scout, then 6 years old, would enjoy it. I found some nice sites talking about how hypotrochoid math works, a complete listing of the gear ratios of one of the Kenner 401 set with close-up images of each gear, and several Flash, java, and HTML5 apps to draw hypotrochoids with given gear ratio inputs. However, nowhere did I find an app that showed the gears move as you drew, which as far as I was concerned was the main draw.

I decided that was a perfect excuse to brush up on my HTML5 animation skills, and within a few days I had code that would draw actual gears that followed mouse movements or touch gestures, drawing a hypotrochoid in its wake. I added the necessary elements to let it function as a smartphone web app, posted it here, and showed it to my daughter Scout, who thought it was a fun enough idle amusement for a minute or two, but since it could only make the one shape, didn't have much replay value.

I shelved the code and moved onto other things, but late this year I returned to the app and spruced it up some, and presented it to Scout under the title Pufftygraph ("Puff" is one of her nicknames) as one of her official Christmas presents. She and her mom enjoyed playing with it while Christmas cookies were in the oven, and it seemed to be a big hit with both of them. Here's an example of a drawing it can produce now:

Tuesday, November 27, 2012

iPhone multi-touch events and braille-like input

Below is a quick demo of me "typing" a short phrase and some numbers using a modified version of my Blind Input iPhone web app. This is a proof of concept app that doesn't integrate into the phone's other text entry forms, and is arguably more difficult to learn than braille. In case it appears I've solved some great accessibility problem, Siri and the iPhone's native accessibility features has me beat in spades, and my app is only an interesting idea I wanted to experiment with.

Monday, November 12, 2012

The math behind HTML5 context transforms

If you've drawn widgets with HTML5 canvases, you've no doubt come across such methods as ctx.translate(x, y), ctx.scale(x, y), and ctx.rotate(radians). These are all convenience methods for ctx.transform(a, b, c, d, e, f), which applies a generic affine transform to the canvas. Consulting the specs will show that the a-f variables refer to this transformation matrix:

If this looks incomprehensible, it might help to express the matrix in basic Algebraic terms:

 x' = ax + cy + e, and
 y' = bx + dy + f

Sunday, November 04, 2012

Simple Javascript RGB/HSV converter

This is a simple and straightforward converter between RGB and HSV values, with RGBs from 0 - 255 and HSV values with hue from 0 - 359 and S/V from 0 - 1. I wrote it for an as yet unfinished HTML5 red-eye correction tool, but I'll be unable to devote much time to side-projects until after the holidays, so I thought I'd put this up now in case someone found it useful.


function getHSV(r, g, b) {
  var h, s, v, max, delta;

  // v (value) is the highest of the RGB values scaled to [0-1]
  max = Math.max(r, Math.max(g, b));
  if (max == 0) return [0, 0, 0];
  v = max / 255;

  // delta is the difference between the largest and smallest of RGB
  delta = max - Math.min(r, Math.min(g, b));
  if (delta == 0) return [0, 0, v]; // No delta = grey, only v is significant

  // s (saturation) is delta divided by max
  s = delta / max;

  // h (hue) is a number in degrees describing the color's angle on the hsv color wheel
  if      (r == max) h =     (g - b) / delta;
  else if (g == max) h = 2 + (b - r) / delta;
  else if (b == max) h = 4 + (r - g) / delta;

  // convert hue to degrees
  if (h < 0) h += 6;
  h *= 60;

  return [h, s, v];

function getRGB(h, s, v) {
  var quadrant, max, mid, min, fraction;
  max = Math.round(v * 255);
  if( s == 0 ) return ([max, max, max]); // Greys

  // Quadrant is between 0 and 5, where 0, 2, and 4 are red, green, and blue
  h /= 60;
  quadrant = Math.floor(h);

  // fraction is distance away from quadrant representing hue's primary color
  fraction = (quadrant % 2 == 0) ? (1 - h % 1) : h % 1;

  // min and mid are the smaller two RGB colors in the final return array
  // We don't know what primary colors they represent...
  min = Math.round(max * ( 1 - s ));
  mid = Math.round(max * ( 1 - s * fraction ));

  // ...until we check what quadrant we're in
  switch (quadrant) {
    // reds
    case 5: return [max, min, mid];
    case 0: return [max, mid, min];
    // greens
    case 1: return [mid, max, min];
    case 2: return [min, max, mid];
    // blues
    case 3: return [min, mid, max];
    case 4: return [mid, min, max];

Thursday, October 11, 2012

Internet Explorer rendering issue fixed

I noticed today that viewing this site in IE blew things up. This was due mainly to putting javascript source for HTML5 canvas operations above the fold in a couple of blog entries.

I fixed that, so the page should look normal to IE users... however, you're missing out. Use an HTML5-capable browser instead to get the full gist of what I've been working on lately. And also the cool pacman banner.

In other news, Adelaide turns one year old on Sunday! Here she is with her sister Scout, the person who has given Liberty and I the most help with the baby, and who is possibly the most loving and patient sister a baby could have. I love them both more than I can say... but I'll keep trying anyway.

Sunday, July 29, 2012

Counting Squares

NPR's "Science Friday" posted a square-counting puzzle on their Facebook page yesterday, and a friend of mine challenged me to write a program to count them, hopefully coming up with the same answer (40) that we did with a manual count.

My first pass is a generalized (more or less) solution where different sized boards can be created with arbitrary horizontal or vertical lines. It's not the most solid thing I've ever written, doesn't take user inputs or validate the hardcoded input, but it illustrates a simple, brute-force attack of the problem.

This requires an HTML5-capable browser (Chrome, Firefox, Safari), and should start counting 5 seconds after loading.

Tuesday, July 10, 2012

Dear Scout

So Scout's father moved to California, and this weekend I flew her out to see him, where she'll stay until just before school starts. Combine missing a girl I love with my recent dive into cryptography, and the natural outcome is, of course, to write her a letter - in secret code!

When I was in high school, I had the idea to write a substitution cipher using symbols for letters. My code consisted of squares, circles, triangles, stars, horizontal, vertical, and diagonal lines, plus and equals signs, and some other unique but easy to draw symbols that the intervening 25 years has wiped from my memory. I used it to write a letter of no particular consequence to my friend Rachel (actually she was my friend Bill's friend, who I poached for purposes of odd geeky stuff like inventing strategy games to play and reviewing her early short stories), and she decoded it with little effort, predictable given her intelligence. What made it pretty straightforward to decode was context. I had formatted the letter like a letter, complete with spaces between words, and the encoded greeting "Dear Rachel" which let her immediately translate the 7 letters a, c, d, e, h, l, and r. Since "a" was included, a lone "I" was easy to translate, and then the rest could be filled in with a style akin to Sudoku, filling in words that were mostly complete already, and adding the newly translated letters to other words.

I wanted to do something like that for Scout, but I thought of a symbol set that would be both easy to write a program for, and comprise 26 letters and 10 digits: pairs of dice. Each die face could have a value of 1 through 6, giving 36 possibilities for a pair. I didn't want the code to be as easy as iterating through the alphabet and replacing 1.1 with a, 1.2 with b, etc., but at the same time I didn't want it to be so complex as to be off-putting for a 7 year old. It eventually ocurred to me that "Dear Scout" was an even better greeting than Rachel's, as it had no overlapping letters. If I kept the cipher alphabetized, but pulled "Dear Scout" to the beginning of the cipher, then the greeting would look like this:

Saturday, July 07, 2012

Encryption, part 2: Elgamal and the Discrete Logarithm

In my quest to better understand the mechanics of encryption, I've found the Elgamal method the hardest to get my head around. The problem was not that the underlying math is difficult, it was that I didn't know some of the background terminology (cyclic group, congruence class, group isomorphism), the various explanations online all used different variables, and made references to "mathy" things it was supposed the reader was already familiar with. Lastly, the articles on discrete logs and Elgamal encryption on my go-to site for techie info, Wikipedia, were a hot mess, mistaking modular multiplicative inverse for division, and leaving out crucial middle steps (how to get from "collect underpants" to "profit", as it were). The whole affair really shook my faith in using Wikipedia as a trusted source for tech info.

A relatively simple explanation is this: You and your buddy both have a secret that combines to form an encryption key. To encrypt a message, multiply the key by the message value, divide by a modulus, and the remainder is your ciphertext. To decrypt, multiply the ciphertext by the key's inverse, and, again, divide by the modulus, and the remainder is the original message. Fin.

There is, naturally, some math involved, most of it geared around how to build the secret key so only you and your buddy know it, without either of you revealing your part of the secret. Let's start with some of the basic terminology, then get into the mechanics of building the encryption key.

Thursday, June 28, 2012

RSA encryption and the other Sun Tzu


Before we get started on how exactly RSA works and how it's related to Chinese mathematicians, it's important to have a basic comprehension of modular arithmetic, totients, and the "modular multiplicative inverse". None of these are very difficult, but they aren't commonly talked about, so here's a quick refresher:


In simplest terms, what you're looking for in a modular problem is the remainder of a division. Dividing 7 by 3 gives 2 with a remainder of 1. Expressed as a modular equation, 3 is the modulus, and 7 and 1 are congruent. The equation can be expressed like this:

7 ≡ 1 (mod 3)

Wednesday, June 13, 2012

Four ways to construct a pentagon

There are animations of the 4 compass and straightedge construction techniques at the bottom of this entry, but they require an HTML5 capable browser. (I suggest Chrome, but the animations should work with a modern Firefox, Safari, or Chromium... but let me know if they don't.)

Also included are animations of the first 6 "problems" in book 1 of Euclid's Elements, as a preview of a larger project I'm working on, and two variations on creating a heptadecagon (a seventeen-sided polygon).

Over the last few weeks I've been spending what free time I have obsessing over the odd mathematics of Argand diagrams, complex roots, and how they relate to constructing regular polygons with a compass and straightedge. I found, among other things, that I had forgotten quite a bit from my trig and geometry classes from 25 years ago.

Friday, May 18, 2012

Compass and Straightedge geometry meets HTML5

This is a proof of concept build of an HTML5 engine to perform classical Greek compass and straightedge calculations, as described in this Wikipedia article. In brief, an initial set of points can be created, and then points can be connected by lines, circles can be drawn with one point as center and another as one point in the circumference, and finally the points where circles and/or lines intersect can be added as new points. With those simple rules, angles and line segments can be bisected, and certain regular (equilateral) shapes can be created.

I have created a rudimentary language to describe the adding of points, lines, and circles, and finding their intersections, which I discuss briefly after the demo below. Without further ado, choose a sample "program" to run to bisect an angle or create a regular shape. If you're a fan of Gauss, be sure to check out the heptadecagon.

Thursday, May 10, 2012

Animated prime number machine

This uses the HTML5 canvas architecture, so no IE8 or less; sorry. I have only tested it with Google Chrome, so it may not work in other HTML5-capable browsers. If you find this to be the case, please leave feedback with any errors you see, and what browser version you're using, and I'll see what I can do to get it working for you.

The principle of the prime number machine is of rolling coins and elevators. I created this because I thought it would be neat to have a way for prime numbers to be produced by a set of mechanical rules rather than with pure mathematical methods. Here is a basic description of the rules:

  • If a coin rolls into an empty box, it creates an elevator with the height shown on the coin, and a new empty box appears.
  • If a coin hits the top or bottom of an existing elevator, it bounces off with no effect.
  • The coin's number increments after each cycle
  • The elevators go down a floor during each cycle until the top car is flush with the ground line, then they begin going back up to where they started.

This results in two basic phenomena: All new elevators correspond to prime numbers. When a coin does not have a prime number on it, all of the elevators corresponding to the coin's prime factors have a car flush with the ground.