Reporter block gets exponentially slower as the list gets bigger

Hi, this issue baffles and annoys me quite a bit. The issue is with the block on the right. Here's what its meant to do:
The sprite creates as many clones as inputed through "alonzo count". The clones are then randomly spread along y=-160. The reporter block on the left creates a list of the distances between the clones. All the functions up until now happen instantly, no lags at all. However, the reporter block on the right gives me headaches. It's function is to find the smallest non-zero number in the generated list. The list has positive and negative values, the first item in the list is zero, and there are a few other zeros in the list. The block then reports the position of the smallest number on the list.

As the number of clones increases, the list generated by the first block increases by (nubmer of clones)^2. Each increase in number of clones makes the second block exponentially slower. The warp block doesn't seem to help with this.

I've simplified the block as much as I can and tried moving and adding warp blocks around different segments of the code but nothing seems to work.

I'd really appreciate any suggestions to improve it.

Thanks a lot

In the second block Clone with smallest distance, make another script variable (Assume you will call it data) and set that to the 1st reporter block you mentioned distance between each clone and replace all duplicated instances of distance between each clone block with the script variable you declared the distance between each clone (Data script variable in this solution). Hope this helps! If this does not speed up the clone with smaller distance block, then I can't find another one.

@hm100 is right about the main problem, namely calling DISTANCE BETWEEN EACH BLOCK six times for every item of the list that the first call returns. That's where the exponential growth in time comes from.

I'd like to add a couple of stylistic points. First, instead of computing √̅x̅²̅ to get the absolute value, there's an ABS option in the pulldown menu of the SQRT block.

More importantly, the most Snap!ish way to do this computation, probably also the fastest, is to use higher order functions and hyperblocks:


≠ and MIN are hidden primitives; to find them, grab an = and a MOD block, respectively, right-click it, and choose RELABEL from the menu. (Or just write them in Snap! yourself.)

The report block you suggest works fantastically. Is there a way to find the item number instead of/as well as the item value?

Yes, but it's slightly ugly; you append the item number to each item, which hairs up the comparisons, and then extract it from the result:


To get that "input names" thing, click the right arrow of the gray ring in MAP twice.

If you want only the index, just take ITEM 2 OF the result.

Which list is used on the item block?
(when it says "item(1) of []"

I tried creating a variable and set the value of the list to that variable. I think it made it a bit faster, but its still painfully slow.

Don't put a list in the item block. It's supposed to be empty there.

I implemented that but it shows error. Here is a link to the project:

https://snap.berkeley.edu/project?user=sajjad_sharif&project=alonzo%20clustering

I implemented the suggestions on the operators reporter block named "clone with smallest distance 2".

All the commands work with "clone with smallest distance" but the block is slow. The block "distance between each clone" generates the list used by these blocks.

Ideally, I need a block that gives the exact output as "clone with smallest distance" as the whole project is reliant on that block. But I need it to be fast.

Thank you very much everyone for trying to help.

No, you're supposed to leave these empty:
Screenshot 2021-04-18 164346

Expanding on @helicoptur's answer:

Higher order functions (map, keep, find first, combine) work by filling empty slots in the expression inside the gray ring, repeatedly, once for each item of the input list. So


is equivalent to

But COMBINE is a little different from the others, because it requires a two-input function;


is equivalent to
untitled script pic
In this case two different values go into the two empty input slots of each × block.

COMBINE USING MIN would find the smallest value in a list of numbers. But in your problem you have a list of index-value pairs, so the combining function is a little more complicated.

But on top of that, as I'm writing this I see that the function should be


not ITEM 2 OF, because it's the value you want to minimize, not the index.

The block either gives me an error, or just outputs 0.

It didn't work, I've submitted my project now.

What do you mean?

It was due 8 hours ago and I could fix the issue

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.