In Day 4 we need to look at the characters in a grid and count up the number of occurrences of a word (XMAS) in “word search” style (can go any direction including diagonals and backwards). Initially, I thought it would be fun to create my own custom iterator that was given a position in the grid and delta x and y values and which yielded each character in that direction until we ran…
In Day 2 we need to do “things” to the consecutive pairs in a list of ints. The Rust standard library was created by thorough, right-thinking people, so getting consecutive pairs from a Vec is pretty easy: nums.windows(2).map(|w|(w[0],w[1]))But I’m not a barbarian. If I need to do three or four things to this list of pairs, I’m not going to reify that transformation into a…
[Editor’s note: This post vents anger at other software engineers. If they read it, they’ll probably feel bad. I hope they don’t read it, as my goal is not to make them feel bad, it is merely to express the boundless frustration I feel as we collectively fumble our way, in the dark, through the never ending battle against complexity. Undoubtedly people who have used software that…
I like to do puzzles. Crossword puzzles, logic puzzles, number puzzles, even a well conceived word search can tickle my fancy. My 2019 was nicely full of puzzles, so I’m recapping the year with a little summary of my puzzle throughput. Perhaps I’ll lure more people into the wild world of puzzling with my enthusiasm. For the past few years, I’ve been a subscriber to Games World of…
Hey kids, gather around the campfire. It’s time for side project story time with Uncle Mike. Today we’re going to talk about a little app I made to support my taiko practice. The motivation for the app is to answer the question “What am I practicing today?” when I go down to my practice space and prepare to make a lot of noise banging on drums. I’m trying to stick to…
I usually wait until my birthday to introspect on my life and make any course corrections that have been percolating in my subconscious. However, this year my subconscious seems to be ready for the percolations to bubble up on a more traditional “New Year’s resolution” schedule, so I’m going to run with it. Three things have percolated up, all somewhat intertwingled: Have…
What I originally took to be a quest for personal information management (PIM) nirvana, I now realize is in fact a perpetual cycle of personal information management samsara: the constant death of old tools and birth of new. As someone who loves building tools, I suppose this is a good thing. Before introducing the newest incarnation in this cycle, let me give a brief history. If you don’t…
Mario asked me an interesting question the other day. As is often my tendency, I gave him a multi-thousand word answer. Then he foolishly asked more interesting questions, so I hit him with additional walls of text. Be careful what you ask for kids. In the end, we figured we’d share with the class because perhaps some useful explanations happened along the way. [Note: because I’m lazy…
When I first started doing Android stuff in earnest, I kept a list of Things That Sucked™ about Android, but I never cleaned it up and published it. Now (years later) I’ve forgotten the details of many of my infuriated scribblings, so I’m unlikely to ever publish it as I’d likely be complaining about things that have long since been fixed and end up misleading anyone who happened…
After fourteen long and glorious years of driver automobile partnership, Anne the Van and I are parting ways. Natalie has finally decided that it might be useful to drive, but she’s not ready to drive something as majestic as Anne, so we’re getting a smaller car. Before turning her loose on the open market, I am putting out feelers to see if anyone “in the family” is in the…
For a combination of reasons, I’ve finally gone completely mad and decided to try my hand at the Quixotic task of developing a new programming model. Naturally it will solve all of our problems and make delicious toast. This is somewhat inspired by Bret Victor’s excellent presentations, but is also something that has been gnawing at the back of my mind for some time. I even went so far…
I was looking for a good F# cheat sheet and found a nice one originally published by a6systems, which has since disappeared from the Internet. I wasted thirty minutes of my life trying to track down a copy of the PDF. I found half a dozen sites that linked to the defunct original website, and a quarter dozen “document hosting” sites that insisted I register with them to download the…
The fruits of the last year and change of my, Sean Keeton’s, and a few other Dread Ringers' labor finally made its way to the App Store and Google Play last December. Now three months have gone by while I too infrequently found time to work on this post-mortem. I’m forcing myself to wrap it up today, lest the game be long forgotten by everyone but its author before this post-mortem is…
We finally moved into our new house on Aloha after many months of remodeling. It’s not completely finished, but it’s done enough that we’re moving in and enjoying the company of the contractors for a few weeks. I’ve posted some photos on the Googley Plus.
I frequently suffer from Java’s complete lack of assistance when it comes to asynchronous programming, but this little multi-phase maneuver really brings home the pain: protected void findFriends (final Socks.Network sock, Group contents) { contents.removeAll(); final Label status = UI.wrapLabel(_msgs.findingFriends); contents.add(status); class FriendFinder { public void start () { // make…
One of my colleagues recently committed a change with the comment: Log Message: ----------- Switching from "type *varname" to "type* varname" It gave me hope for the future, that we might overcome the legacy of K&R’s terrible mistake when they pioneered the styles foo *pointer and foo array[]. The world has mostly come around to the view that [] is part of the type, not the variable (i.e.…
I logged into the server that hosts samskivert.com yesterday and noticed that someone had done a very ham fisted job of hacking into my server (in addition to whatever nefarious business they hacked in to perpetrate, they changed the uid of my primary account to 0 and left the passwd file thusly modified). That’s what I get for having anything other than Apache and sshd running. Naturally,…
(Apologies for the duplication with Google+, still sorting out my syndication process.) What do you think should happen if you do the following in Java? Map<String,String> map = new HashMap<String,String>(); map.put("foo", "bar"); Iterator<Map.Entry<String,String>> iter = map.entrySet().iterator(); Map.Entry<String,String> entry = iter.next(); iter.remove(); entry.setValue("baz"); Should the entry…
Far too often, Google App Engine reports that everything is smooth sailing: when the view from my app looks substantially less rosy: My app is not complex. It stuffs data into the app engine data store and pulls it back out again. The total size of all my entities is one meeeellion bytes. The code is not massive; it’s seven jar files, the largest of which is the app engine API.
A post on the Sonatype blog cheerfully reports: Adding an additional source folder is as simple as: <project> ... <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>add-source</id> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources>…
I’ve been using Linux and X Windows as my primary operating system for development for a long time. Owing to the spotty or non-existent support of consumer applications over the years, I have generally maintained an auxiliary machine (sometimes Windows, sometimes a Mac) on which to run things like iTunes or the Flash Authoring Tool (or even the Flash player when Linux support was crap). My primary…
Problem 066: (source): import scala.collection.mutable.{Map => MMap} object Euler066 extends EulerApp { def leastx (d :Int) = { val amap = MMap[Int,BigInt]() val pmap = MMap[Int,BigInt]() val qmap = MMap[Int,BigInt]() val ppmap = MMap[Int,BigInt]() val qqmap = MMap[Int,BigInt]() def a (i :Int) :BigInt = amap.getOrElseUpdate(i, i match { case 0 => math.sqrt(d).toInt case _ => (a(0) + pp(i))/qq(i)…
I have progressed through a broad variety of personal information management tools over the course of my life, and they invariably fail to meet my needs in one way or another. This periodically motivates a flurry of note taking on what would comprise the “perfect” personal information management system, which I generally record using whatever duct tape and baling wire contraption I am currently…
I saw some weird background activity on my network interface and undertook an investigation. netstat readily revealed that Firefox had a metric ton of TCP connections open: yonami.local:58809 cdce.sef004.interna:www ESTABLISHED 7215/firefox-bin yonami.local:58828 cdce.sef004.interna:www ESTABLISHED 7215/firefox-bin yonami.local:33425 pv-in-f106.1e100.ne:www ESTABLISHED 7215/firefox-bin…
Like most developers, you probably don’t like unnecessary typing. By that, I don’t mean the static and dynamic variety, but the fingers on keyboard variety. However, when it comes to manipulating files via version control, we have recently taken a step backward. Historically, when faced with paths that look like the following: src/main/java/com/company/project/foopkg/MyAwesomeFoo.java…
The XML insanity of passing compiler arguments to Maven like so: <compilerArguments> <Xlint/> <Xlint:-serial/> <Xlint:-path/> </compilerArguments> has not surprisingly, come back to bite me in the ass. Most normal Maven actions seem to have no problem with it, but when I try to actually publish my project (via mvn release:prepare), I get the error I expected to see all along: [INFO]…
One can, and is indeed encouraged to, sign one’s Maven artifacts with GPG. This involves generating an artifact-version.jar.asc file containing the ASCII representation of the cryptographic signature for the artifact in question. This is uploaded to the Maven repository along with the artifact. Maven then helpfully generates artifact-version.jar.asc.md5 and artifact-version.jar.asc.sha1, and…
These ruminations were languishing in commit messages, which would normally satisfy my urge to complain. But now I need to complain further, and don’t have a commit message in which to express my discontent, so I’m airing the whole basket of dirty laundry here, and going on the record as a Maven hater. For those of you privy to the original commit messages, my new complaints will be…
Sun, in their infinite wisdom, circa Java 1.3, extended the jar file specification to allow dependencies to be expressed inside jar files by adding a Class-Path attribute to the MANIFEST.MF file. This causes the JVM (and javac, and various app servers) to try to magically add dependent jar files to the classpath. This is half-assed and wrong in too many ways to enumerate here. Some other…
The saga (act i, act ii) continues. More reasons why Maven sucks: Plugin version handling sucks. I learned this when I was trying to get Maven to generate javadocs. I was configuring the Maven Javadoc plugin with links to external javadocs when I discovered the very handy detectJavaApiLink option. It automatically adds a link to the standard Java API javadocs whose version matches the version…
I’m foolishly trying to write a javac annotation processor in Scala. This has already been a road fraught with gratuitous obstacles, but the latest wrinkle has driven me to vent in public. When I run my annotation processor thusly: javac -processor FooProcessor -processorpath fooproc/classes:blah/scala-library.jar SomeFile.java I get java.lang.IllegalStateException: zip file closed when my…
Problem 063: (source): object Euler063 extends EulerApp { def pows (n :Int) = Stream.from(1) prefixLength(p => BigInt(n).pow(p).toString.length == p) def answer = 1 to 9 map(pows) sum } The main observation here is that the number of digits of ax, for a ≥ 10, is guaranteed to exceed x. So we can restrict ourselves to looking only at the numbers from 1 to 9. Furthermore, the number of digits of ax,…
I am a heavy user of virtual desktops. I generally have a couple of shell windows, an emacs window, possibly a browser, and whatever target program I’m working on, on each of a few virtual desktops. When I’m interrupted from one project, I flip to the next virtual desktop, open a shell window, open an emacs window and start hacking away on said interruption. Often the stack will get…
Problem 058: object Euler58 extends EulerApp { def checkring (r :Int, primes :Int, nums :Int) :Int = { if (primes*10/nums < 1) 2*r-1 else { val skip = 2*r val base = (skip-1)*(skip-1) val rp = List(1, 2, 3).map(base+skip*_).filter(isprime).length checkring(r+1, primes+rp, nums+4); } } def answer = checkring(2, 3, 5) } This one is pretty easy after observing that you skip twice the “radius" to get…
Problem 060: object Euler60 extends EulerApp { val primes = genprimes(10000) filter(0.!=) val ppairs = Set() ++ (for { ii <- 0 until primes.length-1; jj <- ii until primes.length; val pi = primes(ii); val pj = primes(jj); if (isprime((pi.toString+pj).toInt) && isprime((pj.toString+pi).toInt)) } yield (pi, pj)) def isset (pset :List[Int], prime :Int) = pset.foldLeft(true)((b, a) => b && ppairs((a,…
Problem 056: object Euler56 extends EulerApp { def answer = (for { a <- 90 to 100; b <- 90 to 100 } yield BigInt(a).pow(b).toString.map(_-'0').sum) max } I’m in Switzerland at the moment, so my mind naturally turns to Project Euler. I have made some changes to my problem harness. Previously, I relied on Scala’s Application class’s jiggery pokery to stuff your whole program into a…
I don’t expect anyone to know the answer to this question, but I’m hoping that bitching about it will improve my mood sufficiently to prepare me for the painful foray into the guts of javac that will be needed to find the answer myself. There’s a very sophisticated pile of code in com.sun.tools.javac.comp.Infer that infers the type of a universally quantified method application, given its…
My current research project has given me myriad opportunities to break the Java compiler. Usually, this is because I’m tinkering with its internal data structures in a way that it neither anticipated nor feels especially good about. In such circumstances, I usually apologize profusely and look for a less intrusive way to accomplish my goals. Today however, I managed to cause javac to take umbrage…
In the nineteenth century, which was a dark and inflationary age in typography and type design, many compositors were encouraged to stuff extra spaces between sentences. Generations of twentieth-century typists were taught to do the same, by hitting the spacebar twice after every period. Your typing as well as your typesetting will benefit from unlearning this quaint Victorian habit. Robert…
In my recent programming adventures, I separately encountered two perplexing error messages: RuntimeException: Variable is used without definition! IllegalArgumentException: Duplicate field expected Inspection of the underlying code brought clarity: throw new RuntimeException("Variable " + m + " used without definition!"); throw new IllegalArgumentException("Duplicate field " + fieldName); The…
Problem 052: object Euler52 extends Application { def sort (n :Int) = n.toString.toList.sortWith(_<_).mkString.toInt def g (n :Int, sn :Int) = (2 to 6).forall(m => sort(n*m) == sn) def f (n :Int) = g(n, sort(n)) println(Stream.from(1).find(f).get) } Happy New Year! What better way to ring in the new year than doing math problems while sitting on the lanai under the Hawaiian sun? I’m already…
Problem 053: object Euler53 extends Application { def fact (n :BigInt) :BigInt = if (n < 2) 1 else n * fact(n-1) def choose (n :BigInt, r :BigInt) = fact(n)/(fact(r)*fact(n-r)) println((for (n <- 1 to 100; r <- 1 to n; if (choose(n, r) > 1000000)) yield 1).sum) } Another simple brute force solution. Enumerate and count. BigInt lets us avoid any serious thinking.
Problem 054: object Euler54 extends EulerApp { class Card (s :String) { val suit :Char = s.charAt(1) val rank :Int = "23456789TJQKA".indexOf(s.charAt(0)) def > (o :Card) = if (rank == o.rank) suit > o.suit else rank > o.rank } class Hand (c :Seq[Card]) { def groupCards (cards :List[Card]) :List[List[Card]] = if (cards.isEmpty) Nil else { val g = cards.takeWhile(_.rank == cards.head.rank) g ::…