Tuesday, October 1, 2013

INTERCAL - Doing Problem 17, the hard way

There are a lot of crazy languages out there. Most of the crazier languages I have used were invented sometime in the last decade, by crazy people who wanted to see what would be hard to write a compiler for or just to have fun, etc, etc. INTERCAL is not like those languages. INTERCAL was written in 1972 at Princeton in order to be as different from other languages as possible. I will admit that I took a wimpy approach to INTERCAL: the language has two binary operators, mingle ($), which makes a 32-bit value out of 2 16-bit values and alternating the digits, and select (~) which takes the bits of the right value where the left has 1's and shifts all those to the right to form a number. I did not put up with these or the unary or, and + xor, which operate on alternating digits. Instead, I used the standard libraries. With the Standard libraries, Adding two numbers is as simple as a DO (1509) NEXT instruction while the numbers you want to add are in :1 and :2 (those being variable names).

Anyway, despite ignoring those variables, there were plenty of difficulties. INTERCAL has no ifs, no gotos, no most anything that is in any other language. There are only NEXT instructions which push instructions onto a call stack, where they can be manipulated with FORGET or RESUME, and, of course, everyone's favorite, COME FROM (the opposite of GO TO, which is not in the language).

So, with all of these fun things to keep up with, there are some even more fun things in INTERCAL: the errors. Among the compile and run time errors I had to solve while writing this program were

THE NEXT STACK RUPTURES. ALL DIE. OH, THE EMBARRASSMENT!
WHAT BASE AND/OR LANGUAGE INCLUDES 23?
RANDOM COMPILER BUG
PROGRAM HAS GOTTEN LOST ON THE WAY TO WHO KNOWS WHERE
PROGRAM HAS DISAPPEARED INTO THE BLACK LAGOON
THROW STICK BEFORE RETRIEVING!
YOU MUST LIKE THIS LABEL A LOT!
PROGRAMMER IS INSUFFICIENTLY POLITE

And that isn't even all of them. The last one has a particularly good story: all INTERCAL commands must be prefixed with either DO, PLEASE, or PLEASE DO. Put too many PLEASEs, you get an error for being overly polite, too few, insufficiently polite: the programmer must remember to keep a delicate balance.
This INTERCAL program is the result of about 4 days of working with the language, with varying degrees of effort on those days. This is not only the first and longest INTERCAL program I have written, but it is actually as of now the longest Project Euler solution I have written. This solution opens up ELM, the language I previously solved problem 17 in, so be on the lookout for the next appearance of that functional language that compiles to html and Javascript.
(3)     DO NOT GIVE UP
(2000)  PLEASE NOTE THIS IS A MODULUS FUNCTION
        DO STASH :1 + :2 + :196
        DO (1550) NEXT
        DO :196 <- :1
PLEASE  DO :1 <- :3
        DO (1540) NEXT
        DO :197 <- :2
PLEASE  DO :1 <- :196
        DO :2 <- :3
        DO (1510) NEXT
        DO RETRIEVE :1 + :2 + :196
PLEASE  RESUME #1

(2010)  PLEASE DO NOTE THIS FCN GIVES SINGLE DIGIT LETTERS
        DO NOTE :2 <- LETTERS(:1)
        DO STASH :1 + :3 + :4
(19)    DO (18) NEXT
(29)    DO :2 <- #4
(18)    DO (17) NEXT
(28)    PLEASE DO :2 <- #5
(17)    DO (16) NEXT
(27)    DO :2 <- #5
(16)    DO (15) NEXT
(26)    PLEASE DO :2 <- #3
(15)    DO (14) NEXT
(25)    DO :2 <- #4
(14)    DO (13) NEXT
(24)    DO :2 <- #4
(13)    PLEASE DO (12) NEXT
(23)    DO :2 <- #5
(12)    DO (11) NEXT
(22)    DO :2 <- #3
(11)    DO (10) NEXT
(21)    DO :2 <- #3
(10)    DO (100) NEXT
(20)    DO :2 <- #0
(100)   PLEASE DO :2 <- #1
        DO (1509) NEXT
        DO :1 <- :3
        PLEASE RESUME :1
        DO COME FROM (29)
        DO COME FROM (28)
        DO COME FROM (27)
PLEASE  DO COME FROM (26)
        DO COME FROM (25)
        DO COME FROM (24)
        DO COME FROM (23)
        DO COME FROM (22)
        DO COME FROM (21)
        DO COME FROM (20)
        DO :4 <- :2
        DO :2 <- :1
        DO :1 <- #10
        DO (1510) NEXT
        DO :2 <- :4
PLEASE  DO FORGET :3
        DO NOT RETRIEVE :1 + :3 + :4
PLEASE  RESUME #1

(2020)  DO NOTE THIS FCN GIVES TWO DIGIT LETTERS
        DO NOTE :2 <- LETTERS(:1)
        PLEASE STASH :1 + :3 + :4 + :5 + :6 + :7 + :14
(39)    DO (38) NEXT
(49)    DO :5 <- #6
(38)    DO (37) NEXT
(48)    DO :5 <- #6
(37)    DO (36) NEXT
(47)    PLEASE DO :5 <- #7
(36)    DO (35) NEXT
(46)    DO :5 <- #5
(35)    DO (34) NEXT
(45)    DO :5 <- #5
(34)    DO (33) NEXT
(44)    PLEASE DO :5 <- #5
(33)    DO (32) NEXT
(43)    DO :5 <- #6
(32)    DO (31) NEXT
(42)    PLEASE DO :5 <- #6
(31)    DO (30) NEXT
(41)    DO (2030) NEXT
(30)    DO (200) NEXT
(40)    DO :5 <- #0
(200)   PLEASE DO :2 <- #10
        DO :14 <- :1
        DO (1550) NEXT
        DO :1 <- :3
        DO :2 <- #1
        DO (1509) NEXT
        DO :7 <- :3
PLEASE  RESUME :7 
        DO COME FROM (49)
        DO COME FROM (48)
        DO COME FROM (47)
        DO COME FROM (46)
        DO COME FROM (45)
PLEASE  DO COME FROM (44)
        DO COME FROM (43)
        DO COME FROM (42)
        DO COME FROM (40)
PLEASE  DO :1 <- :14
        DO :2 <- #10
        DO (2000) NEXT
PLEASE  DO :1 <- :3
        DO (2010) NEXT
        DO :1 <- :5
        DO (1509) NEXT
PLEASE  DO COME FROM (41)
        DO :6 <- :3
        DO :2 <- :7
        DO :1 <- #10
PLEASE  DO (1510) NEXT
        DO FORGET :3
        DO :2 <- :6
        DO RETRIEVE :1 + :3 + :4 + :5 + :6 + :7 + :14
PLEASE  RESUME #1

(2030)  DO NOTE THIS IS THE TEENS FUNCTION
        DO NOTE :3 <- LETTERS(:14)
        DO STASH :1 + :2 +  :5 + :6
(59)    DO (58) NEXT
(69)    DO :6 <- #8
(58)    DO (57) NEXT
(68)    DO :6 <- #8
(57)    DO (56) NEXT
(67)    DO :6 <- #9
(56)    DO (55) NEXT
(66)    PLEASE DO :6 <- #7
(55)    DO (54) NEXT
(65)    DO :6 <- #7
(54)    DO (53) NEXT
(64)    DO :6 <- #8
(53)    DO (52) NEXT
(63)    DO :6 <- #8
(52)    DO (51) NEXT
(62)    PLEASE DO :6 <- #6
(51)    DO (50) NEXT
(61)    DO :6 <- #6
(50)    DO (300) NEXT
(60)    DO :6 <- #3
(300)   DO :1 <- :14
        DO :2 <- #10
PLEASE  DO (2000) NEXT
        DO :1 <- :3
        DO :2 <- #1
        DO (1509) NEXT
PLEASE  RESUME :3
        DO COME FROM (69)
        DO COME FROM (68)
        DO COME FROM (67)
        DO COME FROM (66)
        DO COME FROM (65)
PLEASE  DO COME FROM (64)
        DO COME FROM (63)
        DO COME FROM (62)
        DO COME FROM (61)
PLEASE  DO COME FROM (60)
        DO :2 <- :3
        DO :1 <- #10
        DO (1510) NEXT
        DO FORGET :3
PLEASE  DO :3 <- :6
        DO RETRIEVE :1 + :2 + :5 + :6
PLEASE  RESUME #1

(2040)  PLEASE DO NOTE THIS IS THE EVERYTHING FCN
        DO NOTE :6 <- LETTERS(:1)
        DO STASH :1 + :2 + :3 + :5 + :7
        DO :5 <- :1
(101)   DO (102) NEXT
(111)   DO NOT GIVE UP
(102)   DO (103) NEXT
        DO FORGET #1
PLEASE  DO :1 <- :5
        DO (2020) NEXT
(112)   DO :6 <- :2
(103)   PLEASE DO :1 <- :5
        DO :2 <- #100
        DO (1550) NEXT
        DO :1 <- :3
        DO :2 <- :3
        DO (1550) NEXT
PLEASE  DO :1 <- :3
        DO :2 <- #1
        DO (1509) NEXT
        DO RESUME :3   
        DO COME FROM (111)
        DO :1 <- :5
        DO :2 <- #100
        DO (1550) NEXT
        DO :1 <- :3
PLEASE  DO (2010) NEXT
        DO :6 <- :2
        DO :1 <- :6
        DO :2 <- #7
        DO (1509) NEXT
PLEASE  DO :6 <- :3
(90)    DO (91) NEXT
        DO :1 <- :6
        DO :2 <- #3
        DO (1509) NEXT
PLEASE  DO :6 <- :3
        DO :1 <- :5
        DO :2 <- #100
        DO (2000) NEXT
        DO :1 <- :3
        DO (2020) NEXT
PLEASE  DO :1 <- :6
        DO (1509) NEXT
(96)    DO :6 <- :3
(91)    DO (92) NEXT
(95)    DO FORGET #1
(92)    DO :1 <- :5
        DO :2 <- #100
        DO (2000) NEXT
        DO :1 <- :3
PLEASE  DO :2 <- :3
        DO (1550) NEXT
        DO :1 <- :3
        DO :2 <- #1
PLEASE  DO (1509) NEXT
        DO RESUME :3
        DO COME FROM (95)
        DO COME FROM (96)
        DO COME FROM (112)
        DO RETRIEVE :1 + :2 + :3 + :5 + :7
PLEASE  RESUME #1

        DO NOTE THIS IS MAIN
        DO COME FROM (3)
        DO :206 <- #11
        DO :205 <- #1
(70)    DO (71) NEXT
(80)    DO READ OUT :206
(71)    DO (72) NEXT
PLEASE  DO :1 <- :205
        DO (2040) NEXT
        DO :1 <- :205
PLEASE  DO :2 <- #1
        DO (1509) NEXT
        DO :205 <- :3
PLEASE  DO :1 <- :6
        DO :2 <- :206
        DO (1509) NEXT
        DO :206 <- :3
PLEASE  DO FORGET #2
        DO (70) NEXT
(72)    DO :1 <- :205
        DO :2 <- #1000
        DO (1550) NEXT
PLEASE  DO :1 <- :3
        DO :2 <- #1
        DO (1509) NEXT
        PLEASE RESUME :3
        DO COME FROM (80)
PLEASE  DO GIVE UP        

No comments:

Post a Comment