\ HEXADOKU.FTH by Fred Behringer HEX \ In Turbo-Forth und ZF vorhanden, jedoch nicht ANS \ ------------------------------------------------- : ON ( ad -- ) -1 SWAP ! ; : OFF ( ad -- ) 0 SWAP ! ; \ Matrixaufbau \ ------------ \ Alle Bearbeitungen (Zeilen-/Spalten-Vertauschung etc) nur fuer MATRIX. \ Bei VORGABE wird zunaechst MATRIX nach V-MATRIX kopiert und die Vorgabewerte \ werden in MATRIX gesammelt. \ XCH-M tauscht MATRIX und V-MATRIX gegeneinander aus. \ Hexadoku-Matrix, zeilenweise, pro Element ein Byte VARIABLE MATRIX 0FF ALLOT \ Vorgabe-Matrix, vom selben Aufbau wie MATRIX VARIABLE V-MATRIX 0FF ALLOT \ MATRIX nach V-MATRIX kopieren : CPY-M ( -- ) 100 0 DO MATRIX I + C@ V-MATRIX I + C! LOOP ; \ MATRIX mit V-MATRIX vertauschen : XCH-M ( -- ) 100 0 DO MATRIX I + C@ V-MATRIX I + C@ MATRIX I + C! V-MATRIX I + C! LOOP ; \ MATRIX zu etwa 50% mit vorgegebenen Elementen belegen \ seed = Anfangsbyte im RAM fuer Zufallsauswahl \ Kleinerer Belegungsprozentsatz gelingt durch mehrfache Anwendung : AUSWAHL ( seed -- ) 100 0 DO DUP I + C@ 1 AND 0= IF 20 I MATRIX + C! THEN LOOP DROP ; \ Vorher MATRIX sichern : VORGABE ( seed -- ) CPY-M AUSWAHL XCH-M ; \ MATRIX-Elemente \ --------------- \ Adresse ad[ij] von Element a[ij] in MATRIX, i = Zeile, j = Spalte : AD[IJ] ( i j -- ad[ij] ) SWAP 10 * + MATRIX + ; \ Hole Element a[ij] von MATRIX : A[IJ]@ ( i j -- a[ij] ) AD[IJ] C@ ; \ Speichere Element a[ij] nach MATRIX : A[IJ]! ( a[ij] i j -- ) AD[IJ] C! ; \ Zeilen und Spalten \ ------------------ \ Hole Zeile i von MATRIX, letztes Element zuerst auf Stack, I=j ! : A[I.]@ ( i -- a[i.] ) 00 0F DO DUP I A[ij]@ SWAP -1 +LOOP DROP ; \ Hole Spalte j von MATRIX, letztes Element zuerst auf Stack, I=i ! : A[.J]@ ( j -- a[.j] ) 00 0F DO I OVER A[IJ]@ SWAP -1 +LOOP DROP ; \ Speichere Zeile i von MATRIX, juengstes Stack-Element zuerst ins RAM, I=j ! : A[I.]! ( a[i.] i -- ) 10 00 DO SWAP OVER I A[IJ]! LOOP DROP ; \ Speichere Spalte j von MATRIX, juengstes Stack-Element zuerst ins RAM, I=i ! : A[.J]! ( a[i.] j -- ) 10 00 DO SWAP OVER I SWAP A[IJ]! LOOP DROP ; \ Rotationen und Konstantenaddition \ --------------------------------- \ Linksrotation der Zeile i von MATRIX um 1 Spalte : ROL1[I.] ( i -- ) >R R@ 0 A[ij]@ R@ A[i.]@ DROP R> A[i.]! ; \ Linksrotation der Zeile i von MATRIX um 4 Spalten : ROL4[I.] ( i -- ) 4 0 DO DUP ROL1[I.] LOOP DROP ; \ Addition von 4*n zu saemtlichen Elementen von MATRIX : ADD4 ( n -- ) 4 * 100 0 DO DUP MATRIX I + C@ + 10 MOD MATRIX I + C! LOOP DROP ; \ Rechtsrotation der Zeile i von MATRIX um 1 Spalte : ROR1[I.] ( i -- ) >R R@ A[i.]@ R@ 0F A[ij]@ R> A[i.]! DROP ; \ Rechtsrotation der Zeile i von MATRIX um 4 Spalten : ROR4[I.] ( i -- ) 4 0 DO DUP ROR1[I.] LOOP DROP ; \ Bildschirmdarstellungen \ ----------------------- \ Spaltensprung : J+ ( i -- ) DUP 0> SWAP 4 MOD 0= AND IF SPACE THEN ; \ ASCII --> Ziffernausgabe : ZIFF ( n i -- ) J+ DUP 0F U> IF EMIT SPACE ELSE . THEN ; \ Zeilensprung : I+ ( i -- ) DUP 0> SWAP 4 MOD 0= AND IF CR THEN ; \ Bildschirmdarstellung von MATRIX : .M ( -- ) 10 0 DO I I+ CR I A[I.]@ 10 0 DO I ZIFF LOOP LOOP ; \ Bildschirmdarstellung von V-MATRIX : .V ( -- ) CR 10 0 DO I I+ 24 SPACES 10 0 DO V-MATRIX J 10 * + I + C@ I ZIFF LOOP CR LOOP ; \ Bildschirmdarstellung von MATRIX & V-MATRIX : .M&V ( -- ) CR 10 0 DO 10 0 DO MATRIX J 10 * + I + C@ I ZIFF LOOP 5 SPACES 10 0 DO V-MATRIX J 10 * + I + C@ I ZIFF LOOP CR I 1+ I+ LOOP ; \ Abwandlungen von MATRIX \ ----------------------- \ Kanonische Matrix --> MATRIX : KANON ( -- ) 00 0F DO I -1 +LOOP 00 A[I.]! 10 01 DO I 4 MOD 0= IF I 04 - A[I.]@ I A[I.]! I ROL1[I.] ELSE I 01 - A[I.]@ I A[I.]! I ROL4[I.] THEN LOOP ; \ Linkskanonische Matrix --> MATRIX : KANONL ( -- ) KANON ; \ Rechtskanonische Matrix --> MATRIX; entspricht KANON mit ROR statt ROL. : KANONR ( -- ) 00 0F DO I -1 +LOOP 00 A[I.]! 10 01 DO I 4 MOD 0= IF I 04 - A[I.]@ I A[I.]! I ROR1[I.] ELSE I 01 - A[I.]@ I A[I.]! I ROR4[I.] THEN LOOP ; \ Transponierte von MATRIX, a[ij] <--> a[ji] fuer i < j : TRANSP ( -- ) 10 0 DO 10 0 DO I J < IF I J A[IJ]@ J I A[IJ]@ I J A[IJ]! J I A[IJ]! THEN LOOP LOOP ; \ Viererquadrate und Streifen \ --------------------------- \ Aus Zeile/Spalte mach Viererquadrat (0...f) : IJ>V ( i j -- v ) 4 / SWAP 4 / 4 * + ; \ Aus Zeile/Spalte mach Querstreifen (0...3) : IJ>Q ( i j -- q ) DROP 4 / 4 * ; \ Aus Zeile/Spalte mach Laengsstreifen (0...3) : IJ>L ( i j -- l ) NIP 4 / 4 * ; \ Aus Quer/Laengs mach Viererquadrat (0...f) : QL>V ( q l -- v ) SWAP 4 * + ; \ Aus Viererquadrat mach Quer/Laengs (0..3, 0..3) : V>QL ( v -- q l ) 4 /MOD SWAP ; \ Tausche Zeile i1 in MATRIX gegen Zeile i2 : XCHI ( i1 i2 -- ) >R >R R@ A[I.]@ R> R@ SWAP >R A[I.]@ R> A[I.]! R> A[I.]! ; \ Tausche Spalte j1 in MATRIX gegen Spalte j2 : XCHJ ( j1 j2 -- ) >R >R R@ A[.J]@ R> R@ SWAP >R A[.J]@ R> A[.J]! R> A[.J]! ; \ Kehre Zeilenfolge in MATRIX um ( i <--> 0f-i ) : INVERSI ( -- ) 8 0 DO I 0F I - XCHI LOOP ; \ Kehre Spaltenfolge in MATRIX um ( j <--> 0f-j ) : INVERSJ ( -- ) 8 0 DO I 0F I - XCHJ LOOP ; \ Tausche Querstreifen q1 in MATRIX gegen Querstreifen q2 : XCHQ ( q1 q2 -- ) 4 MOD SWAP 4 MOD 4 0 DO 2DUP 4 * I + SWAP 4 * I + XCHI LOOP 2DROP ; \ Tausche Laengsstreifen l1 in MATRIX gegen Laengsstreifen l2 : XCHL ( l1 l2 -- ) TRANSP XCHQ TRANSP ; \ Hauptprogramm: Folge von Hexadokus \ ---------------------------------- \ Zaehler VARIABLE INDEX \ Bildschirmanzeige mit zugehoeriger Loesung (LOES? = ON/OFF)? VARIABLE LOES? LOES? ON \ Default \ Start von HEXA bei kanonischer MATRIX? VARIABLE KANON? KANON? ON \ Default \ Beliebig viele Vorgabematrizen erzeugen und anzeigen. \ Bei LOES? OFF nur Vorgaben, bei LOES? ON auch Loesungen. \ KANON? ON : Start mit kanonischer MATRIX \ Return-Taste oder [q] oder [Q] = raus, andere Taste = naechstes Bild. : HEXA ( -- ) ." Taste oder ( [ret] oder [q] oder [Q] ) druecken!" CR 2000 INDEX ! ( seed zu Beginn der Folge ) KANON? @ IF KANON THEN BEGIN KEY DUP 0D ( [ret] ) = OVER 71 ( q ) = OR SWAP 51 ( Q ) = OR IF EXIT THEN 5 INDEX +! INDEX @ C@ 1 AND IF TRANSP THEN 3 INDEX +! INDEX @ C@ 1 AND IF INVERSI THEN 3 INDEX +! INDEX @ C@ 1 AND IF INVERSJ THEN 3 INDEX +! INDEX @ C@ INDEX @ 1+ C@ XCHQ 3 INDEX +! INDEX @ C@ INDEX @ 1+ C@ XCHL 3 INDEX +! INDEX @ C@ ADD4 3 INDEX +! INDEX @ C@ 4 / 4 * 10 MOD DUP INDEX @ 1+ C@ 4 MOD + SWAP INDEX @ 2 + C@ 4 MOD + XCHI 5 INDEX +! INDEX @ C@ 4 / 4 * 10 MOD DUP INDEX @ 1+ C@ 4 MOD + SWAP INDEX @ 2 + C@ 4 MOD + XCHJ 5 INDEX +! INDEX @ VORGABE LOES? @ IF .M&V ELSE .V THEN CR ." Weiter mit Taste, raus mit [ret] oder [q] oder [Q] !" AGAIN ; \ Zulaessigkeitspruefungen \ ------------------------ \ Tritt n in Zeile i mindestens zweimal auf ? Meldung, wenn ja. \ Funktioniert auch fuer Leerstellen (n=20h) : 2*INI? ( n i -- ) INDEX OFF 10 * MATRIX + 10 0 DO 2DUP I + C@ = IF 1 INDEX +! THEN LOOP 2DROP INDEX @ 1 > ABORT" Mindestens zweimal!" ; \ Tritt n in Spalte j mindestens zweimal auf ? Meldung, wenn ja. \ Funktioniert auch fuer Leerstellen (n=20h) : 2*INJ? ( n j -- ) TRANSP 2*INI? TRANSP ; \ Tritt n im Viererquadrat v mindestens zweimal auf ? \ Funktioniert auch fuer Leerstellen (n=20h) : 2*INV? ( n v -- ) INDEX OFF V>QL SWAP 10 * + 4 * MATRIX + 4 0 DO 2DUP I + C@ = IF 1 INDEX +! THEN LOOP 10 + 4 0 DO 2DUP I + C@ = IF 1 INDEX +! THEN LOOP 10 + 4 0 DO 2DUP I + C@ = IF 1 INDEX +! THEN LOOP 10 + 4 0 DO 2DUP I + C@ = IF 1 INDEX +! THEN LOOP 10 + 2DROP INDEX @ 1 > ABORT" Mindestens zweimal!" ; \ Ist MATRIX zulaessig? Meldung, wenn nicht. : MOK? ( -- ) 10 0 DO 10 0 DO J I 2*INI? LOOP LOOP 10 0 DO 10 0 DO J I 2*INJ? LOOP LOOP 10 0 DO 10 0 DO J I 2*INV? LOOP LOOP ; \ finis