Here's my APL solution to the Market Days puzzle:

{del} Z{<-}A DAYSPLUS B;I;M;R;S;Y;#IO

[2] #IO{<-}0

{del}

{del}. CIY{<-}1994 1995

{del}. CID{<-}2 12 31{rho}'WWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDD{+

+}DDDWWHDDDDWWDXXXDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDHWWDDDDDWWDDDDDWWDDDDDWWDDH{+

+}DDWXWDDDDDWWDDDDDWWDDDDDWWDDDDDWWHDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDXDWWHDDDD{+

+}WWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWHDDDDWWDDDDDWWDD{+

+}DDDWWDDDDDXWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDHDWWDDDXD{+

+}DWWDDDDDWWDDDDDWWDDDDDWWHDDDDWWHDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWD{+

+}DDDDWWHDDDDWWDDXXXDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDHWWDDDDDWWDD{+

+}DDDWWXDDDDDWWDDDDDWWDDDDDWWDDDDDWWHDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDXWWDHDD{+

+}DWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWHDDDDWWDDDDDWWD{+

+}DDDDWWDDDDDWXWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDDDWWDDDHDWWDDDD{+

+}XDWWDDDDDWWDDDDDWWDDDDDWWHDDDDWW'

(Note: If you pass this message to DEFINEFNS in the APLASCII v1.3

workspace, it will define both DAYSPLUS and the variables CIY and CID.)

This is essentially the same algorithm as Roger Hui's J solution of

6 Sep 1995, with a slight variation in the origin shifting. I convert

years, months, and days to zero-origin indices by subtracting the scalar

19940101 instead of subtracting 1994 1 1 from each column of the

unpacked date matrix. The dual Roger mentions is on line [8] of this

function: indexing through M is "inverted" by lookup in M. Quite a lot

of duals for such a small function; I count four of them.

The algorithm assumes that CIY contains consecutive years in

ascending order. CIY and CID should be sorted beforehand if this is not

the case.

I saw Roger's solution before I started working on this problem, and

I must admit that figuring out his program was a more interesting puzzle

than developing the APL solution. Maybe I'll find time to write an

explanation of Roger's function, but for now I'd just like to point out

something that made my jaw drop: the phrase "efd^:_1" is used to compute

the inverse of efd, a rather nontrivial user-defined function. Roger

has pointed out that tacit definitions are amenable to formal

manipulation, and this is an impressive example. But I suspect that few

many J users would know that J could invert efd. From my study of the

manual and readme files, I would have expected J to invert {&cenum (part

of efd) by linear approximation, but it seems to know that cenum&i. is a

suitable inverse.

ObTimings:

The execution times below were measured on a 66MHz 486, running Windows

3.1 (for +III and J2). The left argument was 5000{rho}19950906; the

right argument was 5000{rho}{neg}11+{iota}21 (in 1-origin APL; _10+i.21

in 0-origin J).

APL*PLUS/PC v7.1 1.81 secs

APL*PLUS II v5.2 0.177

APL*PLUS III v1.2 0.153

J2 v2.06 0.64

The J2 figure is for Roger's daysplus function, which avoids a bit of

work by precomputing cenum. When I put all of his solution (including

the cenum=.) in an explicit function, the execution time was .66

seconds. I don't know what's slowing up the J program. It isn't the

computation of efd^:_1, which seems to run just as fast as efd itself.

While I prefer the monolithic form of DAYSPLUS, Roger's EFD function

(and its inverse DFE) are handy for defining the other market day

utilities that Roger gave in his posting. Here are APL versions,

expressed using direct definition:

CENUM {<-} +\,CID='D'

CORG {<-} 0 100 100{basevalue}(1{take}CIY),1 1

EFD: CENUM[#IO+0 12 31{basevalue}0 100 100{represent}{omega}-CORG]

DFE: CORG+0 100 100{basevalue}0 12 31{represent}(CENUM{iota}{omega})-#IO

DAYSPLUS and the other utilities are asily expressed in terms of EFD and

DFE:

DAYSPLUS: DFE {omega}+EFD{alpha}

BETWEEN: (EFD{omega})-EFD{alpha}

MARKETDAY: {omega}=DFE EFD{omega}

I wonder if there's a clever algebraic way of expressing EFD and DFE.

Jim