Thanks, Raul. --Kip Sent from my iPad
On Feb 17, 2013, at 7:39 AM, Raul Miller <[email protected]> wrote: > 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
