From J Wiki
Jump to: navigation, search

card game simulation, memory-optimization, XML, open-source, data structures, bowling scores, functional programming acceptance, TIOBE index, dynamic languages

Location:: Heartland

Agenda for NYCJUG 20110308

1. Beginner's regatta: Easing the way for beginners: basic readability
standards and a success story - see "Card Game Simulation-Simple

An exercise in J that has generated a lot of feedback:
"Calculating Bowling Scores.pdf" (1st 6 pp).

2. Show-and-tell: Simple Comparison of XML Files-Compendium.pdf

Report on open-source J: see "Source Digest 20110307-v1i7.pdf".

3. Advanced topics: do arrays fit Intel chips better than strucs?  See
"How to Manipulate Data Structure to Optimize Memory Use on 32.pdf".

4. Learning, teaching and promoting J, et al.: see "Why isnt Functional
Programming More Widely Used.pdf", "TIOBE Programming Community Index for
February 201.pdf" (1st 6 pp), "Dynamic Languages Strike Back.pdf" (1st 20 pp),
"Unpopularity of Dynamic Languages.pdf".

Beginner's Regatta

Card Game Simulation – Re-formatted

from Devon McCormick <>
to   Programming forum <>
date Thu, Mar 3, 2011 at 10:45 AM
subject   Re: [Jprogramming] Doing it the J way

As a side note, am I the only one who would find the code easier to read if it had some minimal formatting, as shown below, which includes basic indentation, avoidance of low-information density lines like a bare "do.", and a comment or two? I don't mean to single out Justin for criticism as much of the example code also avoids this basic, helpful formatting.

toRoot=: ([ ,~ { $: ])`(0$0"0)@.(0=[)
poss=: ({:@:](>@:{~ <:&:(#@:>)/)`(>@:{.)@.(1=#)@:(></.]) (-.~i.)~)`(0$0"0)@.(= #)

alg=: 3 : 0
NB.* alg: Create full tree of card deck possibilities to test hi-lo strategy.
fail=. 0$0 [ tree=. stack=. ,: 0 [ vals=. ,: _1

while. 0 < # stack do.
   topStack=. {. stack
   stack=. }. stack
   game=. vals {~ topStack toRoot tree
   p=. y poss game
   numPoss=. # p
   if. numPoss > 0 do.
       vals=. vals , p
       stack=. stack ,~ (# tree) + i. numPoss
       tree=. tree , numPoss $ topStack
       fail=. fail , y - numPoss
   else. fail=. fail , 0 end.

NB.EG (0 0 0 1 2;_1 0 1 1 0) -: alg 2

I also incorporated my own convention of a leading comment with an explanation of what is intended and a trailing comment with an example (showing the expected result, if feasible).

from     Devon McCormick <>
date     Thu, Mar 3, 2011 at 11:01 AM

I should probably also note that I'm critical in part because the code is good in many other respects - variables are localized, names are sufficiently meaningful (except "alg"), and earlier versions were well-commented (arguably, even over-commented but I'm a minimalist at heart).

On Thu, Mar 3, 2011 at 10:53 AM, Justin Paston-Cooper < > wrote:

> Your criticism is valid. I'd been lazy previously because of lack of

> auto-indent. The line with fail =. fail , y - numPoss should be fail

> =. fail , y - numPoss + # game, but I'm not using fail yet.

. ..

from David Ward Lambert <>
date Thu, Mar 3, 2011 at 11:37 AM

In the jgtk edit window find "format" in the "script" window. This will indent your code. I use j mode for emacs which indents my source quite nicely, as do all of the emacs language modes I've used. (Mark the target region and invoke indent-region command.) Start a new line using C-j instead of Enter gives the right indentation. Tab at beginning of line also move point to correct spot.

from Justin Paston-Cooper <>
date Sun, Mar 6, 2011 at 11:42 AM

Thanks to all again for your great advice. On Devon's advice, I made a stochastic version. For the empty game it calculates all relevant outcomes for 800000 random shuffles of 13 cards, in 117 seconds. I then got it working with four simultaneous processes (my processor has four cores), each doing 200000 random shuffles, and the whole thing finishes in 30 seconds. I didn't use any kind of locking or mutex. I made a shared jmf with an array of boxes, one for each process to puts its result in. I then had a main process launch the threads and check every second whether the every box had been filled. I don't know how safe this is, but it seems to work. Two processes never write to the same place in the array at the same time, so I thought it would be okay.

I have a copy of Mathematica 8, which has a package called CUDALink. It allows one to easily run computations on one's NVidia graphics card. It comes with a lot of in-built things like dot products on arrays, folding and mapping with simple arithmetic, etc and it allows one to write C libraries and run them as well. What's more, it comes with some good random number generation facilities to run on the graphics card. It would be nice if J could provide something I can run on my graphics card instead of having to port things to C. I don't know much about this subject or C in general. Has anyone had experience of running J on graphics cards, or making J produce code which I might be able to use for this purpose?

Calculating Bowling Scores

How to Calculate a Bowling Score

By Nellie Day, eHow Contributor

Calculating your bowling score is not difficult.

Calculating your bowling score may seem like a daunting task as your score in bowling is not added like a score in any other sport. Most people do not attempt to calculate their bowling score manually, and will opt to calculate it through electronic means. Despite the complicated appearance of calculating a bowling score, there are only several rules that you must remember in order to master this skill.

Difficulty: Moderately Challenging


1. Notice that your scoring sheet has 10 boxes for each frame of bowling. Additionally, each box will have two smaller boxes in the upper right hand corner. These boxes are there because you get two chances on each frame to knock down all 10 pins.

2. Keep track of how many pins you knock down on your first try on the first frame. If you knock all 10 pins down, you have just scored a strike. If you do not knock down all the pins, you will be afforded another opportunity to knock down the remaining pins. If you do knock down the remaining pins, you have just scored a spare. If you do not knock down the remaining pins, your score will be the amount of pins you have knocked down for that particular frame. Scoring a spare or a strike have different scoring consequences that will be discussed later.

3. Write down the score you received on your first frame of bowling if you did not knock down all the pins. Your score will be the number of pins you knocked down. Remember that you should write down how many pins you knocked down in the two boxes in the upper right hand corner of the frame boxes to keep an accurate score.

4. Do not write your score down if bowl a spare. In the two boxes in the upper right hand corner of the frame box, write down how many pins you knocked down in the first box but write down a "/" in the second box to indicate that you have bowled a spare. The "/" will indicate that you can add an additional 10 points to your next frame of bowling. For example, if you scored a spare on your first frame of bowling and then score seven points on your second frame, you second frame score will actually be 17 points.

5. Do not write down your score if you bowl a strike. Write down a "x" in the last box in the upper right hand corner of the frame box. The "x" indicates that you have just bowled a strike. The strike allows you to add ten additional points to the next two frames of bowling. For example, if you bowl a strike during your first frame of bowling and then score seven points during your second frame and nine points during your third frame, your second and third frame points will be 17 and 19 respectively.

6. Continually add 10 points if you score consecutive spares or strikes in a row. For example, if you score a strike on your first frame and a strike on your second frame, you will already start with 20 points on your third frame from the 10 points that carried over from the first frame and the 10 points from the second frame. Thus, if you score seven points on your third frame after scoring two consecutive strikes, your score for the third frame will be 27 points.

Scoring games of bowling


Ron Jeffries has in several places discussed the calculation of bowling scores as a model programming task. The idea is to receive a list of balls (i.e. tallies of pins knocked down by each) that comprise a complete game of bowling (for one player), and produce the game score as the result.

In addition to my own programs to solve this problem, here I've also collected J solutions to this exercise written by others.

Related web pages: • J-related blog posts by Ron Jeffries • A page on the topic by Jeff Zellner • Early notes and TDD example by Raul Miller

My first bowling scorer

Here is what I wrote the first time I took on this task:

frame =: verb define
 WhereStrikes =. monad :'y #~ 2 ~:/\ 1, 2|y' (10&= # i.@#) y
 BallsAsFramePairs =. WhereStrikes dyad :'y #!._1~ 1j1 x } 1#~#y' y
 monad :'(#~ _1&~:)&.> _2<\ y' BallsAsFramePairs

scoregame =: verb define
 framepins =. [: > {.
 bonus1    =. 10=+/   NB. for strikes and spares
 bonus2    =. 10={.   NB. for strikes
 laterballs=. monad :'2 {. ; }.y'
 bonus     =. laterballs * [:(bonus1, bonus2) framepins
 oneframe  =. [: +/ framepins, bonus
 scoreheadframe=. ([: < ([: > {.), [:oneframe }.) , 2}.]
 +/ >{. scoreheadframe^:10 (a:,frame) y

That program was written without studying any other solutions to the problem. In structuring it, I attempted to make the algorithm apparent strictly through named components rather than commentary. That idea was relatively new to me at the time. Still, I included a couple comments.

My second bowling scorer

Some months later, I wrote a different solution. This one came after I'd studied Henry Rich's solution carefully. I've used indentation to segregate subordinate supportive definitions from the major definitions.

     o =: @:

score_game=: +/ o( select`value } )

value =: trim (0, 2 3 +/\ ])o extend
     extend=: ,& 0 0
     trim  =: #o[  |:o{.  |:o]

select=: trim [:extend [:>o{: [:score_frame^:10 mark ; 0$0:

mark  =: (_9 * 10 =])  *o+/o,:  10 = 2 +/\]

     front=: 1 :' (0;0)&{:: u >o{. '
     back =: 1 :' (0;0)&{:: u >o{: '

score_frame=: (consume }.])front  ;  ( ], pins, omit)back

consume=:   [{ 2 2 1  "_   NB. TwoBalls, TwoBalls, OneBall
pins   =:   [{ 1 2 2  "_   NB. OpenFrame, MarkFrame, MarkFrame
omit   =: [{:: 0;0;0$0:    NB. ExtraBall, ExtraBall, Nothing

The general pattern of this solution is to select pin-totals according to the identification of frames. In keeping with the "breadth-wise" bias of J, all possible pin-totals are calculated. A selection from those is then made to fit the actual pattern of frames in the given game. (Mr. Rich's approach is similar.) I'm happy with the expression of the selection relationship at the highest level, particularly ( selectvalue } ) within score_game and (0, 2 3 +/\ ]) within value. I am less happy about how the details of the selectors (in pins and omit) seem hard to relate to their application, even with the brief comments I included to assist. (These comments are names I decided not to define to cover the special values involved.) In completing this I got helpful advice from Dan Bron on simplifications. For example, he pointed me toward the use of a gerund pair as the argument to Item Amend. I also appreciate J. M. Quintana's technique of using o as an abbreviation for @: . A solution by Henry Rich Henry Rich's solution to this problem has been particularly prominent.

NB. Index of each ball that starts a frame
framex =: 10 {. 0 {~^:a:~  _1 _1  ,~  i.@# >:@:+  10&~:
NB. Score for each ball, assuming that ball starts a frame
scoreifframe =: 3   +^:(9<])`+/@|.\   ,&0
NB. Pick the balls that actually start frames & add em up
gamescore =: [: +/ framex { scoreifframe

A solution by June Kim

Another J solution to this problem was written by June Kim some years back. He posted it with some explanatory comments here. The code portion I reproduce below:

of=: @
sum=: +/
for=: ^:
match=: -:
applied=: &>/
head=: {.
andbonus=: conjunction def '(m+n)&{. ; m&}.'

open=: 2 andbonus 0
spare=: 2 andbonus 1
strike=: 1 andbonus 2

isStr=: 10 match head
isSpr=: 10 match sum of (2&head)

summed=: (sum@[ , ])applied@ (@])
attach=: [,head@]
rest=: }.@]
accumed=: ([`(attach;rest)`) (`:6)
frame=: open`spare@.isSpr`strike@.isStr
doframe=: frame summed accumed applied

limit=: (<&)(@#)
init=: ''&;
score=: >@head
frames=: doframe for (10 limit of score) for (_:`init)
gscore=: sum of score of frames

empty_case=: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
open_case=: 9 0 8 1 7 2 6 3 5 4 4 5 3 6 2 7 8 1 0 9
spare_case=: 9 1 8 2 7 3 6 4 5 5 4 6 3 7 2 8 1 9 8 2 1
strike_case=: 10 10 10 10 10 10 10 10 10 10 10 10
alt_case=: 9 1 10 8 2 10 7 3 10 6 4 10 5 5 10 4 6
none_and_spare_case=: 0 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
strike_none_spare_case=: 10 0 10 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0

assert 0-:gscore empty_case
assert 90-:gscore open_case
assert 145-:gscore spare_case
assert 300-:gscore strike_case
assert 200-:gscore alt_case
assert 30-:gscore none_and_spare_case
assert 34-:gscore strike_none_spare_case

[I particularly like this solution as it defines a domain-specific vocabulary and includes a fairly comprehensive set of test cases.]


Simple Comparison of XML Files

This simple comparison shows differences in tags and their values between two XML files but ignores matching tags that appear in different places in the file. To illustrate what differences it finds, consider the following XML file as our base case.


<?xml version="1.0" encoding="UTF-8"?>

Our first comparison file has all the same data but the tags appear in a different order.


<?xml version="1.0" encoding="UTF-8"?>

Assuming we have installed the comparison tool and are on the command line in the local directory of these two files, we run it by entering something likethis:

simpWOCompareXML.bat samp1.xml samp1b.xml Diff1vs1b.csv

This compares “samp1.xml” to “samp1b.xml” and puts the results into the file “Diff1vs1b.csv”. This output file, when we open in in Excel, looks something like this: height="89",width="439"

The blank lines following the titles indicate there are no data differences between the two files, as we expected.

If we compare our base file “samp1.xml” to the following file, we should find there are differences in some of the numeric values.


<?xml version="1.0" encoding="UTF-8"?>

Running the comparison for these two files:

simpWOCompareXML.bat samp1.xml samp2.xml Diff1vs2.csv

We get the following output in the specified file “Diff1vs2.csv”: height="150",width="719"

From this, we can see that some dates and values differ.

For our last file to compare to “samp1.xml”, we’ll look at the following which, in addition to a differing value for a tag, has an extra tag and is missing a tag. It also has some tags in a different order but this difference is ignored.


<?xml version="1.0" encoding="UTF-8"?>

This comparison gives the following result:


Simple XML File Comparison: XML2FlatTree.ijs

The File:XML2FlatTree.ijs, to be installed in the user’s projects directory, e.g. “”, looks like this.

NB.* XML2FlatTree.ijs: parse XML file -> flat tree list.

require '~addons/xml/sax/sax.ijs'
require 'csv'
saxclass 'saxp'

dropLastPathElm=: ] {.~ '/' i:~ ]

NB. Call-backs for XML parser
startDocument=: 3 : 0
   TREE=: ''
   STK=: ''
   LVL=: 0

startElement=: 4 : 0
   STK=: STK,'/',y
   LVL_1=: <:LVL=: LVL+1

endElement=: 3 : 0
   LVL=: LVL-1
   STK=: dropLastPathElm STK

characters=: 3 : 0
   TREE=: TREE,(LVL~:LVL_1)#<STK,':',y

endDocument=: 3 : 'TREE'

NB. Calling fns
cocurrent 'base'

extrCmdLnVars=: ] #~ ([: +./ '='&e.)&>
nmVal2Cols=: (] }.~&.> '=' = {.&>)"1@:(] split~ '=' i.~ ])
NB. nmVal2Cols=: [: (] }.~&.> '=' = {.&>)"1@:(] ({. ,&< }.)~ '=' i.~ ])&> ] #~ ([: +./ '='&e.)&>
dropKey=: (] }.~ [: >: ':' i:~ ])
extrKey=: ] {.~ ':' i:~ ]

egUse=: 0 : 0
   tr1=. process_saxp_ CRLF-.~fread 'samp1.xml'
   tr2=. process_saxp_ CRLF-.~fread 'samp2.xml'
   tr1=. process_saxp_ xml1
   tr2=. process_saxp_ xml2
   (/:~) &.> (tree1-.tree2);<tree2-.tree1

NB.* getFlnms: get names of files specified, e.g. in command line.
getFlnms=: 3 : 0
   nvpairs=. |:nmVal2Cols &> extrCmdLnVars y
   nvpairs=. (toupper&.>0{nvpairs) 0}nvpairs
   wh=. (0{nvpairs) i. 'FILE1';'FILE2';'OUTFL'
   try. wh{1{nvpairs
   catch. smoutput 'Argument must specify "file1=...", "file2=..." and "outfl=...".'
       smoutput 'Argument is: "',(}:;' ',~&.>":&.>(<^:(L. = 0:))y),'"'
NB.EG 'fl1 fl2'=. getFlnms ARGV_z_

getFlnmsTC0_testCases_=: 3 : 0
   coinsert 'base'
   assert. ('foo';'bar') -: getFlnms 'foobar';'file1=foo';'FILE2=bar'
   assert. ('foo1';'bar1') -: getFlnms 'foo';'bar';'file1=foo1';'FILE2=bar1';'file1=foo2';'FILE2=bar2'
   assert. 0 0 -: $getFlnms 'foo';'bar'

NB.* simpleWithout: simplest case: show lines in each file but not other.
simpleWithout=: 3 : 0
   'fl1 fl2 outfl'=. jpathsep&.>getFlnms y
   tr1=. process_saxp_ CRLF-.~fread fl1
   tr2=. process_saxp_ CRLF-.~fread fl2

   tit=. 'In file1, not file2';'In file2, not file1'
   outfl;~(|:tit,.(tr1-.tr2),:tr2-.tr1) writecsv outfl

NB.* sampleBatFl: example of batch file to invoke this.
sampleBatFl=: 0 : 0
Rem simpWOCompareXML.bat: simply compare 2 XML files to find differing tags.
If %3/==/ goto SHOWHOW
set RUNFL="%USERPROFILE%/j701-user/projects/XML2FlatTree.ijs"
set JEXE="C:/Program Files/J701/bin/jconsole.exe"
%JEXE% %RUNFL% file1=%1 file2=%2 outfl=%3 RUNANDEXIT

Echo Example - to compare XML files and write differences to "xmlDiffs.csv":
Echo %0 fl1.xml fl2.xml xmlDiffs.csv

3 : 0 ''
   if. 'RUNANDEXIT' +./ . E. ;toupper&.>ARGV_z_ do. 13!:0]1
       if. 0<>0{szfl=. simpleWithout ARGV_z_ do.
           smoutput '"',(>1{szfl),'" written.'
           smoutput '"',(>1{szfl),'" NOT written.'

Source Digest, Vol 1, Issue 7

Date:    Mon, Mar 7, 2011 at 10:26 AM
Subject: Source Digest, Vol 1, Issue 7
. Today's Topics:

1. openj (Jack Andrews) 1. Re: openj (bill lam) 1. Re: openj (Jack Andrews) 1. Re: Success! (chris burke) 1. Re: official J Source available (Raul Miller) 1. Re: official J Source available (Jack Andrews) 1. Re: openj (Jeff Zellner) 1. Re: openj (Eric Iverson) 1. my 2 cents (Eric Iverson)

Date: Mon, 7 Mar 2011 17:15:08 +1100
From: Jack Andrews < >
Subject: [Jsource] openj

i've githubbed j701_b_source.tar.gz here:


. let's get stuff done. first task: . - append newlines to files lacking a terminating newline

Date: Mon, 7 Mar 2011 15:10:33 +0800
From: bill lam < >
Subject: Re: [Jsource] openj

Thanks, I found no problem in cloning. Not very efficient but the following can get the job done.

$ git ls-files|xargs
makefile test/g420r2.ijs

where eol.ijs is

 3 : 0''
   for_f. }.ARGV do.
       if. LF~:{:t=. 1!:1 f do.
           stdout LF,>f (t,LF) 1!:2 f

exit 0 ???, 07 ??? 2011, Jack Andrews ?????(?):

. > i've githubbed j701_b_source.tar.gz here: > > > …

On Mon, Mar 7, 2011 at 6:10 PM, bill lam < > wrote: > Thanks, I found no problem in cloning.

> > Not very efficient but the following can get the job done.

> $ git ls-files|xargs ../eol.ijs thanks bill, I just ran it as you said, and pushed the result. I checked the diff, and all looks fine. ta, jack.


Date: Tue, 8 Mar 2011 00:16:04 +1100
From: Jack Andrews < >
Subject: Re: [Jsource] official J Source available

hi raul,

On Mon, Mar 7, 2011 at 11:09 PM, Raul Miller < > wrote:

> On Sun, Mar 6, 2011 at 10:08 PM, bill lam < > wrote:

>> Git should be more complicated and yet it recommend build using its hand

>> crafted makefile instead of ./configure

> > I have not looked at autotools for a while, but it used to be awful. yes, i agree that autotools is a but much. it only takes one (simple) file for CMake to generate - Makefiles - VC++ project files - nmake files - many other build systems' inputs

  • the key here is /single/ maintenance* we don't want to maintain multiple build systems every time a file is added or preprocessor macros change yes, we could write a simple script to generate nmake and Makefile.s, but what about VC++ project/solution files? with a single CMake file, you will instantly get your Makefiles as well as your VC++ projects (and it would be best if we didn't have to write a script to generate VC++ project files) [and VC++ project files are handy] maybe i could show you how CMake works in a small fork at github? will have a look at that soon. oh, and for Windows users, we can automate the install of CMake and supply a .bat file to run CMake on the source. for most linux systems, you can easily get cmake. ta, jack.


My 2 cents: The J community would best be served by building J binaries for new platforms, making sure those binaries work properly (rigorous tests), and encouraging the use of J on these new platforms by making the binaries freely and easily available in nice installer packages. Use the source to take J where it has never gone before. Building alternate versions for systems already well supported by standard Jsoftware installers makes no sense. Avoid fragmenting our small community by making language changes that have not been discussed in great detail in the programming forum and achieved a high degree of consensus. Play by yourself in private by all means, but a cascade of language changes, regardless of whether good or not, is a disservice to our community. The goal is new J users who share a common language, not lots of ports and porters. A great new toy. Play smart.

. End of Source Digest, Vol 1, Issue 7

  • ***********************************


File:Calculating Bowling Scores.pdf

File:Card Game Simulation-Simple re-format.pdf

File:Dynamic Languages Strike Back.pdf

File:How to Manipulate Data Structure to Optimize Memory Use on 32.pdf

File:Simple Comparison of XML Files-Compendium.pdf

File:Source Digest 20110307-v1i7.pdf

File:TIOBE Programming Community Index for February 201.pdf

File:Unpopularity of Dynamic Languages.pdf

File:Why isnt Functional Programming More Widely Used.pdf