This article is part of a series. Be sure to check out part 1, part 2, part 3, part 4 and part 5.
Here is a new word wrap test program. It has new test string cases, and now reports the code space used and variable memory used in addition to time. In order to properly report code space, it may require some tweaking (unless you have it entered 100% byte-for-byte like I typed it). I will make a .DSK image available for download soon.
Your submission should be a subroutine that starts at line 1 and expects A$ to be the string to word wrap, WD to be the screen width to wrap to, and RETURNs and the end back to the caller.
The new test program records the start and end time (to determine speed), start and end memory (to determine variable usage), and displays the code size of the program minus the number of bytes of the test program (line 0, lines 100-end). It has the size of the “empty” test program (nothing from line 1-99) hard coded so it can reflect the overhead of your routine in those lines.
NOTE: The memory usage shown by this program is just variables, and not string space. Each variable used takes 7 bytes, and string data goes in the CLEAR xxx block of memory. If memory used shows 16, but you had to do a CLEAR 600 to make your routine work, you do require more than 16 bytes but I couldn’t
Configuring the Test
- CODE SPACE: The code space value printed is hard coded to subtract the size of the test program with a value in line 260. If you retype the test program and change any spaces or anything that would alter the size, that constant value needs to be adjusted. You want it to print 0 when you have nothing in lines 1-99 and type GOTO 280. If it does not print 0, adjust the value subtracted at the end of line 280. (If it prints 4, add 4 to the value that is there. If it prints -2, subtract 2.)
- MEMORY: If your program uses more than the default 200 bytes reserved for variables, adjust the CLEAR command in LINE 100. If you are pre-DIMensioning variables you plan to use, you can also add them to LINE 100 but this will count against your code size. It is a good thing to do for speed.
The test program will perform the following tests:
- An empty string.
- A short string that does not need to word wrap.
- A multi-line string of words that will need to word wrap. Its has words with characters ending in position 32 to test if the wrap routine uses that column without skipping extra spaces between lines.
- A string with a word longer than 32 characters and one longer than 64 characters to test chopping of long words (where it just splits it in the middle).
I believe these will test all possible conditions, and will help us compare all the versions for code size, variable usage and execution speed.
WWTEST10.BAS – Version 1.0
0 GOTO 100:REM WW-TEST 1.0 100 CLS:CLEAR 200:DIM A$,M1,M2,T1,T2,WD 110 INPUT"SCREEN WIDTH ";WD 120 IF WD=0 THEN WD=32 130 TIMER=0:T1=TIMER 140 M1=MEM 150 PRINT "EMPTY STRING:" 160 A$="":GOSUB 1 170 PRINT "SHORT STRING:" 180 A$="THIS SHOULD NOT NEED TO WRAP.":GOSUB 1 190 PRINT "LONG STRING:" 200 A$="THIS IS A STRING WE WANT TO WORD WRAP. EACH LINE CONTAINS EXACTLY 32 CHARACTERS. IT SHOULD USE THE LAST COLUMN AND SHOW FOUR LINES.":GOSUB 1 210 PRINT "WORD > WIDTH:" 220 A$="SUPERCALIFRAGILISTICEXPIALIDOCIOUS IS A WORD TOO LONG TO FIT ON ONE LINE. THIS ONE TAKES OVER TWO: ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890. DID IT WORK?":GOSUB 1 230 A$="" 240 T2=TIMER 250 PRINT"TIME TAKEN:"T2-T1 260 M2=MEM 270 PRINT"MEMORY USE:"M1-M2 280 PRINT"CODE SPACE:"PEEK(27)*256+PEEK(28)-PEEK(25)*256+PEEK(26)-767 290 END
Allen Huffman version 1 (MID$):
1 IFA$=""THENPRINT:RETURNELSEZS=1 2 ZE=LEN(A$):IFZE-ZS+1<=WD THENPRINTMID$(A$,ZS,ZE-ZS+1);:IFZE-ZS+1<WD THENPRINT:RETURN 3 FORZE=ZS+WD TOZS STEP-1:IFMID$(A$,ZE,1)<>" "THENNEXT:ZC=0ELSEZE=ZE-1:ZC=1 4 IFZE<ZS THENZE=ZS+WD-1 5 PRINTMID$(A$,ZS,ZE-ZS+1);:IFZE-ZS+1<WD THENPRINT 6 ZS=ZE+1+ZC:GOTO2
Allen Huffman version 2 (LEFT$/RIGHT$) – required additional string space:
1 IFA$=""THENPRINT:RETURN 2 ZE=LEN(A$):IFZE<=WD THENPRINTA$;:IFZE<WD THENPRINT:RETURN 3 FORZE=WD+1TO1STEP-1:IFMID$(A$,ZE,1)<>" "THENNEXT:ZP=0ELSEZE=ZE-1:ZP=1 4 IFZE=0THENZE=WD 5 PRINTLEFT$(A$,ZE);:IF ZE<WD THENPRINT 6 A$=RIGHT$(A$,LEN(A$)-ZE-ZP):GOTO2
Jim Gerrie version 3 (does not use the last character of the row):
1 C1=1:CC=WD+1 2 CC=CC-1:ON-(MID$(A$,CC,1)<>""ANDMID$(A$,CC,1)<>" "ANDCC>C1)GOTO2:C2=CC-C1:IFCC=C1 THENC2=31:CC=C1+WD-2 3 PRINTMID$(A$,C1,C2):C1=CC+1:CC=C1+WD:ON-(C1<=LEN(A$))GOTO2:RETURN
Darren Atkinson version 1 (VARPTR):
1 C1=1:CC=WD+2:VP=VARPTR(A$):VP=PEEK(VP+2)*256+PEEK(VP+3)-1:LN=LEN(A$)-1:SP=32 2 CC=CC-1:IFCC<LN ANDPEEK(VP+CC)<>SP ANDCC>C1 THEN2ELSEC2=CC-C1:IFCC=C1 THENC2=WD:CC=C1+WD-1 3 PRINTMID$(A$,C1,C2);:C1=CC+1:CC=C1+WD:IFC2<>WD ORLN+1<WD THENPRINT 4 IFC1<LN THEN2ELSERETURN
Darren Atkinson version 2 (INSTR):
1 ST=1:LN=LEN(A$)+1:FORPP=1TOLN:LW=INSTR(PP,A$," "):IFLW THENIFLW-ST<WD THENPP=LW:NEXTELSEELSEPRINTMID$(A$,ST):RETURN 2 IFLW-ST=WD THENPRINTMID$(A$,ST,LW-ST);:PP=LW:ST=LW+1:NEXTELSEIFPP<>ST THENPRINTMID$(A$,ST,PP-ST-1):ST=PP:PP=PP-1:NEXTELSEPRINTMID$(A$,ST,LW-ST)" ";:PP=LW:ST=LW+1:NEXT
Current Results (Time/Mem/Code)
- AH1 – 129 / 21 / 228
- AH2 – 119 / 14 / 186 * actually 114 memory (CLEAR 300)
- JG3 – 308 / 21 / 164
- DA1 – 260 / 42 / 224
- DA2 – 72 / 28 / 219
Fastest: Darren Atkinson’s #2
Lowest Memory Usage: Allen Huffman’s #1 and Jim Gerrie’s #3.
Smallest Code Space: Jim Gerrie’s #3.