2 ms·
Other things that are non-self-evident except to people already familiar with APL: * means exponentiation, not multiplication; and "⍟var which is Pi times var"
by gjm11 12y ago
Other things that are non-self-evident except to people already familiar with APL: * means exponentiation, not multiplication; and "⍟var which is Pi times var" is incorrect: it's actually log(var).
I have to confess that I don't find this sort of example very compelling; Box-Muller isn't much more than a one-liner in any language. I mean, here it is in C, not noted for its richly expressive terseness:
double norm(void) {
while (1) {
double u=rand01(), v=rand01();
double s = u*u+v*v;
if (0 < s && s <= 1) return u * sqrt(-2*log(s)/s);
}
}
(I assumed that we already had a rand01() function equivalent to your "u"; I suggest that in any nontrivial program the gain in brevity from the single-character name is outweighed by being unable to call a local variable "u" and, if you have a bunch of these, the cognitive load of remembering what all the single-character names mean.)
I bet the C implementation is distinctly easier to make sense of for most mathematicians and most programmers, and it's not even substantially longer. (APL: 94 non-blank characters. C: 111 non-blank characters. I remark that counting non-blank characters is about as favourable a metric for APL as one can reasonably ask for.) One can code-golf it further: combine the declaration of u,v with that of s (saves 5 non-blank characters --> 106); switch to your "u" instead of my "rand01" and rename u,v to (say) x,y (saves 10 characters --> 96); convert to do/while and use commas instead of {;;;} for body (saves 4 characters -> 92). That looks like this, and I think is still pretty easy to read:
double norm(void) {
double x,y,s;
do x=u(), y=u(), s=x*x+y*y; while (s==0 || s>1);
return x*sqrt(-2*log(s)/s);
}
(Note: character-counting is by hand and it's entirely possible I'm out by a couple of chars either way.)
[EDITED to fix formatting screwage; aargh, I hate HN's treatment of asterisks]
- RBerenguel 12y agoYou are right, π times is the monadic "circle" function... Still trying to learn fluently all operators. And indeed, it's not a specially good example, but I don't have a lot of APL code written (the "nicest" being a Mandelbrot set one-liner), the "longest" being this one and a function to generate histograms, but way harder to read, since it uses quite a few operators: ∇a←n hist x ⍝ Histogram data from x in n buckets s←x[⍋ x] mx←¯1 ↑ s mn←1 ↑ s bk←mn+(⍳n)×(mx-mn)÷n a←+/(~(↑bk)<s) s←((↑bk)<s)/s bk←1↓bk LOOP:→(0=⍴bk)/END a←a,+/(~(↑bk)<s) s←((↑bk)<s)/s bk←1↓bk →LOOP END: ∇ Not brilliant, and even at the time of writing (5 or 6 months ago) I had the feeling it may be possible to write it loopless or close enough. Variables in this one are still "global" since (even if it works) I was still checking it for possible bugs.