PHONE WORD

Developer(s): David Hartman
Date: 1988
Type: Program
Platform(s): TS 2068
Tags: Home

PHONE WORD generates all possible letter combinations for the last four digits of a telephone number, exploiting the standard telephone keypad mapping (2=ABC, 3=DEF, etc.) to display every word a number could spell. The program stores letter groups in a two-dimensional string array `l$(10,3)` and all 81 candidate words in `w$(81,4)`, iterating through four nested loops to build every combination. A notable quirk appears at line 310 and throughout lines 550–620, where `n$(PI)` is used instead of `n$(3)` to index the third character of the input string — PI evaluates to approximately 3.14159 and is truncated to integer 3, making it functionally equivalent but unconventional. Digits 0 and 1 receive special handling: if at most one such digit is present, it is substituted directly into that position of the word; if more than one is found, the program reports the number cannot form a useful word. The results are displayed six at a time, with an option to send the output to a printer via the COPY command.


Program Structure

The program is organized into a main flow with two subroutines and a data block:

  1. Lines 30–80: Title screen display and initial keypress wait.
  2. Lines 90–240: Input section — prompts for a 4-digit string, validates length, and flags digits 0 and 1.
  3. Lines 250–360: Four nested loops building all 81 letter combinations into w$.
  4. Lines 370–540: Results display, six words per line, with optional COPY to printer.
  5. Lines 550–630: Alternate word-building branch for numbers containing one 0 or 1.
  6. Lines 650–690: Subroutine to restore substituted digits (Q→1, Z→0) before display.
  7. Lines 700–740: Initialization subroutine — dimensions arrays and READs keypad letter groups.
  8. Lines 750–790: Error branch for numbers with more than one 0 or 1.

Array Design

Two string arrays carry all the data:

ArrayDimensionsPurpose
l$(10,3)10 rows × 3 charsTelephone keypad letter groups (index 1–9, row 10 unused)
w$(81,4)81 rows × 4 charsAll generated 4-letter word candidates (3⁴ = 81)

The l$ array is dimensioned as DIM l$(10,PI) at line 700. Because PI ≈ 3.14159 is truncated to 3, this is equivalent to DIM l$(10,3) — a three-character-wide string per row, matching the three letters on each telephone key.

The PI Indexing Quirk

The most striking anomaly in this program is the repeated use of n$(PI) (lines 310, 550–620) to reference the third character of the input string n$. Since BASIC truncates floating-point indices to integers, PI → 3, making n$(PI) identical in effect to n$(3). This is almost certainly an accidental substitution — the author or a text editor may have inadvertently replaced the digit 3 with the token PI in those positions. It is functionally harmless but unusual and inconsistent with the use of literal 3 elsewhere.

Digit Substitution Strategy

Because 0 and 1 do not map to letters on a telephone keypad, the program converts them to sentinel characters before processing:

  • 0"Z" (last row of l$, which is empty)
  • 1"Q" (row 1 of l$, which is also empty)

The counter f tracks how many such substitutions were made. If f > 1, the program branches to line 750 and reports the number is unsuitable. If f = 1, the four nested loops still run but control falls through to lines 550–630, where a chain of eight IF tests detects which position holds a sentinel and hard-codes the literal digit character ("0" or "1") into that slot of the word. The subroutine at lines 650–690 reverses the Q/Z substitution back to 1/0 before printing the original number for display.

Word Generation Loop

Lines 260–360 use four nested FOR loops (indices j, k, l, m each running 1–3) producing 3⁴ = 81 iterations, one per word. Each iteration calls l$(VAL n$(pos), loop_var) to look up the letter at position loop_var within the keypad group for the digit at n$(pos). The results are concatenated and stored in w$(x) with x incrementing from 1 to 81.

Results Display

Lines 410–480 implement a simple paging loop: starting at j=1, it prints six words per pass (indices j to j+5), then advances j to the next group and loops back. The sentinel check at line 430 exits when k=82 (one past the last valid index), preventing an out-of-bounds read. After all 81 words are shown, line 490 offers a COPY option; pressing C or c triggers a hardcopy and then RUN restarts the program entirely rather than GO TO 90, which would re-dimension the arrays unnecessarily.

Notable Idioms

  • PAUSE 0 followed by keypress-drain loops (IF INKEY$ <>"" THEN GO TO n) is the standard debounced wait pattern.
  • VAL n$(pos) converts a single character from the digit string to its numeric value for use as a row index into l$.
  • DIM l$(10,PI) — using the built-in constant PI as a dimension argument is an unusual but legal memory-saving trick that happens to produce the correct size of 3.
  • INPUT LINE n$ is used to prevent the INPUT parser from interpreting the digit string as a numeric expression.

Bugs and Anomalies

  • n$(PI) instead of n$(3): As described above, functionally correct but clearly unintentional.
  • Missing letter Q on key 7: The DATA at line 730 maps key 7 to "PRS" (omitting Q, as on older telephone keypads) and key 9 to "WXY" (omitting Z). This is historically accurate for the era’s standard keypad layout.
  • Line 640 STOP: This line is unreachable dead code; it sits between the end of the display loop (line 540 jumps to RUN) and the start of the subroutines, and no branch targets it.
  • Single-zero/one branch inefficiency: When f=1, the four nested loops still execute 81 times, but lines 310’s GO TO 550 (via IF f THEN GO TO 550 at line 300) means line 310 is skipped every iteration. Lines 550–630 then perform eight sequential IF tests each iteration to find the flagged position, which is redundant since the position was known during the initial scan at lines 150–190.

Source Code

  10 REM WORDS FROM TELEPHONE NUMBERS
  20 REM 105/1.1 3/20/88
  30 CLS 
  40 PRINT AT 6,0;"Words from Telephone Numbers"; AT 14,0;"Let's see what your number","spells."
  50 PRINT AT 21,0;"\* 1988 David Hartman"
  60 GO SUB 700
  70 IF INKEY$ <>"" THEN GO TO 70
  80 PAUSE 0
  90 CLS 
 100 PRINT TAB 8;"TELEPHONE WORDS",,,
 110 PRINT "Enter the last four digits of   your telephone number to see","what they spell. Then, use that word when somebody wants your","number. He probably will be","able to remember it without","writing it down."
 120 INPUT  LINE n$
 130 IF LEN n$ <>4 THEN GO TO 220
 140 LET f=0
 150 FOR j=1 TO 4
 160 IF n$(j)="1" OR n$(j)="0" THEN LET f=f+1
 170 IF n$(j)="1" THEN LET n$(j)="Q"
 180 IF n$(j)="0" THEN LET n$(j)="Z"
 190 NEXT j
 200 IF f>1 THEN GO TO 750
 210 GO TO 250
 220 PRINT AT 15,0;"You did not enter a 4 digit","number. Please try again."
 230 IF INKEY$ <>"" THEN GO TO 230
 240 PAUSE 0:GO TO 90
 250 LET x=1
 260 FOR j=1 TO 3
 270 FOR k=1 TO 3
 280 FOR l=1 TO 3
 290 FOR m=1 TO 3
 300 IF f THEN GO TO 550
 310 LET w$(x)=l$(VAL n$(1),j)+l$(VAL n$(2),k)+l$(VAL n$(PI),l)+l$(VAL n$(4),m)
 320 LET x=x+1
 330 NEXT m
 340 NEXT l
 350 NEXT k
 360 NEXT j
 370 CLS 
 380 GO SUB 650
 390 PRINT "Here are the choices for ";n$;":"
 400 PRINT 
 410 LET j=1
 420 FOR k=j TO j+5
 430 IF k=82 THEN GO TO 490
 440 PRINT w$(k);".";
 450 NEXT k
 460 PRINT 
 470 LET j=k
 480 GO TO 420
 490 PRINT AT 21,0;"(C) COPY?"
 500 INPUT  LINE a$
 510 IF a$ <>"c" AND a$ <>"C" THEN GO TO 90
 520 PRINT AT 21,0,
 530 COPY 
 540 RUN 
 550 IF n$(1)="Z" THEN LET w$(x)="0"+l$(VAL n$(2),k)+l$(VAL n$(PI),l)+l$(VAL n$(4),m)
 560 IF n$(1)="Q" THEN LET w$(x)="1"+l$(VAL n$(2),k)+l$(VAL n$(PI),l)+l$(VAL n$(4),m)
 570 IF n$(2)="Z" THEN LET w$(x)=l$(VAL n$(1),j)+"0"+l$(VAL n$(PI),l)+l$(VAL n$(4),m)
 580 IF n$(2)="Q" THEN LET w$(x)=l$(VAL n$(1),j)+"1"+l$(VAL n$(PI),l)+l$(VAL n$(4),m)
 590 IF n$(PI)="Z" THEN LET w$(x)=l$(VAL n$(1),j)+l$(VAL n$(2),k)+"0"+l$(VAL n$(4),m)
 600 IF n$(PI)="Q" THEN LET w$(x)=l$(VAL n$(1),j)+l$(VAL n$(2),k)+"1"+l$(VAL n$(4),m)
 610 IF n$(4)="Z" THEN LET w$(x)=l$(VAL n$(1),j)+l$(VAL n$(2),k)+l$(VAL n$(PI),l)+"0"
 620 IF n$(4)="Q" THEN LET w$(x)=l$(VAL n$(1),j)+l$(VAL n$(2),k)+l$(VAL n$(PI),l)+"1"
 630 GO TO 320
 640 STOP 
 650 FOR j=1 TO 4
 660 IF n$(j)="Q" THEN LET n$(j)="1"
 670 IF n$(j)="Z" THEN LET n$(j)="0"
 680 NEXT j
 690 RETURN 
 700 DIM l$(10, PI)
 710 DIM w$(81,4)
 720 RESTORE 700:FOR J=1 TO 10:READ L$(j):NEXT J
 730 DATA "","ABC","DEF","GHI","JKL","MNO","PRS","TUV","WXY",""
 740 RETURN 
 750 CLS 
 760 GO SUB 650
 770 PRINT AT 14,0;"Your number, ";n$;", has too many ones or zeroes to be useful in creating a word..Sorry about that."
 780 IF INKEY$ <>"" THEN GO TO 780
 790 PAUSE 0:GO TO 90

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.