It was 50 years ago this year when the Fortran 66 standard was published. Once you fix the backwardness of the text and the single-character typo in every line, you will get a working Fortran 66 program. Some relevant details:
- If suitable packages are installed, you can compile it on a Linux system with g77 -ff66 source.f which will generate a program a.out which you can run.
- Fortran 66 did not have the concept of opening named files. The program writes its output to unit 42, which might have been a printer, teletype, or even a card punch. On modern computers, this gets written to a file named fort.42 in your current directory.
- All that 1HA, 1HB, ... nonsense is Hollerith string data. Fortran did not get the CHARACTER data type until Fortran 77, and they stored characters in any available variable (usually an array of integers, as many per integer as the machine allowed, though storing just one per integer like this program does was permitted). The number before the H indicated how many of the characters immediately after the H were read as string data. The A specifier in the FORMAT statement prints the Hollerith strings.
- Except in Hollerith strings, and in the first 6 characters of a line, spaces did not matter in Fortran 66. You could insert them anywhere, even inside reserved words.
- Only the first 72 characters in each line counted. When Fortran programs were stored on 80-column punch cards, the last 8 columns were often used to store line numbers which could be used to properly re-sort the program if it spilled (there were even machines for this specific purpose). Those line numbers often survived into versions of the code long after punch cards were no longer used.
- The first character was reserved for a comment indicator, which is not used in this program. The second through fifth were used to store statement labels which code keywords such as DO and GOTO jumped to. The sixth, if it contained any character but 0 or space, indicated the line was a continuation of the previous line. One of these occurs in the DATA statement and you can use it to confirm the column positioning.
As suggested in the flavor text, exactly one character in each line of the program is incorrect. When you succeed in correcting the code, you will get this program:
SUBROUTINE OUTPUT(X,R,L) 00000007
IN TEGER X(L),R(L),L,B(28),J 00000008
DATA B/1HA,1HB,1HC,1HD,1HE,1HF,1HG,1HH,1HI,1HJ,1HK,1HL,1HM,1HN, 00000009
1 1HO,1HP,1HQ,1HR,1HS,1HT,1HU,1HV,1HW,1HX,1HY,1HZ,1H ,1H,/ 00000010
10 FORMAT(45A1) 00000011
DO 20 J=1,L 00000012
R(J)=B(X(J)) 00000013
20 CONTINUE 00000014
WRITE(42,10)R 00000015
END 00000016
SUB ROUTINE DECODE(L,C,N,MSG) 00000017
IN TEGER L,C(L),MDL,MSG(L),PRD,I,J 00000018
DO 40 J=1,L 00000019
MSG(J)=C(J) 00000020
PRD=C(J) 00000021
DO 30 I=1,4 00000022
PRD=MOD(PRD*PRD,N) 00000023
30 CONTINUE 00000024
MSG(J)=MOD(MSG(J)*PRD,N) 00000025
40 CON TINUE 00000026
END 00000027
SUBROUTINE UNCOMP(L,B,Z,MSG,MDL) 00000028
INTEGER L,B,MDL,Z(B),MSG(L),J 00000029
DO 50 J=1,L 00000030
Z(J*3)=MOD(MSG(J),MDL) 00000031
Z(J*3-1)=MOD(MSG(J)/MDL,MDL) 00000032
Z(J*3-2)=MSG(J)/MDL/MDL 00000033
50 CONTINUE 00000034
END 00000035
INTEGER FUNCTION FFOS(N) 00000036
INTEGER J 00000037
FFOS=1 00000038
DO 60 J=1,N 00000039
FFOS=FFOS*J 00000040
60 CONTINUE 00000107
RETURN 00000108
END 00000109
INTEGER FUNCTION FIM(N) 00000110
INT EGER LAST,J,TMP 00000111
LAST=0 00000112
FIM=1 00000113
DO 70 J=2,N 00000114
TMP=LAST 00000115
LAST=FIM 00000116
FIM=TMP+LAST 00000117
70 CONTINUE 00000118
RETURN 00000119
END 00000120
INTEGER FUNCTION PUL(N) 00000121
INTEGER LAST,J,TMP 00000122
LAST=2 00000123
PUL=1 00000124
DO 80 J=2,N 00000125
TMP=LAST 00000126
LAST=PUL 00000127
PUL=TMP+LAST 00000128
80 CONTINUE 00000129
RETURN 00000130
END 00000131
INTEGER FUNCTION CANK(J,K) 00000132
INTEGER I,J,K,FFOS 00000133
CANK=1 00000134
DO 90 I=1,K 00000135
CANK=CANK*(J+1-I) 00000136
90 CONTINUE 00000137
CANK=CANK/FFOS(K) 00000138
RETURN 00000139
END 00000140
INTEGER Z(45),Q(45),I,C(15),MSG(15),N,JET,FFOS,FIM,IE,CANK,PUL 00000207
REAL ELG 00000208
IBENJ(ELG)=INT(EXP(ELG)) 00000209
C(1)=FIM(24) 00000210
C(4)=PUL(2)+FFOS(4)*FFOS(2) 00000211
C(2)=FFOS(5)*FIM(11) 00000212
C(7)=IBENJ(4.0)*FIM(15) 00000213
C(11)=CANK(16,7) 00000214
C(6)=CANK(15,7)+CANK(14,6) 00000215
C(3)=IBENJ(7)*FFOS(4) 00000216
C(13)=C(11)+IBENJ(9) 00000217
C(15)=PUL(21)+CANK(14,7) 00000218
C(8)=C(1)-PUL(19) 00000219
C(12)=PUL(20)+CANK(17,4)+IBENJ(6.0)+PUL(9)-FFOS(1) 00000220
C(13)=C(13)+PUL(10)+PUL(8)+IBENJ(4) 00000221
C(6)=C(6)+PUL(5)+IBENJ(3) 00000222
JET=FFOS(4)+FIM(5) 00000223
C(15)=C(15)+PUL(10)+IBENJ(4)+CANK(4,2) 00000224
C(8)=C(8)-PUL(16)/FIM(3)-PUL(9)-IBENJ(0.0) 00000225
N=FFOS(8)+FIM(17)+3*FFOS(CANK(4,3)) 00000226
C(11)=C(11)-FIM(16)+IBENJ(4)+FFOS(3) 00000227
C(5)=FIM(23)+FIM(19)-IBENJ(6.0)-FIM(7)+FIM(3) 00000228
C(14)=IBENJ(10.0)-IBENJ(4.0)-IBENJ(0.0) 00000229
C(9)=FIM(10)+FIM(24)/FIM(3)-FFOS(4)/FIM(3) 00000230
C(4)=C(4)*(IBENJ(5)-CANK(6,3))+MOD(C(2),2) 00000231
C(7)=C(7)+CANK(13,5)+PUL(5)+1+CANK(8,2) 00000232
C(3)=CANK(11,5)+FFOS(2)+C(3) 00000233
C(10)=FFOS(8)+IBENJ(PUL(4))+IBENJ(5)+FIM(4) 00000234
C(1)=C(1)-IBENJ(9.0)+3*FIM(12)+PUL(5)-FIM(3) 00000235
C(2)=C(2)+IBENJ(6.0)+PUL(2)**FFOS(2) 00000236
CALL DECODE(15,C,N,MSG) 00000237
CALL UNCOMP(15,45,Z,MSG,JET) 00000238
CALL OUTPUT(Z,Q,45) 00000239
END 00000240
It prints one line of output:
OVERPUNCH TYPOS AND CORRECTIONS, THEN OVERLAY
Hopefully you were keeping track of where all those typos were in the code. It's finally time to use those three punch cards (the spooky, backward punch cards which have the upper-right corner cut instead of the upper-left corner). The line numbers (which start at 7, 107, and 207 on each page of the program) should suggest that you start a new card for each printed page, and that you start punching in column 7. The punching format is the standard one for these cards.
The correct letters and typos, per line, are:
- page/card 1: SC, EI, AE, 19, OE, JZ, JD, CM, RH, DZ, RP, NF, OP, SU, DO, OD, RO, UH, PW, UG, DZ, UW, GX, DG, DB, ZY, DZ, UA, EA, OF, NM, SG, DG, OL
- page/card 2: OA, TB, EA, GJ, EA, AO, MX, OT, AI, MB, PI, OA, TX, DB, FJ, PO, SZ, LQ, DT, TS, LZ, LF, CG, RP, ER, TH, TK, AO, OJ, CY, OD, FP, RP, DO
- page/card 3: GE, RH, JT, FA, ST, SA, EU, CY, KZ, OU, BX, UW, PY, KE, UV, UW, FI, PY, UA, CR, IO, FR, JX, MG, KT, CS, SO, JT, UA, PN, AU, NX, PO, EW
Although there were variations with some symbols, the notation for letters and numbers needed here was consistent, and can be found in the Wikipedia article on punch cards.
The program output tells you that you need to overpunch the cards, punching the same card twice, once with the typos and once with the corrections. This will give you cards that may have up to four punches in some columns.
If done correctly, when you overlay the three cards, there will be one hole in many columns where you can see right through all three cards. These holes occur in rows (- for no hole) YY11-143947672-6980-9677-0011-4776.
Further overlay this on the shaded section of the program on page 3, backward (so the cut corner is at the left as it should be, the cards have the printed side down, and characters from the program starting at line 223 show through the holes. Reading column by column, this reads: JEFF SIMONCINI JEFF PAUL PUNK BAND.
This clues the answer, the name of their band, FINAL WARNING.
Program Details
Subroutine OUTPUT does just what its name implies. It takes the L integers in array X and interprets each as an index into the array of characters, B, which contains the alphabet plus a space and a comma, writes the corresponding Hollerith strings into the work array R, and writes it to unit 42.
42 is, of course, the answer to life, the universe, and everything, but was not so until 1979 when Douglas Adams wrote The Hitchhiker's Guide to the Galaxy. Anachronistic! Spooky!
Subroutine DECODE performs a crude RSA decryption of the data it receives, treating each element of the array C as a separate 16-bit message and using a 16-bit key. (Actually 15.5 bit, as the program does not take care to handle the numbers overflowing to negative if they exceed 231-1.) It uses a fixed exponent of 17 which is calculated through repeated squaring and multiplication. And yes, RSA in 1966. More anachronism.
Subroutine UNCOMP unpacks the decrypted message data, in which three numbers for the output have been packed in base 29 into a each element of the INTEGER array.
Functions FFOS, FIM, PUL, and CANK are factorial, Fibonacci, Lucas, and binomial coefficients, respectively, and statement function IBENJ is just the integer truncation of the exponential function.
The rest of the program builds up the values and key for the encrypted message in a convoluted way. All the typos in these lines are in the names of the functions.