RosettaCodeData/Task/Chaocipher/Forth/chaocipher.fth

78 lines
3.1 KiB
Forth
Raw Permalink Normal View History

2026-04-30 12:34:36 -04:00
\ triple words
: 3drop drop drop drop ; ( n1 n2 n3 ---)
: 3dup >r over over r@ rot rot r> ; ( n1 n2 n3 -- n1 n2 n3 n1 n2 n3)
\ ASCIIZ string words
: zstring create chars allot ; ( a1 -- a1 n1)
: zcount dup begin dup c@ while char+ repeat over - ;
: zplace over chars over + >r swap cmove 0 r> c! ;
: +zplace zcount chars + zplace ; ( a1 n1 a2 --)
\ find character in string
: where? ( c a1 n1 -- n2)
0 ?do over over i chars + c@ = if drop i negate leave then loop nip negate ;
64 constant /str \ size of input/output string
27 constant /alpha \ size of alphabet
/str zstring {i} \ input string
/str zstring {o} \ output string
/alpha zstring l \ left alphabet
/alpha zstring r \ right alphabet
/alpha zstring t \ temporary alphabet
: [] chars + ; ( a n -- a+n)
: .tab 9 emit ; ( --)
: .list cr .tab zcount type cr ; ( a --)
: PermuteLeft ( index --)
26 over ?do t over negate i + [] l i [] c@ swap c! loop
dup 0 ?do t over negate 26 i + + [] l i [] c@ swap c! loop drop
t char+ c@ >r t 2 [] dup char- 12 cmove r> t 13 [] c! t zcount l zplace
;
: PermuteRight ( index --)
26 over ?do t over negate i + [] r i [] c@ swap c! loop
dup 0 ?do t over negate 26 i + + [] r i [] c@ swap c! loop drop
t c@ >r t char+ dup char- 25 cmove r> t 25 [] c!
t 2 [] c@ >r t 3 [] dup char- 11 cmove r> t 13 [] c! t zcount r zplace
;
: Encrypt ( input output index1 -- index2)
>r swap r@ [] c@ r /alpha where? dup 0< abort" Corrupt right alphabet"
l over [] c@ rot r> [] c!
;
: Decrypt ( input output index1 -- index2)
>r swap r@ [] c@ l /alpha where? dup 0< abort" Corrupt left alphabet"
r over [] c@ rot r> [] c!
;
: chao ( i o xt f --)
s" HXUCZVAMDSLKPEFJRIGTWOBNYQ" l zplace
s" PTLNBQDEOYSFAVZKGJRIHWXUMC" r zplace
t /alpha erase >r \ erase temporary string
( i o xt R: f)
r@ if cr ." The left and right alphabets after each permutation:" cr then
>r over r> swap zcount 1- nip >r ( i o xt R: f len)
0 begin ( i o xt 0 R: f len)
r> r@ if l zcount type 2 spaces r zcount type cr then >r
>r 3dup r@ swap execute r> dup r@ <
while ( i o xt 0 R: f len)
>r dup PermuteLeft PermuteRight r> 1+
repeat rdrop rdrop drop drop 3drop
;
: main
s" WELLDONEISBETTERTHANWELLSAID" {i} zplace
{o} /str erase \ initialize output string
." The original plaintext is :" {i} .list
{i} {o} ['] Encrypt true chao
cr ." The ciphertext is :" {o} .list
{o} {i} ['] Decrypt false chao
cr ." The recovered plaintext is :" {i} .list
;
main