Small things written in J

Translate, a la Python

In the Python programming language there is a translate() function and an associated method, maketrans(), described here. (Likely, the inspiration for it is tr of Unix.) I've built the same sort of thing in J, both as an explicit script and as a tacit definition drawn from the explicit form. I begin with an example of it in use.

   ('@?!*-',:'aeiou') translate 'th? q-!ck br*wn f*x j-mp?d *v?r th? l@zy d*g'
the quick brown fox jumped over the lazy dog

translate=: dyad define
 FROM=. {.x
 TO  =. {:x
 TEXT=. ,y
 THESE=. FROM i. TEXT
 STET=. THESE = #FROM
 STET {"0 1 TEXT ,.~ THESE { TO, '_'
)

X =: @:[
Y =: @:]
translateT=: (#@{.X = {.X i. ,Y) {"0 1 ,Y ,.~ ({.X i. ,Y) { '_',~ {:X

Binary Search

The following is roughly equivalent to dyadic i.~ . Note also that the code posted here is only viable when x e. y. (That would be a serious flaw for production code, but production code should always use dyadic i.)

bsearch=: 4 : 0 "0 _
    o=. @:
  tilt=. {. o( \: o( [,] ))
  see=. ((<1 1) {] ) {(y"_)
  midel=. >. o -: o(-/)
  nars=. 3 2$ {. , ({:+ 1 0 0 _1+midel) , {:
  narrow=. (] {~ x ( = + 2 * tilt) see)o nars  f.
{. narrow^:_ (<:o# , 0:) y
)

For other implementations of binary search in J, see Rosetta Code.

As for the choice of names, I want to say that 'midel' was derived from 'middle element' (and from sounding like 'middle'.) The 'tilt' is the direction of the discrepancy between the target and the value seen at the current middle element. As for 'nars', this comes from Appalachian caving discussions, where "the nars" are the hazardously narrowed places in a cave system. The results of 'nars' aren't hazardous, nor particularly narrow, but they are the three possible narrowings of the existing range, one of which will be selected in an execution of 'narrow.'

Exclusive-Or Encryption

   ]KeyNoun =. ?. 23 # 2   NB. simple example key
0 1 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0
   useKey =: KeyNoun"_

   encrypt =: (       [: boolToDec  useKey xorCrypt textToBool    ) :. decrypt
   decrypt =: ( a. {~ [: boolToDec  useKey xorCrypt boolToDec^:_1 ) :. encrypt

   xorCrypt =: ] ~: [ $~ #@]
   textToBool =: 3 :' , (8#2) #: , I. a. ="_ _1 y '
   boolToDec =: ( 2 #. (] $~ 8 ([ ,~ #@]%[) ] )) :.  ([: , (8#2) #: ])


   ]Msg=: encrypt 'My secret message.'
40 115 40 185 113 114 230 77 87 8 61 35 35 211 237 198 36 55
   decrypt Msg
My secret message.


   NB. xor encryption is its own inverse:
   ( -: KeyNoun & xorCrypt^:2) textToBool 'hide'
1

Greed

Greed is a game played with dice. For this exercise I worked with the following rules (from Ruby Koans by EdgeCase):

Greed is a dice game where you roll five dice to accumulate points. The following "score" function will be used calculate the score of a single roll of the dice.

Examples:

Here's my solution:

scoregreed =: (triple + singles) @: tallyByFace

tallyByFace =: [: (+/"_) 1 2 3 4 5 6 (="_ 0) ]
singles =: [: +/  100 0 0 0 50 0 *  ] - 3 * 3 <: ]
triple  =: [: +/ 1000 200 300 400 500 600 * 3 <: ]

Rock, Paper, Scissors

Stephen Bailey wrote a blog post about his experience as he begins to learn Erlang. He advises learning a language that is deeply different from what you have already become accustomed to, and suggests functional programming in particular. For initial learning he picked the trivial game Rock, Paper, Scissors; I just had to code something similar in J.

   'rock paper scissors'=:'draw playerX playerY'=:i.3
   reportText=:'Draw.','Win for player X.',:'Win for player Y.'
   result=:(-i.3) |."_1 ]3 3$ draw, playerY, playerX
   vs =: 4 :'reportText{~result{~< x,y'

   rock vs scissors
Win for player X.
   rock vs paper
Win for player Y.
   paper vs paper
Draw.

Later, I decided to write a regression test for those four lines of code. What I came up with runs contrary to my aesthetic sensibilities, but I'm trying to learn about testing by writing more tests. If there is a better way to approach the testing aspect, I'm interested in hearing opinions on the matter.

testRPS=: 3 : 0
txt=.      'Draw.            '
txt=. txt, 'Win for player Y.'
txt=. txt, 'Win for player X.'
txt=. txt, 'Win for player X.'
txt=. txt, 'Draw.            '
txt=. txt, 'Win for player Y.'
txt=. txt, 'Win for player Y.'
txt=. txt, 'Win for player X.'
txt=. txt, 'Draw.            '
(vs"0/~ rock, paper, scissors) -: 3 3 17 $ txt
)

   testRPS''
1


My approach:

kinds=:'PSR'
NB. who wins? "<" means left(x), "^" means up(y)
res=:}. }.;. _2 ] 0 : 0
 PSR
P.^<
S<.^
R^<.
)
numres=:<:'<.^' i. res
vs=:[:{&numres <@,&(kinds&i.)
assert 2 vs/\ succwin=:kinds,{.kinds NB. circular relation(left to right)
assert (-: -@|:) numres NB. x vs y's result is opposite of y vs x's

As I used different approaches in code-under-test and the test, I can cross-check them(you may exchange the two approaches). Textual result funtionality is easy to add. However, I won't unit-test logics with the textual results. --JuneKim

Eight queens solution via 255 sevenths

One solution to the eight queens problem is to use as indexes the first eight digits of a special ratio. (Such indexing is one-based.)

   0j6":((2^8)-1) % (8-1)
36.428571

   ]qn8=:1(<"1(<: 10#.^:_1 <.10e5 * 255%7),.i.8)} 8 8$0
0 0 0 0 0 0 0 1
0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0

   qn8{'.x'
.......x
...x....
x.......
..x.....
.....x..
.x......
......x.
....x...

The orientation chosen here is the structure of the Syntience Inc. logo.

I later posted the following verb to a J forum. It displays n-queen solutions in a manner that suggests a chessboard better than the output seen above. (The not-table that generates checkerboarding was taken from Roger Hui's essay.) Text-based chessboard depiction is pretty unexciting, of course, but what matters is that I keep writing in J.

boards=:' .Q'{~(~:/~8$0 1) >."2 2 (#&0 , 2 , 7&- # 0:)"0 queens 8

A number problem

Thirteen-year old Russell created this for the rest of our family to solve. After solving it mentally I decided to also solve it in J. Here's his problem, followed by my J solver.

a b c d e are all integers between 1 and 5, and they are all different.
We know that

and

We also know that

What numbers correspond to each of the five letters?

all=. (i.!5) A. >:i.5
'a b c d e'=. |: all
fact1=. 5=a+b
fact2=. 2=a-c
fact3=. 5=(2*a)-e
(fact1*.fact2*.fact3) # all

I like the similarity between the normal statement of the problem and the phrasing of the solution.

Initial capitalization

Given text, return that text lower-case except for the upper-case initial letter of each word. (This does not accommodate punctuation, nor does it handle details of titling rules such as not capitalizing embedded words such as 'of'. Also, spacing between words is incidentally made uniform.)

   eachat =: 2 : 'u@:v&.>'
   initial  =: toupper eachat (0&{)
   trail    =: (,&' ')@:tolower eachat }.
   totitle  =:([: ([: }: ;) ([: (initial ,. trail) ;:)) f.

The same code, omitting definition of the temporary verbs (initial, trail):

   totitle  =:([: ([: }: ;) ([: ((toupper eachat (0&{)) ,. ((,&' ')@:tolower eachat }.)) ;:)) f.

   totitle 'GödeL EScHEr bACH'
Gödel Escher Bach

Triangular numbers

Given $n$, return the first $n$ triangular numbers, or the $n$th triangular number.

   +/\>:i. 10
1 3 6 10 15 21 28 36 45 55

   triangularSeries=: +/\@:>:@:i.
   triangularSeries 21
1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 210 231

   triangularNumber=: +/\>:@:i.
   triangularNumber 21
231

Triangular numbers on Wikipedia

Fibonacci sequence

   repeat=: 1 :'u@:]^:['
   fibExtend=: ( , [:+/ _2{.])repeat& 0 1

   fibExtend 9
0 1 1 2 3 5 8 13 21 34 55

TracyHarms/SmallThings (last edited 2011-10-27 18:33:21 by TracyHarms)