silly coding

Normally I stay away from most sites devoted to technology and discussions of it. But the other day I stumbled upon a story with the common lament that crops up periodically on such sites about how stupid other coders are. No real examples, just hearsay. In this story the examples led off with supposedly bad web sites that presented horrible (to them) entry fields. The story contained other examples of bad coding and the eventual eternal question: why can’t today’s coders write “good code,” good code being defined by the commenters in the story.

The same story linked to this old blog post from 2007 titled “Why Can’t Programmers.. Program?” (link: https://blog.codinghorror.com/why-cant-programmers-program/ ). This post is a good fifteen years old. A tremendous amount has changed since it was published. Existing programming languages have undergone fundamental evolution, new languages have come into existence, and programming fads have come and gone. To agree or disagree with this post at this point in history is a bit pointless. But it did provide something amusing for me to do; writing a FizzBuzz program in Python.

The rules for FizzBuzz according to the post are simple enough:

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

I made one important change such that I always print the number so I can check manually if the output is correct or not. Here’s the Python code. Yes, it’s absolutely without “elegance.” I have no use for elegant code, because that’s the code with the most bugs and the most difficult to maintain.

#!/usr/bin/env python3

for i in range(1,101):
    if (i % 3 == 0) and (i % 5 == 0):
        print("FIZZBUZZ {}".format(i))
    elif (i % 3 == 0):
        print("FIZZ     {}".format(i))
    elif (i % 5 == 0):
        print("    BUZZ {}".format(i))
    else:
        print("         {}".format(i))

And here’s the last 11 lines of the output.

...
FIZZBUZZ 90
         91
         92
FIZZ     93
         94
    BUZZ 95
FIZZ     96
         97
         98
FIZZ     99
    BUZZ 100

You’ll note in my implementation I print it all, the indicators along with each number. As I wrote earlier that’s so I can trace and check manually if the output is correct. There’s also another reason to do it this way.

In my deep past I’ve needed to hire folks to fill open admin spots. A test I’ve used in the past goes something like this:

  1. Write a simple program to out text, based on whatever criteria I use at the time.
  2. Pipe that text output to a file.
  3. Use Unix command line tools to search for certain patterns in the text from the file.
  4. Pipe the output generated in (1) into the same command line tools to search for the same patterns in (3).

I didn’t care what language they used as long as it produced the needed output. If I were to do this again, I’d adjust the test thus:

  1. Write a FizzBuzz program in Python and produce the output based on my given criteria.
  2. Pipe the output into a file.
  3. Use Unix command line tools to read the file and search for every instance of “FIZZ”, “BUZZ”, “FIZZBUZZ” and lines that don’t have either, and count the number of lines.
  4. Pipe the output generated by your FizzBuzz program into Unix command line tools to perform the same searches and counts in (3).

The purpose of all of this is to plumb their programming abilities a bit, as well as their abilities to problem solve on the command line. One solution to count the number of instances of FIZZ would be ./fizzbuzz.py | grep -w "FIZZ" | wc -l. This yields a count of 27 lines. If you want to see exactly what the grep is producing then pipe grep’s output into wc -l. The key for grepping the whole word is grep’s ‘-w’ command line switch. That works for the first three word searches. Searching just for blank lines (no words) is a bit more complex, with at least two general solutions. For extra credit, the candidate is required to save the grep output before counting the number of lines, which means they need to know how to use tee.

I’d give a candidate no more than 30 minutes to do all of this. If they’re any good at all they’ll have it all done in far less time.

While I did say it was pointless to argue with a 2007 blog post, I will take a single exception. The was a comment in the 2007 blog post concerning recursion. A quote within that post called recursion as a way to solve a real problem. I do beg to differ. I come from a background in which recursion was to be avoided at all costs. Part of that comes from my initial background straight out of college (we’re talking mid-1970s here) where I was an embedded programmer. Iteration should be your first choice to solve any problem that supposedly calls for recursion.

I provide for your entertainment two implementations of everybody’s favorite recursion excuse, factorial, written using iteration, not recursion. First, a hoary old piece of Python I wrote about in a post on this blog back in 2014:

#!/usr/bin/env python3

import sys

def fact(n):
    a = 1
    print( n, end="! = ")

    while n > 0:
        a, n = a * n, n - 1

    print(a)

if __name__ == '__main__':
    if len(sys.argv) <= 1:
        print("Factorial calculator. Must call with at least one number as an argument.")
        print("Multiple numbers can be entered on the same line, as in '1 2 3'.")
        sys.exit()

    for i in range(1, len(sys.argv)):
        fact(int(sys.argv[i]))

And this is the same code re-written if you will for Julia:

#!/usr/bin/env julia

function Factorial(n)
	a = BigInt(1)
	print(n, "! = ")

	while n > 0
		a, n = a * n, n - 1
	end

	println(a)
end

if (length(ARGS) > 0)
	for x in ARGS
		Factorial(parse(Int64,x))
	end
else
	print("Factorial calculator. Must call with at least one number as an argument.")
    print("Multiple numbers can be entered on the same line, as in '1 2 3'.")
end

They both produce the same output (although I leave it as an exercise to the reader to determine if it’s correct):

What I find interesting are both the strong similarities between Python and Julia, as well as their interesting differences. For example Python can handle big numbers transparently. For Julia, you have to declare a variable as a big number by initializing it with a BigInt (see  line four in the second listing). Command line arguments are accessible directly in Julia, while Python requires you to import sys, and then work with those classes. I deal with both languages through Jupyter, but that’s a post for another time.

Neither one of these examples will win any awards. They’re both blindingly boring, and frankly, I strongly believe code should be written that’s boring. I hate “elegant” code. Boring is one trait of good code that allows it to be fixed if bugs occur or to allow extensions for new functionality.

Generally I’m old and retired and way past caring about the majority of this. But on this point I do care about the negative effect of the trolling critics who make those who are trying to produce better code and trying to improve their coding skills, nigh impossible to succeed. It’s the trolling critics that make it nigh impossible for all of us to have nice things, and to have good people produce those nice things.

going old-school with emacs on raspbian

Here’s another one for the Raspbian Buster notebook. I spent a bit of time trying to install Microsoft’s Visual Studio Code by following these directions at https://pimylifeup.com/raspberry-pi-visual-studio-code/. After setting up all the dependencies, downloading the tarfile and pulling it apart, then attempting to run the script that would install and build everything else, the VS Code installation failed because the JavaScript engine ran out of heap space. Fine. I’ve used VS Code everywhere else, including Linux systems with only 4GB of memory, but I’ve never had a heap-space issue before now. To be truthful I like working with VS Code and all its various plugins. I would have tried to debug the blocker, but I decided to cut my losses then and there.

I got to the point of trying to install VS Code because I found myself thrashing about looking for a comfortable code editor and almost IDE. I say almost IDE because, after nearly two decades immersed in IDE development environments, I’d grown tired of it. VS Code was a nice step back. But it wasn’t going to happen on the Raspberry Pi 4 with Raspbian Buster. That’s when I turned back to VIM (VI Improved) and rather quickly got it into pretty good shape for my needs. But something still nagged at the back of my mind, and as good as Vim has become, it just wasn’t quite right. I then figure, what the hell. I’ll install and try Emacs again.

I was introduced to Emacs back in the early 1990s by an Emacs goddess. That is no exaggeration. She could code rings around all the other guys, and part of her prowess can be attributed to her mastery of Emacs. She showed me how much better Emacs was over vi and then set me up with some directions and  a beginning .emacs file. I learned how to edit with emacs and how to configure it to fit my tastes. It soon became my default editor, and I carried around my .emacs file from project to project. But a funny thing happened on the way into the 21st century. I got swept up into the bigger-is-better development tool environment and eventually forgot about Emacs.

Until today. It’s been so long since I’ve used it that I’ve had to open up a basic web-based user manual and started to build an .emacs from scratch. Fortunately for me Emacs has evolved considerably. The version I’m using now is a desktop client, and it’s menu support has allowed me to quickly get back up to speed again with regards to setting up a decent visual environment. All the very old muscle memory is coming back, and I think I understand part of my uncomfortable feeling with Vim; a lot of the key sequences are too close together. Being back in Emacs, everything just falls naturally back into place.

Emacs is not better than Vim, and Vim isn’t better than Emacs. But Emacs is best for me.