Thanks for your information about trace. h=:(^ i.@>:)&.> hh=: [: < [: (^ [: i. >:) > h 6 ---------------------------┐ │1 6 36 216 1296 7776 46656│ L--------------------------- hh 6 ---------------------------┐ │1 6 36 216 1296 7776 46656│ L--------------------------- I get a domain error when I try to trace hh even though the function works.
Linda -----Original Message----- From: [email protected] [mailto:[email protected]] On Behalf Of Raul Miller Sent: Sunday, February 17, 2013 8:40 AM To: [email protected] Subject: Re: [Jprogramming] Recursive programming (and scoping therein) Here's how I would approach this task: First, I would think about how the sentence gets parsed. Or, if I was just learning how that works, I could have J guide me: require 'addons/general/misc/trace.ijs' trace '*/&>@{@((^ i.@>:)&.>/)@q:~&__' ... (long output elided) Note that the current version of trace does some surprising things with user defined names, but since this sentence has no user defined names I can ignore that issue. Then, I would build up a sequence of named definitions which correspond to those parsing steps. I would try to give them meaningful names, and I would comment them with the code I was substituting for to keep me from getting too lost. Note also that I could plug my names back into the original for testing purposes. For example, using variations on the sentence (*/&>@{@((^ i.@>:)&.>/)@q:~&__) 720 If I was impatient, I might implement testing as something that happens when my definition script gets loaded. Also, towards the end, I would skip a bunch of steps. I used the idiom F@q:~&__ which is equivalent to __ F@q: ] but keeps the left argument of q: from getting to be too distant from q: itself. Rather than mechanically translate this idiom (a rather length process, which requires I come up with worthwhile names for what I think of as garbage intermediate results), I would just use its replacement. The resulting definitions would look something like this: NB. i.@>: monad oneThroughN=: [: i. 1 + ] NB. ^ i.@>: dyad firstNPowers=: [ ^ oneThroughN NB. (^ i.@>:)&.> dyad powersInBoxes=: ([: < ([: > [) firstNPowers [: > ])"0 NB. (^ i.@>:)&.>/ monad combineUsingPowers=: powersInBoxes/ NB. */ monad multiplyAll=: */ NB. */&> monad multiplyAllFromBox=: ([: multiplyAll [: > ])"0 NB. */&>@{ monad multiplyAllPermutations=: [: multiplyAllFromBox { NB. */&>@{@((^ i.@>:)&.>/) monad multiplyAllPowers=: [: multiplyAllPermutations combineUsingPowers fctrs=: [: multiplyAllPowers __ q: ] And, at this point, you could do sfctrs=: fctrs f. 5!:4 <'sfctrs' But note also that if there were any failures in my translations (for example, maybe I thought I was working with a monad where I was really working with a dyad), I could isolate them. And, in fact, when I am debugging tacit J, I use analogous techniques. If I do not understand what data I am dealing with at a particular point, I replace the code which would run after that point so that I can capture the data. If I am particularly lost, I might substitute a phrase, replacing it with <@,&< in an otherwise working example. This shows me exactly what the values are and also shows me whether the context is a monadic or dyadic context. If I want to see the shapes and do not know the context, I can use ;&$ Once I have sufficiently explored the data to be able to construct my own examples, I can extract the phrase (the one I had just replaced) onto the command line and give it representative arguments. Anyways, I strongly believe that being able to isolate problems is a crucial skill for people working with computers. I hope this helps, -- Raul On Sat, Feb 16, 2013 at 10:13 PM, Linda Alvord <[email protected]> wrote: > I am trying to write factrs in simple J. I hit two snags: > > factrs=: */&>@{@((^ i.@>:)&.>/)@q:~&__ > 5!:6 <'factrs' > ((((((*/)&>)@{)@(((^ (i.@>:))&.>)/))@q:)~)&__ > factrs 500 > 1 5 25 125 > 2 10 50 250 > 4 20 100 500 > > f=:((((((*/)&>)@{)@(((^ (i.@>:))&.>)/))@q:)~)&__ > g=:(((^ (i.@>:))&.>)/) > g > (^ i.@>:)&.>/ > g 500 > 500 > > f=:((((((*/)&>)@{)@g)@q:)~)&__ > h=:(((*/)&>)@{) > h > */&>@{ > h 500 > 500 > > f=:(((h@g)@q:)~)&__ > f > h@g@q:~&__ > > gg=: 13 :'(<( ^ [: i. >:)>)/ y' > hh=: 13 :'*/"1>"0{y' > > ff=:(((hh@g)@q:)~)&__ > ff 500 > 1 5 25 125 > 2 10 50 250 > 4 20 100 500 > > ff=:(((hh@gg)@q:)~)&__ > ff 500 > |length error: gg > | ff 500 > |[-24] c:\users\owner\j701-user\temp\52.ijs > > I can't understand gg well enough to adjust the rank. > > What does &__ mean? > > Linda > > > -----Original Message----- > From: [email protected] > [mailto:[email protected]] On Behalf Of Raul > Miller > Sent: Monday, February 11, 2013 3:28 PM > To: [email protected] > Subject: Re: [Jprogramming] Recursive programming (and scoping > therein) > > After reading this, and finally noticing the comment about remel in > the original post, I am uncomfortable with this treatment of remel. > > A scheme 'alist' is like two J lists, one a list of keys which we > search to get an index into the other. If the types are compatible > (probably valid for integers or boxes), this could be a two > dimensional array where one of the dimensions is 2. > > But the original code is not using an alist, as near as I can tell -- > it's just using a list of divisors. In this context, I think remel > would logically be replaced by dyadic use of J's -. primitive. > Except, this does not work as near as I can tell. I'm not sure if > that's because remel is expected to modify the original alist, or if > that's because remel is really meant to treat the alist as a stack > where it's removing not only the matching element but all previous > elements (which is what the J implementation does). > > But ignoring that, and using the original supplied definition, here's > how I would translate the original code to J: > > allfactors =: af q: > > remel =: [ }.~ [: >: i. > > af=: dyad define > divisors=. y > num=. x > if.0=#divisors do.,num end. > uniquefactors=. ~.divisors > ;num;(num&% af divisors&remel)&.> uniquefactors > ) > > I have not tried to optimize this for efficiency because the recursive > process itself is too inefficient to be worth bothering with. > > For reference, here's one of the implementations from that rosetta > code link I posted earlier: > > factrs=: */&>@{@((^ i.@>:)&.>/)@q:~&__ > factrs 12 > 1 3 > 2 6 > 4 12 > > Obviously you would want to ravel that result before treating it as a list. > > ,@factrs 12 > 1 3 2 6 4 12 > > Anyways, I believe that this approach should be more efficient than > the use of remel (or whatever that should be) in recursion. > > -- > Raul > > On Mon, Feb 11, 2013 at 12:01 PM, Marshall Lochbaum > <[email protected]> > wrote: >> I assume the problems you're having are in getting num and divisors >> to work inside the lambda clause. J can handle this fine--just use >> tacit code rather than an explicit function for the lambda. Here is >> the same code in J. >> >> remel =: ([ }.~ [: >: i.)"_ 0 >> >> allfactors =: af q: >> >> af =: [ , 4 : 0 ^: (*@#@]) >> x (% af&.>(;@:) y <@remel ]) ~.y >> ) >> >> af uses a bit of refactoring to avoid having to write the case where >> y >> (divisors) is empty explicitly. We know we want to tack x (num) to >> the beginning of the list regardless of what happens in the function. >> Once we have made this choice with the [ , at the beginning of af's >> definition, we see that the rest of the function should just return >> an empty list if passed an empty list for y. Therefore we add >> ^:(*@#@]) to af. This means the explicit portion is only executed if >> y has nonzero length. Otherwise it will do nothing, that is, return y >> which is the empty list we want. >> >> The inside of the function is fairly straightforward. We compute the >> nub of y to use as the right argument. Then y <@remel ] gives a boxed >> list of terms (remel divisors x), and % with left argument x and >> right argument ~.y gives the terms (/ num x). We apply af to them >> using af&.> to give a list of boxed results and combine these into a >> single list with ; . >> >> af can also be written in a completely tacit form, although in this >> form we can't easily juggle the three terms num, divisors, and >> (unique divisors). The easiest way out of this is just to compute the >> nub of divisors twice. >> >> af =: [ , ((%~.) $:&.>(;@:) (<@remel ~.)@]) ^: (*@#@]) >> >> This verb uses $: for self-reference, but is largely the same as the >> other form of af. >> >> I realize that methods like these aren't really equivalent to proper >> scoping rules, but I think most of the time they are good enough. >> >> Marshall >> >> On Mon, Feb 11, 2013 at 01:04:31PM +0000, Alex Giannakopoulos wrote: >>> Are there any resources on recursive programming in J? Couldn't >>> find much by searching. >>> I would particularly like to know about scoping, and also so-called >>> free variables. >>> >>> It seems to me that the enforced naming of variables as 'x' and 'y' >>> might cause problems in nested functions, necessitating awkward >>> renaming and copying. >>> >>> I will give a little example here (my apologies to those unfamiliar >>> with >>> Scheme.) >>> I am trying to write a routine that will return ALL the factors of a >>> number, not just the prime ones. >>> I do this by using an auxiliary routine that takes the number to >>> factor and a list of numbers still to combine. >>> >>> ;; function (unique numlist) corresponds to J's ~. >>> ;; function (remel alist elem) corresponds to J's [ }.~ [: >: i. >>> ;; function (primefactors n) corresponds to J's q: >>> >>> (define (allfactors n) (af n (primefators n)) >>> >>> (define (af num divisors) >>> (if (null? divisors) (list num) >>> (let ((uniquefactors (unique divisors))) >>> (flatten >>> (cons num >>> (map (lambda(x) (af (/ num x) (remel divisors x))) >>> uniquefactors)))))) >>> >>> Now I tried to express this in J, but can't even get to first base, >>> because of the scoping problems I mentioned. >>> I realise that recursion is not the primary mode for programming J, >>> and a good solution may instead use something like running totals >>> (\), but for the time being I am stuck. >>> Any suggestions gratefully received. >>> -------------------------------------------------------------------- >>> - >>> - For information about J forums see >>> http://www.jsoftware.com/forums.htm >> --------------------------------------------------------------------- >> - For information about J forums see >> http://www.jsoftware.com/forums.htm > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm > > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
