Joe Maller.com

Undone

That moment when you realize the quickie side project has taken too long and even though it’s close to done, you put it aside to deal with the tasks that have piled up behind it. Knowing the likihood of completing the side project diminishes with every moment it’s left undone.


Solving a difficult KenKen puzzle

That right there is the hardest KenKen puzzle I’ve ever come across. Maybe I’m just missing a strategy and there’s something obvious I overlooked, but I found the levels of ambiguity in this one to be very, very difficult to unravel. I’ve been coming back to this puzzle for months. Having finally cracked it, I wanted to document the solution. Partly to remember what happened, but mostly because it just felt so darn good to finally figure out.

With KenKen puzzles, there is no guessing. The puzzles are logical, and after doing hundreds of them over the past several years, I’ve only come across one or two that seemed to have equally forked possiibilities. And I hated those.

KenKen is similar to Sudoku, rows and columns contain n-digits with no repeats (a Latin Square). With KenKen, it can be helpful to know the sum of all digits in the puzzle’s dimension since every row and column must add up to that Triangular number. For a six digit puzzle this is 21. For this particular puzzle, it’s also worth remembering that there are only three paths to 11: {1, 4, 6}, {2, 3, 6} and {2, 4, 5}. Note the digits unique to each pathway.

Starting Out

The key to breaking into this one was column 6. Since column 6’s top cage sums to 11, and F6 is 5, the sum of D6 and E6 must equal 5. Since the only possibilities are combinations of 1, 2, 3 and 4, and E6 can’t be 1 because the sum of E5 and F5 can’t be 12, there are only three possibilities, D6: {1, 2, 3} and E6: {2, 3, 4}. Since the sum of both cages is 20 and we know 5 is accounted for, the sum of C3 through F6 must be 15. That means A5 and B5 have to add up to 6. The remaining half of that cage, B4 and C4 must add up to 7.

We now know the sum of B4 through F6, so A4 must be 3. This also reveals F3 is also 3 because the sums of all cells in the top two cages of column 3 are known.

Having a 3 in F3 means the remaining slots of that cage, F1 and F2 can only be 2 and 4. This means F4 must be 1 and F5 must be 6 because, like E6, F5 can’t be 1. Additionally, D4 and E4 must contain 4 and 6 because there’s no other way to get to 11 using a 1. The last two cells of column 4 can only be 2 and 5.

The upper left cage, A2, B1 and B2, has limited choices. Since the largest possible number is 6, the sum of any two adjacent sides can’t be less than 9. Likewise, since the largest adjacent sum is 11, neither A2 or B1 can be less than 4. The only exception is B2 which could be 3 since both adjacent cells could be 6.

But the D2, E2 cage can’t contain 3 and 4. If it did, then A2 and B2 could only be 5 and 6, which would mean B1 would have to be 4. The problem is that F1 and F2 can only be 2 or 4 and column 2’s 4 would already be taken by the 3 and 4 in D2 and E2. So, the D2, E2 cage can only be a combination of 2 and 5 or 1 and 6, the sum of A2, B2 must be 9 and B1 has to be 6.

At this point, things get hairy. I couldn’t see any obvious connection and essentially started trying alternate solutions.

A dead end

There are only two remaining combinations for reaching 11 in the A6, B6, C6 cage, but if A2 was 6 and B2 was 3, the only remaining combination would be {1, 4, 6} because the top row would already have 6, 1, and 3, leaving only a 2 or 4 as candidates in A6 except the 2 would be taken by any combination of A3, B3, B4, A5 and B5. So, from here, the top row could only be filled out one way:

That cascades down to E6. Now the D2, E2 cage has would have to be 2 or 5 because the 6 was taken by A2. But E6 couldn’t be 2 because then E5 would have to be 5 which would make E2 impossible. And here’s where this tangent falls apart all over the board. That was a long way to go to prove that A2 and B2 have to be 4 and 5.

It all comes together

Disproving that was painful, but now we’re starting to get somewhere. Confirming A2‘s and B2‘s candidates reveals C2 is 3, F2 is 2 and F1 is 4. This also limits C1‘s candidates to 2 and 5. C4 is also limited to 2 and 5, so no other cells in row C can contain a 2 or 5.

Even better, there’s now only one way to fill in the top two rows:

That pretty much gives it all away. Columns 2, 4 and 6 are quickly revealed and the remaining values are easily discovered.

The solved puzzle:

Solvers

It was interesting and humbling to run this puzzle through two KenKen solvers after finishing it by hand.

Michael Heyeck’s NekNek solver solved the puzzle instantly. Michael documented the creation of his KenKen solver, including the complete python source code (less than 150 lines with comments).

Below is the puzzle in JSON notation for the Poison Meatball solver. It was slightly reassuring that this took a few seconds to get to the answer.

{
    "width": 6,
    "height": 6,
    "values": [1, 2, 3, 4, 5, 6],
    "rules": [{
        "op": "=",
        "value": 1,
        "cells": [{"x": 0, "y": 0 }]
    }, {
        "op": "+",
        "value": 15,
        "cells": [{"x": 1, "y": 0 }, {"x": 0, "y": 1 }, {"x": 1, "y": 1 }]
    }, {
        "op": "+",
        "value": 10,
        "cells": [{"x": 2, "y": 0 }, {"x": 3, "y": 0 }, {"x": 2, "y": 1 }]
    }, {
        "op": "+",
        "value": 13,
        "cells": [{"x": 4, "y": 0 }, {"x": 3, "y": 1 }, {"x": 4, "y": 1 }, {"x": 3, "y": 2 }]
    }, {
        "op": "+",
        "value": 11,
        "cells": [{"x": 5, "y": 0 }, {"x": 5, "y": 1 }, {"x": 5, "y": 2 }]
    }, {
        "op": "+",
        "value": 13,
        "cells": [{"x": 0, "y": 2 }, {"x": 1, "y": 2 }, {"x": 0, "y": 3 }, {"x": 0, "y": 4 }]
    }, {
        "op": "+",
        "value": 11,
        "cells": [{"x": 2, "y": 2 }, {"x": 2, "y": 3 }, {"x": 2, "y": 4 }]
    }, {
        "op": "+",
        "value": 7,
        "cells": [{"x": 4, "y": 2 }, {"x": 4, "y": 3 }, {"x": 5, "y": 3 }]
    }, {
        "op": "+",
        "value": 7,
        "cells": [{"x": 1, "y": 3 }, {"x": 1, "y": 4 }]
    }, {
        "op": "+",
        "value": 11,
        "cells": [{"x": 3, "y": 3 }, {"x": 3, "y": 4 }, {"x": 3, "y": 5 }]
    }, {
        "op": "+",
        "value": 13,
        "cells": [{"x": 4, "y": 4 }, {"x": 5, "y": 4 }, {"x": 4, "y": 5 }]
    }, {
        "op": "+",
        "value": 9,
        "cells": [{"x": 0, "y": 5}, {"x": 1, "y": 5}, {"x": 2, "y": 5}]
    }, {
        "op": "=",
        "value": 5,
        "cells": [{"x": 5, "y": 5}]
    }]
}

How to Spell Hanukkah 2012

  1. Hanukkah: 53,200,000 hits.
  2. Chanukah: 8,860,000 hits.
  3. Hannukah: 1,890,000 hits.
  4. Hanuka: 1,440,000 hits.
  5. Hanukah: 1,170,000 hits.
  6. Chanuka: 989,000 hits.
  7. Chanukkah: 670,000 hits.
  8. Hanukka: 522,000 hits.
  9. Channukah: 332,000 hits.
  10. Chanukka: 323,000 hits.
  11. Xanuka: 198,000 hits.
  12. Hannuka: 134,000 hits.
  13. Hannukkah: 120,000 hits.
  14. Channuka: 46,600 hits.
  15. Hannukka: 23,500 hits.
  16. Channukkah: 18,200 hits.
  17. Channukka: 13,400 hits.
  18. Janukah: 12,800 hits.
  19. Janukkah: 9,330 hits.
  20. Chanuqa: 3,730 hits.

Hanukkah (חֲנֻכָּה) started at sundown on Saturday, December 8th, 2012. This year’s data was collected on the last day, December 16th, since early years have skewed data in the past (and it was a busy week).

My original 2005 post: 16 Ways to Spell Hanukkah.
Updated annually: 2011, 2010, 2009, 2008, 2007, 2006

Google Trends: Top five spellings since 2005

Notes on data:

I had no luck with either Google’s or Bing’s APIs this year and eventually I just decided to paste the numbers from searches. Data was collected using a Chrome Incognito session to avoid search engine personalization. I thought I might average Bing & Google’s numbers (see 2012 data sheet), but ended up using only Google’s data since their numbers were more consistent.

Updated datasource: How to Spell Hanukkah Spreadsheet


PHP Composer on shared hosting

One of my goals with PHP is to simplify and streamline my workflow as much as possible. Ideally this helps prevent wasting enormous amounts of my time on stupid crap like autoloaders, library dependencies and re-inventing the wheel.

I’m using a few libraries on IOP’s site, but as much work as these have saved, I ended up with an ugly mishmash of autoloading and require code.

Enter the Composer project.

Composer is a tool for dependency management in PHP. It allows you to declare the dependent libraries your project needs and it will install them in your project for you.

Together with Packagist, which is sort of a nascent RubyGems or PyPI equivalent, using libraries in PHP just got a whole lot cleaner. Composer even generates a complete autoloader, meaning a bunch of annoying code can be replaced with a simple composer.json file and this:

require 'vendor/autoload.php';

Except when they don’t. Because, sometimes, they won’t.

There’s always a catch, isn’t there?

The problem I ran into was the dated default PHP configuration on our shared cPanel host. Trying to run curl -s http://getcomposer.org/installer | php threw this back at me:

#!/usr/bin/env php
Some settings on your machine make Composer unable to work properly.
Make sure that you fix the issues listed below and run this script again:

The phar extension is missing.
Install it or recompile php without --disable-phar

The allow_url_fopen setting is incorrect.
Add the following to the end of your `php.ini`:
    allow_url_fopen = On

The ionCube Loader extension is incompatible with Phar files.
Remove this line (path may be different) from your `php.ini`:
    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so

* sigh * These are not settings most shared hosts grant users access to–and if you ask they’ll probably just try to upsell you a VPS. Thankfully though, many cPanel installations now allow users to select different versions of PHP (A2 does). And thankfully again, these alternate versions are often compiled with different flags.

That’s great for web pages, but Composer’s installer uses the command line. To use an alternate version of PHP in a shell, we need to know where the alternate PHP binaries are. An easy way is simply to switch the PHP Version via cPanel, then load a page containing phpinfo();. The actual PHP binary path isn’t listed, but it’s easy enough to figure out from what’s there. Mine was /opt/php/php-5.4.0/bin/php.

Once you’ve got that, you can fiddle with your $PATH (it’s searched from left to right) or just alias the alternate PHP binary:

alias php='/opt/php/php-5.4.0/bin/php'

I aliased php in my .bashrc file (reasons previously discussed) and composer installed flawlessly.


A more Git-friendly WordPress

So a few months ago I mentioned wanting to get away from WordPress and PHP. It’s not going very well.

WordPress keeps sucking me back in. A favor here, a quick job there. Next thing I know, I swear I can’t remember how to iterate an array in Ruby or Python.

While sitting down to work on a WordPress project still fills me with dread, I did recently discover a few things which slightly alleviate my misery.

My favorite, as described here by David Winter, is the ability to move the wp-content directory out of the standard WordPress hierarchy. Aside from the database, wp-content holds basically everything which makes a site unique; themes, plugins, uploads, etc. With those out of the way, all of the core WordPress application code can be removed from the site’s git repo and stored as a submodule (pulling from the WordPress GitHub mirror), making version control a lot cleaner and easier and giving me one less thing to think about.

This directory layout should really be the default. The WordPress folder ought be a sacrosanct library, only changing when the application is upgraded. The ability to move wp-content was added back in version 2.6 released in July of 2008. I wish I’d learned about this sooner.

I’m also doing something inspired by Mark Jaquith’s WordPress local dev tips which also allows me to also keep my wp-config.php file versioned and outside of the wordpress directory.

Because it’s a really bad idea to keep password files in version control, I created a wp-config-db-sample.php file containing placeholders for the database login information:

That file gets copied to wp-config-db.php, populated with the appropriate settings (and added to .gitignore), then included by changing the top of wp-config.php like this:


Cost of Adobe’s new Creative Cloud vs. Creative Suite

Adobe recently announced their new Creative Cloud software subscription service. While regular paid updates have essentially already made Creative Suite subscription software, I wanted to know if there was any cost benefit in switching our conventional CS Master Collection licenses over to Adobe’s new Cloud.

After projecting some numbers, I was disappointed by what I found.


(source spreadsheet)

Should you switch?

Starting from scratch? Yes.

Creative Cloud is clearly a smart financial move for those who don’t own any Adobe software. Buying Creative Cloud vs. a full price Creative Suite Master Collection license will save money for the foreseeable future.

Upgrading existing licenses? Erm, maybe?

For existing users, the value of Creative Cloud gets murky. It looks like Adobe set their price based on a straight transition of existing Creative Suite users to Creative Cloud. When compared to the standard Master Collection upgrade path for existing licenses on a 12-month product cycle, Adobe’s revenues are precisely maintained–with a slight tip to their favor. I believe this is shortsighted and fails to recognize the potential of growing revenues by increasing licenses.

Adobe’s Introductory offer for current CS customers ($29.99/month, for one year) ends on August 31, and taking advantage of this offer makes Creative Cloud much more compelling. With standard pricing ($49.99/month), Creative Cloud subscription costs would equal Creative Suite upgrade costs after 11 months, though the advantage sawtooths back the following month. Taking advantage of promotional pricing pushes cost-parity back to almost 4 years.

Teams and temporary workers? Probably not.

Team-ready pricing ($69.99/month) seems the most broken. Maybe there’s a cost/complexity crossover with bigger groups, but for a small office I can’t imagine any collaboration or turnover features would justify the significant additional costs.

The month-to-month price of $74.99 is unfortunate too. Paying for eight months of Creative Cloud is the same price as a year at standard prices (four months costs the same as a year at the promo rate). A small army of fine artists support themselves by freelancing as typesetters, retouchers and production artists for only part of the year. They need software, but for many studios with a distinct busy season, those licenses sit idle for half the year–effectively doubling the cost of necessary software.

Conclusion

One would think the truck-loads of money Apple is making on volume might make a compelling argument for Adobe to dramatically undercut the price of Creative Suite and push their customers towards Creative Cloud. In 2007, Steve Jobs was asked if he feared cannibalization of Mac OS by iOS. He replied that if there was to be cannibalization of Apple products, it should be by Apple. This is exactly how Adobe needs to start thinking.

Reducing the price of Creative Cloud by a third or even half would not diminish the perceived value of Adobe’s apps, but it would help dissipate the perception that Adobe’s products are impossibly expensive. This poisonous idea carries on long, long after people leave school and is partly why Adobe always tops lists of most-pirated software.

Going back to Apple as an example of doing things right, Creative Cloud should not have five price tiers (promotional, standard, team, student & teacher and monthly). The CS6 product grid is bad enough. Educational users should not be rewarded for forswearing commercial work, nor should they be financially punished when their skills are practically applied in the marketplace. The Student & Teacher price should be the only price. If Creative Cloud was simply $30/month–with no caveats–I’d recommend it without hesitation.

For Adobe’s existing customers, Creative Cloud is a slightly better deal, but disappointingly, not by much. When compared to the cost of upgrading existing software, Creative Cloud is more of an installment plan than a subscription. It costs the same, but the payments are spaced out over time.

We’ll be switching over, but with full knowledge that the monthly fees are not really saving us anything in the long run.

Other thoughts

  • Creative Cloud Mac/WinCreative Cloud appears to be platform agnostic. Being able to install on Macs and PCs would be a big plus.

  • Immediate updates sounds good, but it could also present a huge headache if a critical bug or backwards incompatibility slips through. If an update breaks an application, which has happened in the past, will Adobe offer rollbacks to previous versions?

  • Promised “community collaboration” is a potential security disaster. Having worked on projects with sensitive information, the potential for a slip-up is terrifying. Agencies should be very concerned about pre-release materials being “shared” before they’re public.

  • A lot of studios purchase every-other Creative Suite upgrade. The chart clearly shows this is cost-neutral. While there may be some benefit because known systems increase productivity and reduce training costs, Adobe’s upgrade pricing model has eliminated any cost saving from skipping versions.

    Adobe’s Creative Suite release history:

    • CS1: September, 2003 (19 months)
    • CS2: April, 2005 (25 months)
    • CS3: March, 2007 (18 months)
    • CS4: September, 2008 (19 months)
    • CS5: April, 2010 (12 months)
    • CS5.5: April, 2011 (13 months)
    • CS6: May, 2012

    In 2011, Adobe announced they had switched to an annual release cycle.


Lend me your grace and swiftness

Plenty-coups (1848–1932), last hereditary chief of the Crow Indians

“‘O Butterflies, lend me your grace and swiftness!’ I repeated, rubbing the broken wings over my pounding heart. If this would give me grace and speed I should catch many butterflies, I knew. But instead of keeping the secret I told my friends, as my grandfather knew I would. And how many, many we boys caught after that to rub over our hearts. We chased butterflies to give us endurance in running, always rubbing our breasts with their wings, asking the butterflies to give us a portion of their power. We worked very hard at this. because running is necessary both in hunting and in war. I was never the swiftest among my friends, but not many could run farther than I.”

“Is running a greater accomplishment than swimming?”

“Yes, but swimming is more fun. In all seasons of the year most men were in the rivers before sunrise. Boys had plenty of teachers here. Sometimes they were hard on us, too. They would often send us into the water to swim among cakes of floating ice, and the ice taught us to take care of our bodies. Cold toughens a man.”
Plenty-coups (1848–1932), last hereditary chief of the Crow Indians

From the book, Plenty-coups: Chief of the Crows (also Google Books, via Tuck)

Chief Plenty-coups with daughter



« Previous PageNext Page »