1 REM Ins{nd av Kristoffer Eriksson <5357> 1986-06-17 01.38.11 100 ! -------------------------------------------------------- 110 ! WILDCARD.BAS - N}gra Wildcardfunktioner j{mf|rda 120 ! F|r ABC800-BASIC, 1986-06-16 130 ! Skrivet och m{tt av Kristoffer Eriksson <5357> 140 ! Kan n}gon komma p} en snabbare rutin i BASIC? 150 ! -------------------------------------------------------- 160 ! 170 ! H{r finns 5 olika testdata att m{ta tiden med. Den wildcardfunktion som 180 ! ska m{tas f}r skrivas in f|r hand i m{tloopen nedan. Alla m{tningar 190 ! gjorda med 20 varv i loopen. 200 ! 210 ! Test 1: Inga wildcards 220 ! Test 2: En stj{rna 230 ! Test 3: Fyra stj{rnor 240 ! Test 4: Fyra stj{rnor, fler "blindg}ngar" i B$ 250 ! Test 5: En stj{rna, mer normal str{ngl{ngd 260 INPUT "Testnr=";T 270 IF T=1 A$="ABCDEFGHIalsbcdkugbllkuflui" : B$="ABCDEFEFGHIalsbcdkugbllkuflui" 280 IF T=2 A$="ABCDEFGHI*bcdefghij" : B$="ABCDEFGHIalsbcdkugllkufluibcdefghij" 290 IF T=3 A$="ABCD*EFGHI*bc*d*j" : B$="ABCDEFGHIalsbcdkugllkufluibcdefghij" 300 IF T=4 A$="ABCD*EFGHI*bc*d*j" : B$="ABCDEFEFGHIalsbcdkugbllkufluibcdjefghij" 310 IF T=5 THEN A$="ABC*DE" : B$="ABCEDE" 320 ! 330 WHILE PEEK(-11)>0 : WEND 340 ; TIME$ PEEK(-11) 350 FOR I=1 TO 20 360 Z=FNWildil(A$,B$) 370 NEXT I 380 ; TIME$ PEEK(-11) 390 END 400 ! FNWild.. (sek) 1 2 3 4 5 410 ! --------------------------------------------------------- 420 ! . Str{ngloop 0.74 6.52 8.33 9.76 0.74 430 ! p Pekloop GOTO 0.55 7.35 8.91 10.42 0.89 440 ! r Helrekursiv 0.54 5.26 5.92 6.00 0.73 450 ! - Helrek INSTR 0.55 2.17(!)1.72 2.48 460 ! ri Helrek INSTRloop 0.55 2.06 1.72 2.25 0.61 470 ! i INSTR 0.13 0.51 1.04 1.38 0.33 480 ! il INSTRloop 0.14 0.56 1.15 1.53 0.37 490 ! 500 ! ASC(X$)=N {r snabbare {n X$='N' eller LEFT$(X$,1)='N' 510 ! RIGHT$(,) och LEFT$(,) {r snabbare {n MID$(,,) 520 ! ASC(RIGHT$(X$,))=N {r snabbare {n MID$(X$,,1)='N' 530 ! LEN(X$)=0 {r snabbare {n X$='' 540 ! A$=B$ {r f|rst}s effektivare ju l{ngre str{ngarna {r 550 ! INSTR(,,,) {r f|rst}s snabbare {n en BASIC-s|kloop 560 ! 570 ! 580 ! --- Str{ngtilldelning i j{mf|relseloop 590 ! 600 DEF FNWild(Wc$,St$) LOCAL W$=80,S$=80 ! W$=20,S$=20 610 IF LEN(St$)=0 IF LEN(Wc$)=0 OR Wc$='*' THEN RETURN -1 ELSE RETURN 0 620 IF LEN(Wc$)=0 THEN RETURN 0 630 W$=Wc$ : S$=St$ 640 WHILE ASCII(W$)=63 OR ASCII(W$)=ASCII(S$) 650 W$=RIGHT$(W$,2) : S$=RIGHT$(S$,2) 660 IF W$=S$ THEN RETURN -1 670 IF LEN(W$)<>0 AND LEN(S$) WEND 680 IF ASCII(W$)<>42 THEN RETURN 0 690 IF LEN(W$)=1 RETURN -1 ! Lika 700 IF FNWild(RIGHT$(W$,2),S$) RETURN -1 710 IF FNWild(W$,RIGHT$(S$,2)) RETURN -1 720 RETURN 0 730 FNEND 740 ! 750 ! 760 ! --- Pekare i str{ng, j{mf|relseloop med GOTO 770 ! 780 DEF FNWildp(Wc$,St$) LOCAL P 790 P=P+1 800 IF P>LEN(St$) IF P>LEN(Wc$) RETURN -1 ELSE 840 810 IF P>LEN(Wc$) THEN RETURN 0 820 IF ASCII(RIGHT$(Wc$,P))=ASCII(RIGHT$(St$,P)) THEN 790 830 IF ASCII(RIGHT$(Wc$,P))=63 THEN 790 840 IF ASCII(RIGHT$(Wc$,P))<>42 THEN RETURN 0 850 IF P=LEN(Wc$) THEN RETURN -1 ! Lika 860 IF FNWildp(RIGHT$(Wc$,P+1),RIGHT$(St$,P)) RETURN -1 870 IF FNWildp(RIGHT$(Wc$,P),RIGHT$(St$,P+1)) RETURN -1 880 RETURN 0 890 FNEND 900 ! 910 ! 920 ! --- Helt rekursiv metod. Slukar minne j{mf|rt med de |vriga, men inte 930 ! s} mycket man skulle kunna tro, eftersom str{ngar |verf|rs med pekare. 940 ! 950 DEF FNWildr(Wc$,St$) 960 IF LEN(St$)=0 IF LEN(Wc$)=0 OR Wc$='*' THEN RETURN -1 ELSE RETURN 0 970 IF LEN(Wc$)=0 THEN RETURN 0 980 IF ASCII(Wc$)=ASCII(St$) RETURN FNWildr(RIGHT$(Wc$,2),RIGHT$(St$,2)) 990 IF ASCII(Wc$)=63 THEN RETURN FNWildr(RIGHT$(Wc$,2),RIGHT$(St$,2)) 1000 IF ASCII(Wc$)<>42 THEN RETURN 0 1010 IF FNWildr(RIGHT$(Wc$,2),St$) RETURN -1 1020 IF FNWildr(Wc$,RIGHT$(St$,2)) RETURN -1 1030 RETURN 0 1040 FNEND 1050 ! 1060 ! 1070 ! --- Rekursiv, men anv{nder INSTR f|r att s|ka efter tecknet efter '*'. 1080 ! Detta spara massor av tid, eftersom INSTR ers{tter an massa BASIC med 1090 ! maskinkod. H{r anv{nds en loop om INSTR inte hittar r{tt vid f|rsta 1100 ! f|rs|ket, men det g}r ungef{r lika snabbt (n}got andra karakt{ristika) 1110 ! att l}ta rutinen anropa sig sj{lv i det l{get, men det drar mer minne. 1120 ! 1130 DEF FNWildri(Wc$,St$) LOCAL P 1140 IF LEN(St$)=0 IF LEN(Wc$)=0 OR Wc$='*' THEN RETURN -1 ELSE RETURN 0 1150 IF LEN(Wc$)=0 THEN RETURN 0 1160 IF ASCII(Wc$)=ASCII(St$) RETURN FNWildri(RIGHT$(Wc$,2),RIGHT$(St$,2)) 1170 IF ASCII(Wc$)=63 THEN RETURN FNWildri(RIGHT$(Wc$,2),RIGHT$(St$,2)) 1180 IF ASCII(Wc$)<>42 THEN RETURN 0 1190 IF LEN(Wc$)=1 THEN RETURN -1 1200 P=INSTR(P+1,St$,MID$(Wc$,2,1)) : IF P=0 THEN RETURN 0 1210 IF FNWildri(RIGHT$(Wc$,2),RIGHT$(St$,P)) RETURN -1 1220 GOTO 1200 1230 ! IF FNWildri(Wc$,RIGHT$(St$,P+1)) RETURN -1 ELSE RETURN 0 1240 FNEND 1250 ! 1260 ! 1270 ! --- Helt INSTR-baserad. Wildcards s|ks upp med INSTR, och delarna 1280 ! d{remellan behandlas som hela str{ngar. Detta |verf|r {nnu mera av 1290 ! jobbet till maskinkod, {ven om rutinen blivit ganska gr|tig. N}got 1300 ! av den rekursiva karakt{ren {r dock kvar. 1310 ! 1320 DEF FNWildi(Wc$,St$) LOCAL P,P2 1330 IF LEN(St$)=0 IF LEN(Wc$)=0 OR Wc$='*' THEN RETURN -1 ELSE RETURN 0 1340 P=INSTR(1,Wc$,"?") 1350 P2=INSTR(1,Wc$,"*") 1360 IF P+P2=0 THEN RETURN Wc$=St$ 1370 IF P IF PLEFT$(St$,P2-1) THEN RETURN 0 1390 IF LEN(Wc$)=P2 THEN RETURN -1 1400 P=P2-1 1410 P=INSTR(P+1,St$,MID$(Wc$,P2+1,1)) : IF P=0 THEN RETURN 0 1420 IF FNWildi(RIGHT$(Wc$,P2+1),RIGHT$(St$,P)) RETURN -1 1430 GOTO 1410 1440 ! IF FNWildi(right$(Wc$,P2),RIGHT$(St$,P+1)) RETURN -1 ELSE RETURN 0 1450 FNEND 1460 ! 1470 ! 1480 ! --- Helt INSTR-baserad, och s} lite rekursiv som m|jligt, utan att 1490 ! |verg} till en datastack. Att nu beh|va anv{nda MID$(), startpekare 1500 ! f|r str{ngarna, och loop, i st{llet f|r rekursion l|nar sig tydligen 1510 ! inte. 1520 ! 1530 DEF FNWildil(Wc$,St$) LOCAL P,P2,P0 1540 IF LEN(St$)=0 IF LEN(Wc$)=0 OR Wc$='*' THEN RETURN -1 ELSE RETURN 0 1550 P0=1 1560 P=INSTR(P0,Wc$,"?") 1570 P2=INSTR(P0,Wc$,"*") 1580 IF P+P2=0 THEN RETURN Wc$=St$ 1590 IF P IF PMID$(St$,P0,P2-P0) THEN RETURN 0 1610 IF LEN(Wc$)=P2 THEN RETURN -1 1620 P=P2-1 1630 P=INSTR(P+1,St$,MID$(Wc$,P2+1,1)) : IF P=0 THEN RETURN 0 1640 IF FNWildil(RIGHT$(Wc$,P2+1),RIGHT$(St$,P)) RETURN -1 1650 GOTO 1630 1660 ! IF FNWildil(right$(Wc$,P2),RIGHT$(St$,P+1)) RETURN -1 ELSE RETURN 0 1670 FNEND 1680 !