Hardware: MARK-13 Thursday Music

Just discovered that iTunes Store [mdh 2023: defunct link] has Hardware (Richard Stanley, 1990) for $9.99 in HD! Blu-Ray is out of print, DVD was a trash VHS port. Best punk rock SF apocalypse flick. "It's horrible, I love it!"

One rewatch later…

Hardware looks even more prophetic now than when young cyberpunk Mark would watch the VHS over and over on a shitty CRT. Get used to the world of ecological disaster, locked into your apt by security systems installed by panopticon-watching perverts, terrorists with trucks smashing open buildings, people squatting & scavenging in the ruins. When a billion people near the uninhabitable equator starve and try to migrate away from global warming, you think anyone's gonna take them in? Or will we just irradiate the planet fighting wars, sterilize the mutant population, and let Google's autonomous killer robots knock us down to carrying capacity? I never believed in a future, and here it is.

… So, that went a little dark. Have a drink, a joint, a fuck, make some art, and play some cute distracting videogames to forget about the end of the world.

The soundtrack's another OOP classic, but here's the day's music based on it:

On the Use of Communications Networks of Tin Cans and String

Gen-X (remember us? I suppose not.) invented l33tspeek but knew when to stop doing it. Now, "old people" use ellipses… and end texts with a period, and it makes the Millennials upset.

Back in the day, all we had were tin cans & string, er, BBS's, which were like Thunderdome without the sense of fair play, but we also tolerated much weirder behavior, and at worst you couldn't call back to one board in your city. Now if you say anything any one of the kiddie mafia doesn't like, they all have a toddler meltdown at you, over the tin can network we built.

I don't have a solution for any of this, just kicking out Tiny Tim's crutches and laughing at him, as one does this season.

Advent of Code 2017: Week 1

After 7 days, let's see how my Advent of Code 2017 is going.

  • Web framework: I made a standard web console, which I then copy forward to the next day. I could just as easily have put all the buttons on a single page, but it'd get too long by day 31.

  • Unit testing: As seen in stdlib.js, my test framework is very simple: On page load, setup, run some asserts, finish to get stats and redbar/greenbar the test console. This has been a great win, even though several of the days had only one or two examples.

  • 01:

    "The captcha requires you to review a sequence of digits (your puzzle input) and find the sum of all digits that match the next digit in the list. The list is circular, so the digit after the last digit is the first digit in the list."

    • So this is nice and easy, linear problem for JS string processing. On the second variant I turned the inner function to pick the next char into a function, which I pass in. No external state.
  • 02:

    "The spreadsheet consists of rows of apparently-random numbers. To make sure the recovery process is on the right track, they need you to calculate the spreadsheet's checksum. For each row, determine the difference between the largest value and the smallest value; the checksum is the sum of all of these differences."

    • Needed to write more utils, this time to process strings into a table of numbers. My first solution kept it as a table of strings, and then I had problems with JS type coercion. Same strategy of finding a pure functional inner loop and extracting that as a function. Actually, subtotalFunc1 mutates cols, but you'll never use it again so it doesn't matter.
  • 03:

    "Each square on the grid is allocated in a spiral pattern starting at a location marked 1 and then counting up while spiraling outward. For example, the first few squares are allocated like this:

    17 16 15 14 13
    18 5 4 3 12
    19 6 1 2 11
    20 7 8 9 10
    21 22 23---> ...

    While this is very space-efficient (no squares are skipped), requested data must be carried back to square 1 (the location of the only access port for this memory system) by programs that can only move up, down, left, or right. They always take the shortest path: the Manhattan Distance between the location of the data and square 1."

    • This was a little insane. There's apparently a pure math solution, but I am not a mathematician, I am a turtle; also song; also Lewis Carroll; also Gödel Escher Bach. So I solved it by moving a turtle around the spiral, turning left whenever there's an open space, and then I could just examine the spiral for values.
    • Yes, I store points as a vector-2 of numbers, rather than making a "Point" class with x,y. In C using a struct makes more sense (since it only takes 8 bytes intead of the 40+ in any object system!), but in anything else, the vector requires the least memory, least work, and is easiest to serialize, use as a hashtable key, and so on.
    • I just copy-pasted and modified for the second task, instead of making a nice inner function to pass in. It's not incredibly hard to parameterize, but I would need to break out of that inner function to return early, so probably using an exception for flow control?
    • Javascript objects are super-useful, like Python dicts but even easier to use. Stuff a bunch of points for the grid, and properties for the minPt, maxPt (bounds) and lastPt, one structure gets to hold everything about the spiral. Writing this in a type-safe or pure functional language would be annoying.
  • 04:

    "A passphrase consists of a series of words (lowercase letters) separated by spaces.
    To ensure security, a valid passphrase must contain no duplicate words."

    • Super simple, a histogram that only counts to 1. The second part only requires sorting the chars in each word, so you can check they aren't anagrams. I was worried that day 3 was the start of an exponential curve in difficulty, so by the end it'd take to the end of the Earth to finish.
  • 05:

    "The message includes a list of the offsets for each jump. Jumps are relative: -1 moves to the previous instruction, and 2 skips the next one. Start at the first instruction in the list. The goal is to follow the jumps until one leads outside the list.
    In addition, these instructions are a little strange; after each jump, the offset of that instruction increases by 1. So, if you come across an offset of 3, you would move three instructions forward, but change it to a 4 for the next time it is encountered.
    How many steps does it take to reach the exit?"

    • I returned the program counter at first, and that passes the sample data test, so I "guessed" wrong the first time, but then reread and found my bug. Having only one example is a problem. Both parts are as usual solved by passing in a function to determine the next state of the instruction. Trivial one aside from my stupid bug.
    • I'm building up a good library of tools by now.
  • 06:

    "In each cycle, it finds the memory bank with the most blocks (ties won by the lowest-numbered memory bank) and redistributes those blocks among the banks. To do this, it removes all of the blocks from the selected bank, then moves to the next (by index) memory bank and inserts one of the blocks. It continues doing this until it runs out of blocks; if it reaches the last memory bank, it wraps around to the first one.
    The debugger would like to know how many redistributions can be done before a blocks-in-banks configuration is produced that has been seen before."

    • Making the balancer was straightforward, I stored each state as a string in a history array, and a parallel histogram to catch the duplicate; I could get rid of hist but it turned out to make the second task easier.
  • 07: (Don't read this or the code until tomorrow if you don't want a spoiler)

    "You offer to help, but first you need to understand the structure of these towers. You ask each program to yell out their name, their weight, and (if they're holding a disc) the names of the programs immediately above them balancing on that disc. You write this information down (your puzzle input). Unfortunately, in their panic, they don't do this in an orderly fashion; by the time you're done, you're not sure which program gave which information.
    Before you're ready to help them, you need to make sure your information is correct. What is the name of the bottom program?"

    • Building the tree was a good puzzle, but not hard: Parse the text into nodes, keep them in a dictionary, then build the structure, and return the only parentless node (the root). Making a recursive toString so I could debug it was important…
    • Second task looked to be tedious (depth-first search and pass the result all the way up), but then I just looked at my output and saw the unbalanced numbers, so entered it by hand. I am a computer, too.

I've got both gold stars each day. I'm completely incapable of reliably checking in at exactly 21:00 PST, and I'm too fussy about my code to ever be "the fastest", so my rankings are awful; maybe it ought to count from when you read the problem set, but then everyone would cheat on at least the first task.

Advent of Code 2017

I've joined the Advent of Code, and I'll be doing it in JS. Got my 2 stars for the day.

For good discipline (or as a handicap), I'm building a halfway-decent set of pages, unit testing framework, and sort of doing things right (good ES6 practices) instead of easy (hack some inline JS in compatibility mode). I'll link it in the sidebar tomorrow, when challenge 1 expires: My Advent of Code

Go on and do it yourself! I say "easy mode is for babies" and make it hard on myself, but really you can do this in anything. There's a perfectly nice Chipmunk BASIC or FreePascal if you're old-school.

Note: The leaderboard reset time is ridiculous, and I don't care about speed-coding or leaderboards. Don't stress about competing for first 100 completions, just do the thing.

Animal Crossing: Pocket Camp

On December, 2005, Animal Crossing: Wild World (AC:WW) came out for the Nintendo DS, I immediately got it, created a town called Yama, and played at least 15 minutes, often hours, every day for years.

I finally got to the point where my house was maxed out, filled with trophies, mail storage was being used for excess items, I had every K.K.Slider song, most of my town was covered with tree farms, flower farms, or stickers to make roads (and force digging holes to be in specific areas).

I was spending too much time in Yama, and couldn't stop checking it every day, so around 2008 I deleted my town, I couldn't break the habit any other way. I still miss Yama.

Animal Crossing: Wild World Snowman

Now Animal Crossing Pocket Camp (AC:PC) is out on iOS, and I can see I'll have the same problem eventually, but for now it's nice to have anything like it back.

AC:PC Squirrel

It's a little frustrating at first, being forced to do tutorials with no freedom of action; I'm of the theory that a game should have chargen, and then you're loose in the world. If you want tutorials or information, leave NPCs or books around, but don't make the player tap on a person or box to progress. The IAP doesn't seem too aggressive in this, I know I could buy "leaf tickets" (and I have to have them, to get K.K.Slider and Tom Nook for my camp), but I'm building them up at some pace in-game.

The camp is much smaller than a town or expanded house, and I don't like the outdoors theme and hippie bus as much as AC:WW, and you can't alter other camps. There's a really annoying siren wail when you're dragging items around, it's piercing and the least Nintendo-like sound I've ever heard; I'm going to try to file a bug report if they have any way to do that. As usual, Nintendo has never heard of scaling servers, and I'm getting constant errors, which will only get worse as more of the world wakes up and starts playing today.

AC:PC Communications Error

But problems aside, I live there now. If you want to be my friend ?, my ID is: 1227 6011 048

Bloggerating

I normally don't do the self-analysis, why are we here thing, and certainly no self-promotion or "personal braaaaaaand". The joke's only funny until you die, then you leave a stink-bomb corpse and it's really funny, and then they shovel dirt in your face. Until then, I mostly do things I find fun and maybe post them for others.

But what is blogging for?

Social media in the form that Twitter and Facebook have produced, is now clearly seen a mistake; it used to be fun, and is easily compulsive, and I'm the next-to-last guy who could say with a straight face "don't do things that are fun but possibly dangerous to your body or mind", but the toxic side-effects have gone from heroin, to a cocktail of PCP, bath salts, and krokodil. It has turned and is eating your face. Get out while you still can.

Reading blogs is quieter. It can happen when you want, a pull request from a bunch of servers instead of a constantly pushing firehose. I can pick thru categories, since I organize feeds into a score of folders. Not everyone has a useful feed anymore, and there are times when a blog or comic stops updating the RSS and I don't notice until an annual sweep of stale feeds. I don't read everything, I read what I want and clear the rest.

My current OPML export has something like 1200 feeds, which is ridiculous, but with my organization it's not that bad. If I want to read comics, SF blogs, Mac news, dev blogs, etc., it all adds up pretty quick. Many only update a few times a year, which is probably not enough; I only keep a few "Tech Bullshit" blogs that spam more than a couple posts a day.

I used NetNewsWire back when Brent Simmons made it, but switched to various others when iPad came out. The NNW iOS rewrite and the years-delayed Black Pixel re-rewrite were unacceptable, but the Google Reader-pocalypse forced me to finally do something, so ever since I've been using FeedBin; apparently not the most popular since it costs $5/month (paying for the things you use! What a bizarre idea!), but a near-desktop quality interface with great keyboard controls, that works well in Safari, is more useful to me.

In the Dark Ages, Before Computers, you'd read, hear, or think of something, and then spend the next week telling everyone you met a distorted version of it, jabber jabber jabber. Some would write letters and then copy them for different correspondents, and the real maniacs would write letters or columns for newspapers or magazines; the Dragon Magazine Waldorf letters are archetypical.

Now we have the unlimited reach to annoy everyone with the noise in our heads. Many people use Twitter as a stream of consciousness of their food ? and bathroom ? habits. It's too easy to type in a box and hit send. And if you "like" that person, and want to see anything halfway smart they write while distracted by everyone else's firehose, you also have to take their bathroom posts. UGH. You were so preoccupied with whether or not you could, that you didn't stop to think if you should..

Take my music posts (please!). On Twitter, I'd sometimes spam a music link every hour or more. Now, I typically have one song in mind, link the album, then use my amnesiac-encylopediac memory of the last 50 years of blues/rock/metal/electronica (a bit more for blues) to find a day's worth of similar albums. Then I keep the post open and hit links for iTunes. It reminds me of my teenage years, pulling a few vinyl or tape albums from my small library and spinning them in between bursts of radio; whole albums, every track unless something annoying was at the start or end of a side; I can't stand the random train-wreck of commercial radio. And my 20s DJing at http://kuoi.org/ with my playlist, I did a lot of deep cuts or half-albums. It's nice if someone else likes my music, but that's not why I post.

This post has been building for a day or two. I write a little, leave it in drafts, change the title, rewrite parts, find le mot juste, a few coherent thoughts, or Suck-like links to emphasize or subvert meanings. When I think it's worth reading, I'll hit Publish. Thinking and writing at any depth is simply impossible in the social media engines.

Movie Policy

My movie policy is "with rare exceptions, don't watch adaptations or sequels".

Movie adaptations of books are mostly horrible. What I read a book for is complex new ideas, setting, plot, very slightly writing style and characterization. Those are almost impossible for movies to capture; they can have attractive sets, cinematography, and soundtrack, and adequate hitting-marks-and-saying-lines by the walking meatsticks we call "actors", but there simply isn't time for a complex plot or any exploration of an idea in a film, and few of them even try.

Competent SF/F/H adaptations are almost nonexistent:

  • 20,000 Leagues Under the Sea (1954)
  • "It's a Good Life" (1961)
  • The Man Who Fell to Earth (1976)
  • Altered States (1980)
  • A Clockwork Orange (1981)
  • "Who Goes There?"/The Thing (1982)

These are not competent, despite what some fanlings will scream in all caps:

  • Solaris (1972) and Solaris (2002), both are slow, tedious, and almost unwatchable. Stanislaw Lem's hard to film, but these are terrible.
  • 2001 (1968) was a collaboration, but the book has an actual ending.
  • The Shining (1980) is beautifully-shot, perfectly-acted nonsense which loses everything interesting from King's book.
  • Every Philip K Dick adaptation. I didn't hate Screamers (1995) or Radio Free Albemuth (2010), but neither are great films.
  • Watchmen (2009) and Batman: The Killing Joke (2016) tried, and about half of each succeeds perfectly, wrecked by the other half being trash.
  • Pirates of the Carribean 2+, which had sometimes spectacularly good ideas and amazing visuals, wrecked by Disneyfication, incoherent plots, bit part actors who aren't competent for limelight, and Depp's Mick Jagger impersonation wearing thin fast.
  • Harry Potter. Films 1-5 are fun trash, then 6-8 are grim, dull, melodramatic trash. I quite like the books, even the grindingly slow later ones, but these aren't quality adaptations.

Competent genre adaptations (I don't read romance or no-genre "literature", so I can't comment on those), I can think of:

  • The Godfather (1972), and the movie is far better than the book.
  • The Wages of Fear/Sorcerer (1977) perhaps, but I haven't read the French novel, only seen the French movie; Sorcerer has deeper characters and literally explosive tension.
  • Lonesome Dove (1989)
  • "Rita Hayworth and the Shawshank Redemption"/The Shawshank Redemption (1994)
  • Fight Club (1999)
  • American Psycho (2000) and The Rules of Attraction (2002), but the Less Than Zero (1987) "adaptation of a title" almost cancels out both positive adaptations.
  • Man on Fire (2004) is better than the book, dumping the trick ending of the book helped.
  • A History of Violence (2005)
  • Jesse Stone: Stone Cold (2005) and all the sequels have done justice to Robert B. Parker's novels, though Tom Selleck is about 30 years older than the Jesse Stone of the books.
  • The Girl with the Dragon Tattoo (2009), the Swedish films are pretty close to the books' brooding tone, technophilia, and fucked-up psychologies, and the actors are great for it. NEVER watch American remakes.

Competent sequels are just as rare. After quite a while thinking on it, I have:

  • Samurai II: Duel at Ichijoji Temple (1955)
  • Sanjuro (1962)
  • The Good, the Bad, and the Ugly (1967)
  • The Godfather: Part II (1974)
  • Dawn of the Dead (1978)
  • Invasion of the Body Snatchers (1978), also an adaptation, but the book is terrible.
  • The Empire Strikes Back (1982)
  • Star Trek II: The Wrath of Khan (1982)
  • Day of the Dead (1985)
  • Aliens (1986), but only barely: It's written by a pack of syphilitic monkeys compared to Dan O'Bannon's perfect Alien, it's not even a horror movie, it's just another of James Cameron's trashy Vietnam-in-space flicks. Still, you take what you can get.
  • The Killer (1989), not technically a sequel to A Better Tommorrow (1986), but close enough.
  • Terminator 2: Judgement Day (1991)
  • New Dragon Inn (1992), I found the original 1967 film grim, dull, and unloveable despite great swordfights, the remake/sequel is fun while still menacing and having even better swordfights.
  • Léon: The Professional (1994), not technically a sequel to La Femme Nikita (1990), but close enough.
  • Hellboy II: The Golden Army (2008), considerably better than the first, and more like the comics.
  • The Dark Knight (2008)
  • While I enjoyed Guardians of the Galaxy Vol. 2 (2017) as fun trash, it's not as good fun trash as the first.

I bring this up because of jwz's unhappy review of Blade Runner 2049. It's like they did everything I hate in films. And jwz likes Blade Runner, I barely tolerate it as moving wallpaper.

Philip K Dick's "Do Androids Dream of Electric Sheep" is vastly more interesting than the very pretty but vapid Blade Runner, and the new one is a sequel to an adaptation, so it's a hall of mirrors reflecting horrors. All the philosophy and setting of DADOES is thrown away for visual flair & a nice Vangelis album, which you can listen to without a movie talking over it.

Why in Blade Runner are there artificial animals & people? Why is the city so empty except for little gaggles of people? Why is empathy their test for humanity? None of this is even hinted at. So the movie is just a psychopath murdering and raping what appear to be human slaves who try to run or can't quite pass his test.

So they doubled down on pretty nonsense instead of background or plot, and introduced stupid new ideas. The only good thing Jared Leto has ever done was American Psycho, especially the Huey Lewis scene. Every use of him in any other film should just be a remake of that scene.

The Future of Programming is Text

You can't grep or diff binary trees. You can't get a Smalltalk IDE on your iPad. You can't write an operating system or a big application in Scratch or the Mindstorms IDE. And even a small program in these won't work in the next version.

But you can edit plain text with any text editor, whether that's ed, nano, Vim, emacs, BBEdit, Atom, Textastic, Editorial, Eclipse, AppCode, whatever. You can save it safely and easily in any source control system. You can run an awk or sed script over your entire codebase and it just works.

See also:

If your language (or non-linguistic programming environment in some cases) is only usable from a single IDE, you've cut yourself off from every other analysis and editing tool in the world, you're dependent on that one tool to do everything you want.

I have old Mac and iPhone NIB files which can't be read with any current version of Xcode/Interface Builder, the file format was only supported by one dev tool and it's changed, and the old tools don't run on modern OS X. These NIB files "work", in that they deserialize into objects, but there's no way to edit them. Where possible, I now do most UI work in code; this isn't great fun, I end up with a ton of builder functions to avoid repetitive code blocks, but it'll still compile and work in 10 years.

This is also why I don't use a WYSIWYG word processor, I use MultiMarkdown. I've lost documents to proprietary WPs, and of course there's no way to run tools over them (except, sort of, MS Word with BASIC).

None of this has stopped people from making new non-text environments, or weird experiments. Experiments can be useful even when they fail, telling us what doesn't work. But they don't catch on because the tools aren't as good as text, and won't work in the future when the experimenter gets bored and quits.

Swiftian Satire, or Tragedy?

I honestly cannot tell if Swift developers are seriously eating Irish babies, or taking the Mickey.

From bad implementations of Equatable and Hashable, the wag leaps to:

extension GridPoint : HashVisitable {
    func hash<H: Hasher>(_ hasher: inout H) {
        self.x.hash(&hasher)
        self.y.hash(&hasher)
    }
}

Bravo! That's easily the funniest punchline to a programming joke since "where do you think the chaos came from?"

Starts with the most bizarre strawman Objective-C Sieve of Erathosthenes I've ever seen. A real implementation would be in C, because Obj-C is C with objects, and it'd be massively faster:

#include <stdlib.h>
#include <stdio.h>

typedef char BOOL; // or link in Foundation
#define YES 1
#define NO 0

int main(int argc, char **argv) {
    if (argc != 2) {
        printf("Usage: primes COUNT\n");
        exit(1);
    }
    long n = atoi(argv[1]);
    BOOL p[n];
    p[0] = NO;
    p[1] = NO;
    for (long i = 2; i < n; ++i) {
        p[i] = YES;
    }
    for (long i = 2; i < n; ++i) {
        for (long j = i*i; j < n; j += i) {
            p[j] = NO;
        }
    }
    for (long i = 1; i < n; ++i) {
        if (p[i]) {
            printf("%ld ", i);
        }
    }
    puts("");
    return 0;
}

This does use more lines of code, but they're short, low-density, and it's instantly obvious what it's doing (my predilection for 1-char var names aside). Can you actually decode his filter-based version?

func sieve(_ sorted: [Int]) -> [Int] {
    guard !sorted.isEmpty else { return [] }
    let (head, tail) = (sorted[0], sorted[1..<sorted.count])
    return [head] + sieve(tail.filter { $0 % head > 0 })
}

let numbers = Array(2...1000000)
let primes = sieve(numbers)
print(primes)

And the runtime experiment:

mdh@Aegura:~/Code/CodeC% time clang -O3 -o primes primes.c                
clang -O3 -o primes primes.c  0.04s user 0.41s system 83% cpu 0.534 total
mdh@Aegura:~/Code/CodeC% time ./primes 1000000 >~/Desktop/primes.txt      
./primes 1000000 > ~/Desktop/primes.txt  0.02s user 0.00s system 89% cpu 0.025 total

mdh@Aegura:~/Code/CodeSwift% time swiftc -O -o swiftPrimes swiftPrimes.swift
swiftc -O -o swiftPrimes swiftPrimes.swift  0.57s user 0.64s system 69% cpu 1.754 total
mdh@Aegura:~/Code/CodeSwift% time ./swiftPrimes >~/Desktop/swiftPrimes.txt  
./swiftPrimes > ~/Desktop/swiftPrimes.txt  51.79s user 26.49s system 99% cpu 1:18.78 total

So the naïve C implementation is about 3,151x faster. I can't measure it precisely because a limit measurable in C, would take Swift until the heat death of the Universe.

So here's my question: Is Vincent aware of this, and his theme of "diabetes", "sugar", "saccharine", etc. pointing at how fat, bloated, slow, and deadly Swift is? He never lets on if this is a joke, he keeps tossing more syntax layers on top of Swift.