FBlag

Artikel mit Tag J

  • Homepage
  • Netzseite

Okt 22: Bringing back the J to Bifid Cipher

As a programming language enthusiast I often examine new (to me) languages, paradigms and concepts. Recently I played with J - sth. like APL with keyboard friendly syntax. If you are familiar with point-free functional programming, J isn't that complicated. More tedious is the used vocabulary (verbs, nouns, frets, agenda, gerunds...) for trivial things and the fact, that you can't use search engines - neither for "J" (-> "site:jsoftware.com"), nor for a function symbol (combination).

Mind bending are the many one-liners and examples in the documentation. And believe me, there isn't much more satisfaction as in unraveling the first lines of J code. ;)

As practical example on "hello world" level I used the Bifid Cipher:

pre=:(]->&9)@-&65@(a.&i.@toupper)
enc=:|:@((%&2@#,2:)$[)@(<.@%&5,5&|)
dec=:((2:,%&2@#)$[)@(<.@%&5,@,.5&|)
pst=:{&a.@(]-<&75)@(5&*@[/+66&+@]/)

encode=:pst@enc@pre
decode=:pst@dec@pre


Keep in mind, this is of course not the shortest or fastest or nicest implementation. It's just my first J program.

A short explanation for the curious

Read from right to left, @ is function composition and & binds a parameter.

pre - prepare our string

1. take a list of characters (the string), convert every character to uppercase (toupper) and look up (&i.) the characters in the ascii table (a.)
   a.&i.@toupper 'hello'

72 69 76 76 79

2. subtract 65 (ascii value of 'A') from every list item (-&65) (a 0..4 indexed cipher table to save some inc- (>:) and decrements (<:))
   -&65@(a.&i.@toupper) 'hello'

7 4 11 11 14

3. and decrement every item greater than 9 (]->&9) for the missing 'J'(!)
   (]->&9)@-&65@(a.&i.@toupper) 'hello'

7 4 10 10 13

The last part needs some explanation. (]->&9) is a so called "monadic fork". We have three functions f (] "identity"), h (- "minus") and g (>&9 "greater than 9") and the constellation as monadic fork (f h g) x executes as h(f(x),g(x)). The comparison gives a list of 0s and 1s, "NB." is line comment:
   NB. the identity (f):
   ] 7 4 11 11 14
7 4 11 11 14
   NB. greater than 9 (g):
   (>&9) 7 4 11 11 14
0 0 1 1 1
   NB. together with minus h(f(x),g(x)):
   (]->&9) 7 4 11 11 14
7 4 10 10 13


enc - encode

1. Now you are familiar with forks, you can interpret (<.@%&5,5&|) also, didn't you? On the left side we divide every element by 5 (%&5) and round (<. "floor") to the next smallest integer. On the other side we compute the remainder of the division with 5 (| "mod") and append (,) that list to our left result.
   (<.@%&5,5&|) 7 4 10 10 13
1 0 2 2 2 2 4 0 0 3

2. with ((%&2@#,2:)$[) we reshape ($) our list to nx2, n is the length (#) of the list divided by 2 (%&2), (2:) is the constant function, giving back 2
   ((%&2@#,2:)$]) 1 0 2 2 2 2 4 0 0 3
1 0
2 2
2 2
4 0
0 3

3. and transpose (|:) it for our final conversion in pst
   |:((%&2@#,2:)$]) 1 0 2 2 2 2 4 0 0 3
1 2 2 4 0
0 2 2 0 3


dec - decode

Decode is similar to encode.
1. div (<.@%&5) and mod (%&|) our list but merge (,@,.) the result
   NB. append from enc
   (<.@%&5,5&|) 5 12 12 20 3
1 2 2 4 0 0 2 2 0 3
   NB. merge from dec
   (<.@%&5,@,.5&|) 5 12 12 20 3
1 0 2 2 2 2 4 0 0 3

2. and again reshape the result to 2xn with n as half list length
   ((2:,%&2@#)$[) 1 0 2 2 2 2 4 0 0 3
1 0 2 2 2
2 4 0 0 3


pst - result to string

1. we have to rebuild our string, so we take the first row ([/) and multiply with 5 (5&*) and add (+) the result to our second (]/) row, to which we added 66 (66&+)
   NB. our table
   t=:((2:,%&2@#)$[)@(<.@%&5,@,.5&|) 5 12 12 20 3
   t
1 0 2 2 2
2 4 0 0 3
   NB. first row
   [/ t
1 0 2 2 2
   NB. second row
   ]/ t
2 4 0 0 3
   NB. multiply and add twice
   (5&*@[/ + 66&+@]/) t
73 70 76 76 79

2. we have to decrement the values below 75 ('K') (]-<&75)
   (]-<&75)(5&*@[/ + 66&+@]/) t
72 69 76 76 79

3. and lookup our values in the ascii table ({&a.)
   NB. decoding result
   ({&a.) 72 69 76 76 79
HELLO
   NB. encoding result
   ({&a.) 70 78 78 86 68
FNNVD


Now we can compose and use our encode and decode functions:
   encode=:pst@enc@pre
   decode=:pst@dec@pre
   encode 'PROGRAMMINGPRAXISWITHJ'
OMQNHHQWUIGWRFGSKFOMTP
   encode 'PROGRAMMINGPRAXIS'
OMQNHHQWUIGBIMWCS
   decode 'OMQNHHQWUIGWRFGSKFOMTP'
PROGRAMMINGPRAXISWITHK
   decode 'OMQNHHQWUIGBIMWCS'
PROGRAMMINGPRAXIS


Another example

Not enough? I see you are as fascinated as I am. The next example ist from j602/system/main/convert.ijs
av=: 3 : '({&a.)`(a.&i.) @. (2&=@(3!:0)) y'

3 : '... y' defines a verb, imagine it as a function with one argument y. (()`()@.()) is:
m@.n is a verb defined by the gerund m with an agenda specified by n ; that is, the verb represented by the train selected from m by the indices n . If n is boxed, the train is parenthesized accordingly. The case m@.v uses the result of the verb v to perform the selection.

Pure beauty! Here (2&=@(3!:0)) acts as a case or if expression. It returns a value which becomes the index of the left "list of functions" (take it with salt). 3!:0 returns the "type" (more salt!) of a parameter. If it is a character it returns 2, the following comparison (2&=) returns 1 and (a.&i) evaluates to the index of this character in the ascii table. Otherwise we assume it is a number and return the corresponding character.
   (2&=@(3!:0)) 'A'
1
   (2&=@(3!:0)) 97
0
   ({&a.) 99
a
   (a.&i.) 'a'
97
   ({&a.)`(a.&i.) @. (2&=@(3!:0)) 'abc'
97 98 99
   ({&a.)`(a.&i.) @. (2&=@(3!:0)) 97 98 99
abc
Geschrieben von Frank in Informatik Kommentare: (0) Trackbacks: (0)
Tags für diesen Artikel: Bifid, J, cipher
« vorherige Seite   (Seite 1 von 1, insgesamt 1 Einträge)   nächste Seite »

Kategorien

  • XML Geschichte
  • XML Informatik
  • XML Kramkiste
  • XML Netzseite
  • XML Politik


Alle Kategorien
 

Layout by Andreas Viklund | Serendipity template by Carl