Get a list of function results until result > x

Viewed 116

I basically want the same thing as this OP: Is there a J idiom for adding to a list until a certain condition is met? But I cant get the answers to work with OP's function or my own. I will rephrase the question and write about the answers at the bottom.

I am trying to create a function that will return a list of fibonacci numbers less than 2.000.000. (without writing "while" inside the function). Here is what i have tried:

First, i picked a way to culculate fibonacci numbers from this site: https://code.jsoftware.com/wiki/Essays/Fibonacci_Sequence

fib =: (i. +/ .! i.@-)"0
        echo fib i.10
        0 1 1 2 3 5 8 13 21 34

Then I made an arbitrary list I knew was larger than what I needed. :

fiblist =: (fib i.40)       NB. THIS IS A BAD SOLUTION!

Finally, I removed the numbers that were greater than what I needed:

result =: (fiblist < 2e6) # fiblist 
        echo result 
        0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181     6765 10946 17711    28657 46368 75025 121393 196418 317811 514229 832040 1.34627e6

This gets the right result, but is there a way to avoid using some arbitrary number like 40 in "fib i.40" ?

I would like to write a function, such that "func 2e6" returns the list of fibonacci numbers below 2.000.000. (without writing "while" inside the function).

echo func 2e6
    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711    28657 46368 75025 121393 196418 317811 514229 832040 1.34627e6

here are the answers from the other question:

first answer:

 2 *^:(100&>@:])^:_"0 (1 3 5 7 9 11)
    128 192 160 112 144 176

second answer:

+:^:(100&>)^:(<_) ] 3 
3 6 12 24 48 96 192

As I understand it, I just need to replace the functions used in the answers, but i dont see how that can work. For example, if I try:

echo (, [: +/ _2&{.)^:(100&>@:])^:_ i.2

I get an error.

1 Answers

I approached it this way. First I want to have a way of generating the nth Fibonacci number, and I used f0b from your link to the Jsoftware Essays.

   f0b=: (-&2 +&$: -&1) ^: (1&<) M.

Once I had that I just want to put it into a verb that will check to see if the result of f0b is less than a certain amount (I used 1000) and if it was then I incremented the input and went through the process again. This is the ($:@:>:) part. $: is Self-Reference. The right 0 argument is the starting point for generating the sequence.

   ($:@:>: ^: (1000 > f0b)) 0
17

This tells me that the 17th Fibonacci number is the largest one less than my limit. I use that information to generate the Fibonacci numbers by applying f0b to each item in i. ($:@:>: ^: (1000 > f0b)) 0 by using rank 0 (fob"0)

   f0b"0 i. ($:@:>: ^: (1000 > f0b)) 0
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

In your case you wanted the ones under 2000000

   f0b"0 i. ($:@:>: ^: (2000000 > f0b)) 0
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269

... and then I realized that you wanted a verb to be able to answer your original question. I went with dyadic where the left argument is the limit and the right argument generates the sequence. Same idea but I was able to make use of some hooks when I went to the tacit form. (> f0b) checks if the result of f0b is under the limit and ($: >:) increments the right argument while allowing the left argument to remain for $:

   2000000 (($: >:) ^: (> f0b)) 0
32
   fnum=: (($: >:) ^: (> f0b)) 
   2000000 fnum 0
32
   f0b"0 i. 2000000 fnum 0
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269

I have little doubt that others will come up with better solutions, but this is what I cobbled together tonight.

Related