Fun(?) with Arithmetic, the 1980s Way
A routine arithmetic challenge, TRS-80 Model III ROM BASIC, and a return to the technology I used as a teenager in my first job.

Stack Overflow's Fun with Arithmetic challenge asks us to take a long list of positive integers, calculate some statistics, count the decimal digits, and concatenate the results.
Mean, median, mode, odd digit count, even digit count. One final number.
More a chore than a challenge.
So, I decided to make it interesting. I would use TRS-80 Model III ROM BASIC, from the early 1980s. The technology I had used as a teenager, in my first job.
An entirely unnecessary constraint. Perfect.
First, get the numbers in
The first step was to turn the input into a series of DATA statements and read it into an array. Familiar territory:
10 DEFINTA-Z
15 DIMN(10000)
1000 DATA 359,598,742,713,221,697,286,562,221,572,914,219,568
1001 DATA 814,426,972,32,654,858,853,246,397,296,739,532,16,456
...
1208 DATA 2,124,897,675,349,862,841,-1Line numbers. Short variable names. Keywords pressed against their arguments. The listing was already beginning to look like something from another lifetime.
Initially, I used -1 to mark the end of the data. It worked as a convention, but I disliked having to maintain that extra value when testing with smaller samples. Forget the marker, put it in the wrong place, and the test itself becomes another source of trouble.
So I replaced it with BASIC's error handling:
100 ONERRORGOTO140
110 READN(M):M=M+1:GOTO110
120 ONERRORGOTO0
130 RETURN
140 M=M-1:RESUME120
Keep reading until BASIC objects. Then adjust the index and resume after the loop.
A rather blunt way to discover the end of the input. At least the input no longer needed an artificial ending.
Sorting, with destinations attached
Next came a Shell sort. An easy insertion-sort would be overly slow, a quick-sort too complex for that limited BASIC. I described the implementation in the commit history as "convoluted," and I see no reason to retract that assessment.
The algorithm sorts elements separated by a gap, then reduces the gap until the final pass puts neighboring elements in order. In the listing, that means comparisons, swaps, and jumps between numbered lines.
You can see the mechanics directly:
240 IFJ<GTHEN270
250 IFN(J)>=N(J-G)THEN270
260 T=N(J):N(J)=N(J-G):N(J-G)=T:J=J-G:GOTO240
There is no library call to hide behind. Each movement through the array has an address, and each address has to be right.
Once sorted, the array serves two purposes: finding the middle values for the median, and bringing repeated values together for the mode.
The median added a small bookkeeping trap. After reading, M holds the last occupied index. The count is therefore M+1. Confuse those two, and the arithmetic can be perfectly respectable while referring to the wrong elements.
Even nostalgia has off-by-one errors.
The arithmetic acquires a dialect
The challenge's mode has its own rule: when several values share the highest frequency, average those values and round the result. So finding the longest run of equal numbers is only part of the job. I also needed to track the sum and count of the tied candidates.
Then came the decimal digits.
My commit message records the discovery rather plainly:
That BASIC has NO MOD operator!
An operation I would barely think about in C suddenly needed to be expressed through division and subtraction. The digit extraction uses an integer temporary V and computes the remainder as:
D=N(I)-V*10
The surrounding loop counts that digit, replaces the number with its reduced value, and continues. It consumes the array entry as it goes, so the original value must already have contributed to the sum and the repetition tracking.
Small decisions, but connected ones. Types, calculation order, and jump targets all matter.
I also removed unnecessary INT() calls after introducing DEFINTA-Z. The sum retained an explicit S#, giving it a double-precision variable while the ordinary variables remained integers.
The mathematics was elementary. Remembering how to express it in this particular BASIC was becoming the actual exercise.
One final number, assembled as text
The challenge wants the results pasted together. I assembled that output as a string, appending each component through a small subroutine:
999 R$=R$+MID$(STR$(R),2,9):RETURN
STR$ supplies the decimal representation; MID$ skips the leading space for a positive value. R$ accumulates the pieces in the required order.
The number I submitted was:
3251179966045634169
The history includes the appropriately cautious milestone "Got FINAL NUMBER! (looks right...)," followed by cleanup and another correction. The explanation for the last fix is shorter:
Wrong GOTO, duh
Apparently, that part of the experience came back too.
Something working, again
The repository preserves the code and the steps along the way. You can try the listing in this TRS-80 Model III emulator, which supports simulated typing from the clipboard. I was happy to revisit BASIC without typing all the data by hand.
A routine calculation had become an enjoyable programming exercise. I had to think about reading, sorting, types, formatting, and control flow in an environment I had used decades earlier.
And I got something working with the technology from my first job.
As a teenager, I used it because it was the tool I had. This time, I chose it because I wanted to see what it felt like again.
The arithmetic was the excuse.
Comments ()