Ok, so.. thinking this through.
The offsets you are interested in at any dimension are positive
integer multiples }.0 1 _1. (The strangeness with the zero should make
sense in a moment.)
For higher dimension n, you are interested the coordinate offsets you
are interested in are positive integer multiples of }.>,{n#<0 1 _1.
It might be sufficient to simply replace your dirs with this approach?
That said, another way of building the coordinate list would be something like:
draft=:4 :0
coords=. y+"1]0 2|: (1+i.>./x)*/}.>,{(#y)#<0 1 _1
keep=. (*/@:<"1&x * */"1@:>:&0) coords
keep <@#"_1 coords
)
Arguments and use match your ugly:
demo=: draft (#@> # >:@i.@#)@[`(<"1@;@[)`]} [ $ 0:
10 11 demo 5 6
0 8 0 0 0 0 6 0 0 0 0
0 0 8 0 0 0 6 0 0 0 7
0 0 0 8 0 0 6 0 0 7 0
0 0 0 0 8 0 6 0 7 0 0
0 0 0 0 0 8 6 7 0 0 0
2 2 2 2 2 2 0 1 1 1 1
0 0 0 0 0 5 3 4 0 0 0
0 0 0 0 5 0 3 0 4 0 0
0 0 0 5 0 0 3 0 0 4 0
0 0 5 0 0 0 3 0 0 0 4
I am not sure if you consider this an improvement. That said, there's
a certain amount of complexity in the specification so you should not
be too surprised by similar complexity in the code.
Thanks,
--
Raul
On Tue, Aug 15, 2017 at 6:04 PM, Louis de Forcrand <[email protected]> wrote:
> Yes; I began writing the message but had to leave unexpectedly.
> Let me explain what I want for a rank 2 array:
>
> Given the index vector I of an element of the array and its shape, I want
> all the elements in lines which are horizontal, vertical, or diagonal,
> and which pass through I. In addition, elements on either side of
> I must be separated.
>
> I would like the indices of the ones in the right array, but grouped
> (in the </. sense) by their key in the left array (order is not
> important, so long as I can easily identify which diagonal each group
> corresponds to):
>
> (;*) 10 11 demo 5 6
> ┌─────────────────────┬─────────────────────┐
> │0 8 0 0 0 0 6 0 0 0 0│0 1 0 0 0 0 1 0 0 0 0│
> │0 0 8 0 0 0 6 0 0 0 7│0 0 1 0 0 0 1 0 0 0 1│
> │0 0 0 8 0 0 6 0 0 7 0│0 0 0 1 0 0 1 0 0 1 0│
> │0 0 0 0 8 0 6 0 7 0 0│0 0 0 0 1 0 1 0 1 0 0│
> │0 0 0 0 0 8 6 7 0 0 0│0 0 0 0 0 1 1 1 0 0 0│
> │2 2 2 2 2 2 0 1 1 1 1│1 1 1 1 1 1 0 1 1 1 1│
> │0 0 0 0 0 5 3 4 0 0 0│0 0 0 0 0 1 1 1 0 0 0│
> │0 0 0 0 5 0 3 0 4 0 0│0 0 0 0 1 0 1 0 1 0 0│
> │0 0 0 5 0 0 3 0 0 4 0│0 0 0 1 0 0 1 0 0 1 0│
> │0 0 5 0 0 0 3 0 0 0 4│0 0 1 0 0 0 1 0 0 0 1│
> └─────────────────────┴─────────────────────┘
>
> I would like this to be extended to arrays of higher rank as well
> if possible. Do you know of a better (less clunky) way than this:
>
> NB. generate indices by walking in each desired direction from
> NB. the starting point and stopping when we hit the edge of the
> NB. array
> ugly=: 4 : '(}.dirs#x) <@}.@}:@(+^:(] -: x | ])^:a:)"1 y’
>
> NB. all desired line “slopes” in a rank y array
> dirs=: (1|.i:1)&([: ,/ ,"0 1/)&(i.1 0)
>
> NB. for display
> demo=: ugly (#@> # >:@i.@#)@[`(<"1@;@[)`]} [ $ 0:
>
> 10 11 ugly 5 6
> ┌────┬───┬───┬────┬───┬───┬────┬───┐
> │5 7│5 5│6 6│6 7│6 5│4 6│4 7│4 5│
> │5 8│5 4│7 6│7 8│7 4│3 6│3 8│3 4│
> │5 9│5 3│8 6│8 9│8 3│2 6│2 9│2 3│
> │5 10│5 2│9 6│9 10│9 2│1 6│1 10│1 2│
> │ │5 1│ │ │ │0 6│ │0 1│
> │ │5 0│ │ │ │ │ │ │
> └────┴───┴───┴────┴───┴───┴────┴───┘
>
> As you can see, the indices here are grouped in the order
> of the output of dirs.
>
> I hope this is a little more clear; it isn’t
> very easy to explain :-/
>
> Thanks!
> Louis
>
>> On 15 Aug 2017, at 14:43, Raul Miller <[email protected]> wrote:
>>
>> I am having problems understanding what you are asking for.
>>
>> I'll try creating some examples which represent my understanding of
>> what you seem to be asking for, and maybe that can help you tell me
>> where I've gone off track:
>>
>> "Given an array index vector i,"
>>
>> For example:
>> i=: i.4 5
>>
>> "how would you go about finding efficiently all indices (or elements
>> at them) of an array for which the index in each dimension is either
>> the same as that in i"
>>
>> This sounds like all values from i, if I take it literally.
>>
>> but, let's say I want column 2 and row 2
>>
>> ($ 2&e.@#:"1 0 ]) i
>> 0 0 1 0 0
>> 0 0 1 0 0
>> 1 1 1 1 1
>> 0 0 1 0 0
>>
>> The indices would be
>>
>> I.,($ 2&e.@#:"1 0 ]) i
>> 2 7 10 11 12 13 14 17
>>
>> Except we've now got several conflicting uses of the word index: row
>> index, column index, ravel index.
>>
>> "or is offset by +/- n, where n is the same for all dimensions, and
>> keep them grouped by “direction”?"
>>
>> Offset from what? Let's say i represents a 10 by 10 matrix, and that
>> want row or column 6, or an offset of 2 from either of those:
>>
>> ($ +./@((6+_2 0 2)&e.)@#:"1 0 ]) i.10 10
>> 0 0 0 0 1 0 1 0 1 0
>> 0 0 0 0 1 0 1 0 1 0
>> 0 0 0 0 1 0 1 0 1 0
>> 0 0 0 0 1 0 1 0 1 0
>> 1 1 1 1 1 1 1 1 1 1
>> 0 0 0 0 1 0 1 0 1 0
>> 1 1 1 1 1 1 1 1 1 1
>> 0 0 0 0 1 0 1 0 1 0
>> 1 1 1 1 1 1 1 1 1 1
>> 0 0 0 0 1 0 1 0 1 0
>>
>> But I don't know which direction the diagonal elements would belong to.
>>
>> (And then I hit your examples and realize that I have no idea how any
>> of that relates to what I thought you were asking for.)
>>
>> Anyways, maybe try again?
>>
>> Thanks,
>>
>> --
>> Raul
>>
>>
>> On Tue, Aug 15, 2017 at 2:45 PM, Louis de Forcrand <[email protected]> wrote:
>>> Hi,
>>>
>>> Given an array index vector i, how would you go about
>>> finding efficiently all indices (or elements at them) of an
>>> array for which the index in each dimension is either the
>>> same as that in i, or is offset by +/- n, where n is the same
>>> for all dimensions, and keep them grouped by “direction”?
>>>
>>> I have a solution but it isn’t very pretty. I will use it to
>>> illustrate though, as this is kind of hard to explain:
>>>
>>>
>>> ugly=: 4 : '(}.dirs#x) <@}.@}:@(+^:(] -: x | ])^:a:)"1 y'
>>> dirs=: (1|.i:1)&([: ,/ ,"0 1/)&(i.1 0)
>>> demo=: ugly (#@> # >:@i.@#)@[`(<"1@;@[)`]} [ $ 0:
>>>
>>> 6 7 ugly 3 4
>>> ┌───┬───┬───┬───┬───┬───┬───┬───┐
>>> │3 5│3 3│4 4│4 5│4 3│2 4│2 5│2 3│
>>> │3 6│3 2│5 4│5 6│5 2│1 4│1 6│1 2│
>>> │ │3 1│ │ │ │0 4│ │0 1│
>>> │ │3 0│ │ │ │ │ │ │
>>> └───┴───┴───┴───┴───┴───┴───┴───┘
>>> 6 7 demo 3 4
>>> 0 8 0 0 6 0 0
>>> 0 0 8 0 6 0 7
>>> 0 0 0 8 6 7 0
>>> 2 2 2 2 0 1 1
>>> 0 0 0 5 3 4 0
>>> 0 0 5 0 3 0 4
>>>
>>> _13 ]\ 5 5 5 ugly 2 2 2
>>> ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
>>> │2 2 3│2 2 1│2 3 2│2 3 3│2 3 1│2 1 2│2 1 3│2 1 1│3 2 2│3 2 3│3 2 1│3 3 2│3
>>> 3 3│
>>> │2 2 4│2 2 0│2 4 2│2 4 4│2 4 0│2 0 2│2 0 4│2 0 0│4 2 2│4 2 4│4 2 0│4 4 2│4
>>> 4 4│
>>> ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
>>> │3 3 1│3 1 2│3 1 3│3 1 1│1 2 2│1 2 3│1 2 1│1 3 2│1 3 3│1 3 1│1 1 2│1 1 3│1
>>> 1 1│
>>> │4 4 0│4 0 2│4 0 4│4 0 0│0 2 2│0 2 4│0 2 0│0 4 2│0 4 4│0 4 0│0 0 2│0 0 4│0
>>> 0 0│
>>> └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
>>> <"2 ] 5 5 5 demo 2 2 2
>>> ┌────────────┬────────────┬─────────┬────────────┬────────────┐
>>> │26 0 24 0 25│0 0 0 0 0│8 0 6 0 7│0 0 0 0 0│17 0 15 0 16│
>>> │ 0 0 0 0 0│0 26 24 25 0│0 8 6 7 0│0 17 15 16 0│ 0 0 0 0 0│
>>> │20 0 18 0 19│0 20 18 19 0│2 2 0 1 1│0 11 9 10 0│11 0 9 0 10│
>>> │ 0 0 0 0 0│0 23 21 22 0│0 5 3 4 0│0 14 12 13 0│ 0 0 0 0 0│
>>> │23 0 21 0 22│0 0 0 0 0│5 0 3 0 4│0 0 0 0 0│14 0 12 0 13│
>>> └────────────┴────────────┴─────────┴────────────┴────────────┘
>>>
>>>
>>> The different numbers in the arrays represent the different
>>> “directions” I was referring to.
>>>
>>> What I need is not necessarily the indices of these positions;
>>> any way to separate them is good.
>>>
>>> Louis
>>>
>>> ----------------------------------------------------------------------
>>> 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