3

At the risk of asking a question with an obvious solution: if I have a function in J that takes two arguments and returns two arguments and I want to accumulate the answer's second argument and to use the first argument for the next calculation and to stop once the first argument equals 0, how do I do it without using a loop?

For instance, I have a function that calculates simultaneously the modulo as well as the integer division of a number in J:

f=:([<.@%]),(]|[) 

Following the example in https://en.wikipedia.org/wiki/Factorial_number_system#Definition ;

 f/463 1 463 0 f/463 2 231 1 f/231 3 77 0 f/77 4 19 1 f/19 5 3 4 f/3 6 0 3 
  • How can I accumulate the sequence 3:4:1:0:1:0 without an explicit accumulator

  • How do I keep the first argument from the answer as well as the second from the previous step to calculate the arguments for the next step?

Just to show and make clear what I'm not looking for is a solution like this in Clojure:

(defn ->factorialBase [n] (loop [counter 1 toRet [] num n] (if (zero? num) toRet (recur (inc counter) (conj toRet (mod num counter)) (quot num counter))))) 

I remember reading about something called windowing where you select a portion of an array, use the portion as arguments to your function and move along. Perhaps there is a solution with that?

Thanks in advance

0

1 Answer 1

0

You usually use some variation of power ^: for this. For example with "boxed n" but:

If >n is _ or empty, u is repeatedly executed until the result stops changing. All the results (not including the final repeated one) are collected into an array. Since a: is <0$0, it is used for n in this case

or, similarly, verb-power (do while) ^:v^:_, where v is a test condition verb.

For example, one way to do this is to keep your index in y and create a test for 0=0{y like this:

 g =: 3 :'(>:{:y),~ f/0 2 { y' g 463 0 1 463 0 2 g 463 0 2 231 1 3 g 231 1 3 77 0 4 g 77 0 4 19 1 5 g 19 1 5 3 4 6 g 3 4 6 0 3 7 

So:

 g^:(<7) 463 0 1 463 0 1 463 0 2 231 1 3 77 0 4 19 1 5 3 4 6 0 3 7 1 {"1 g^:(<7) 463 0 1 0 0 1 0 1 4 3 

or

 t =: 3 :'0 < {. y' NB. 0 when first element is 0; 1 otherwise g^:t^:(<_) ] 463 0 1 463 0 1 463 0 2 231 1 3 77 0 4 19 1 5 3 4 6 0 3 7 
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! Though I'd change to g=:3 : '(>:{.y), f/(1 0 { y)' and t=:3 : '0 < 1 { y' moving the counting column to the front and allowing the last column to be read instead of the last one, giving a prettier intermediate result

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.