--- title: "Word Sorter" id: 53848 type: "computer_media" slug: "sortword" url: "http://localhost/computer_media/sortword/" markdown_url: "http://localhost/computer_media/sortword.md" published_at: "2024-05-13T19:02:05+00:00" modified_at: "2026-03-30T21:46:27+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A Shell-Metzner sort engine for up to n user-supplied words, backed by an external machine code bold-print routine loaded from tape." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Demo" slug: "demo" taxonomy: "genre" url: "http://localhost/type/demo/" media_contents: - id: 55361 title: "SINCUS Exchange Tape 102 – Utilities & Business" type: "computer_media" url: "http://localhost/computer_media/sincus-exchange-tape-102-utilities-business/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/05/word-sorter.png" media_type_tags: "Demo" --- This program implements an interactive word sorter that accepts up to n words from the user, sorts them alphabetically using a Shell-Metzner (Shell sort) algorithm, and displays or prints the sorted list. It loads an external machine code routine from tape at address 57786, invoked via RANDOMIZE USR 57786, which provides a bold-print display effect. The Shell-Metzner sort in the subroutine at line 1500 uses a gap sequence derived from powers of 2 (F = 2^A – 1, halved each pass), operating directly on the string array a$(n,20). The program includes both screen display and printer output routines, with a loop at lines 170–180 allowing the user to redisplay, print, or restart the sort session. The SAVE line at 9999 persists both the BASIC program with auto-run and the machine code block as a separate CODE file. *** ## Program Analysis ### Program Structure The program is organized into four logical phases: initialization and input (lines 5–70), sort invocation and display (lines 75–180), printer output (lines 185–205), and two subroutines — the Shell-Metzner sort (1500–1595) and the screen display loop (2000–2040). A final line (9999) handles saving both the BASIC program and the companion machine code file. | Line Range | Purpose | | --- | --- | | 5–12 | REM header, load machine code, initialize display | | 15–70 | User input: title and word list | | 75–83 | Sort trigger, calls Shell-Metzner at 1500 | | 125–180 | Display sorted list, user interaction loop | | 185–205 | Printer (LPRINT) output routine | | 1500–1595 | Shell-Metzner sort subroutine | | 2000–2040 | Screen display subroutine | | 9999 | SAVE routine for BASIC and CODE | ### Machine Code Usage Line 10 loads an external machine code block with `LOAD ""CODE` and immediately calls it via `RANDOMIZE USR 57786`. The companion file is named `boldprint` and is 100 bytes long, stored at address 57786 (near the top of a 48K memory map). Based on the program name and REM at line 5, this routine modifies the display or font rendering to produce bold text output. The machine code is preserved at line 9999 with `SAVE "boldprint" CODE 57786,100`. ### Shell-Metzner Sort (Lines 1500–1595) The sort uses the Shell-Metzner algorithm, a variant of Shell sort. The gap sequence is initialized as `F = 2^A - 1` where `A = INT(LN N / LN 2)`, effectively the largest power-of-2 minus 1 not exceeding N. Each outer pass halves the gap with `F = INT(F/2)`, returning when `F = 0`. 1. Compute initial gap: `A = INT(LN N / LN 2)`, `F = 2^A - 1` 2. Halve gap: `F = INT(F/2)`; if zero, `RETURN` 3. Set range: `D = N - F`, `B = 1` 4. Compare `A$(A)` and `A$(E)` where `E = A + F`; swap if out of order 5. Walk back by gap while `A >= 1`, then advance `B` Comments at lines 1535 and 1565 document how to reverse sort order (change `>` to `<`) or sort numbers (replace `A$` with a numeric array `A`), indicating the routine was designed to be reusable. ### Key BASIC Idioms - `DIM a$(n,20)` — dynamic string array dimensioned at runtime using user-supplied `n`, with each element padded to 20 characters. - `TAB ((32-LEN l$)/2)` — centers the title string across a 32-column display. - `INVERSE 1` and `FLASH 1` — used for UI highlights on the sort-complete message and input prompts. - `RUN 15` at line 178 restarts the program from the input phase without clearing the CODE routine loaded at line 10, since `RUN` with a line number does not re-execute `LOAD ""CODE`. ### User Interaction Loop Lines 170–180 form a polling loop using bare `INKEY$` (no PAUSE) that checks for `y`, `c`, or `n`/`N` keypresses. This is a standard busy-wait idiom. Notably, lowercase `y` and uppercase `N` are both handled, but uppercase `Y` and lowercase `n` are inconsistently treated — `y` only (line 170) versus both `n` and `N` (line 178). ### Display vs. Print Subroutines The program maintains two parallel output paths: the screen display subroutine at line 2000 uses `PRINT` and uppercase variable names (`M`, `N`, `A$`), while the printer routine at lines 185–205 uses `LPRINT` with lowercase names (`m`, `n`, `a$`). On this platform, variable names are case-sensitive, so `M` and `m` are distinct variables. The sort subroutine at 1500 uses uppercase `A`, `B`, `D`, `E`, `F`, `N`, `A$`, `T$`, while the input phase uses lowercase `m`, `n`, `a$`. The display subroutine at 2000 uses uppercase versions, which correctly reference the sorted array populated by the sort routine. ### Notable Anomalies - Line 175 calls `GO SUB 185` for the print routine but does not have a corresponding `RETURN` path back — after line 205 sets `m=1` and jumps to `GO TO 135`, control never returns to the `GO SUB` caller. This effectively treats the print routine as a one-way branch rather than a true subroutine. - The gap initialization computes `A` twice — once as the log-based exponent (line 1505) and then reuses `A` as the inner loop index from line 1530 onward — relying on `F` having captured the initial gap value before `A` is overwritten. ## Source Code ``` 5 REM sortword2 with boldprint CODE 10 LOAD ""CODE : RANDOMIZE USR 57786 12 CLS : BORDER 6 15 PRINT " "; INVERSE 1;" W O R D S O R T E R " 20 PRINT 25 PRINT " How many words are"'" you going to sort? "; 30 INPUT n: PRINT INVERSE 1;n 35 DIM a$(n,20) 40 PRINT 45 INPUT "Enter the title of the sort. ";l$ 50 PRINT " Enter the words to be sorted.": PRINT 55 PRINT 60 FOR m=1 TO n 65 INPUT a$(m): PRINT m;".";TAB 4;a$(m) 70 NEXT m 75 PRINT 80 PRINT " "; INVERSE 1;"Please wait while I sort." 83 GO SUB 1500 125 CLS 130 PRINT TAB ((32-LEN l$)/2);l$ 135 PRINT 138 GO SUB 2000 155 PRINT : PRINT FLASH 1;"S O R T I S C O M P L E T E D" 160 PRINT : PRINT " Do you wish to see the list again? (y/n)" 165 PRINT : PRINT " If you wish to print the list then press 'c'." 170 IF INKEY$="y" THEN CLS : LET m=1: GO TO 130 175 IF INKEY$="c" THEN CLS : LET m=1: GO SUB 185 178 IF INKEY$="n" OR INKEY$="N" THEN CLS : RUN 15 180 GO TO 170 185 REM print routine 187 LPRINT TAB ((32-LEN l$)/2);l$: LPRINT 190 FOR m=1 TO n 195 LPRINT m;".";TAB 4;a$(m) 198 LPRINT 200 NEXT m 205 LET m=1: GO TO 135 1500 REM Shell-Metzner Sort 1505 LET A=INT (LN N/LN 2): LET F=2^A-1 1510 LET F=INT (F/2): IF F=0 THEN RETURN 1520 LET D=N-F: LET B=1 1530 LET A=B 1535 REM Change Sign(>) in Line 1540 to Reverse Order 1540 LET E=A+F: IF A$(A)>A$(E) THEN GO TO 1570 1550 LET B=B+1: IF B>D THEN GO TO 1510 1560 GO TO 1530 1565 REM Change A$ to A in Line 1570 for Number Sort 1570 LET T$=A$(A): LET A$(A)=A$(E): LET A$(E)=T$ 1580 LET A=A-F: IF A<1 THEN GO TO 1550 1590 GO TO 1540 1595 RETURN 2000 REM 2010 FOR M=1 TO N 2020 PRINT M;".";TAB 4;A$(M) 2030 NEXT M 2040 RETURN 9999 SAVE "sortword2" LINE 1: SAVE "boldprint"CODE 57786,100: BEEP 1,32: ```