www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How do you iterate "vertically" over a 2-D array?

reply Chris Katko <ckatko gmail.com> writes:
I have a 2-D array:

int[5][5] data =
	[
		[1, 0, 1, 0, 0],
		[1, 0, 1, 0, 0],
		[1, 0, 1, 1, 1],
		[1, 0, 0, 1, 0],
		[1, 1, 1, 1, 0]
	];


1 - Is there a way to foreach vertically through that? (that is, 
rotated 90 degrees from the usual iteration.)

2 - Is there a way to send that "vertical slice" to a function?

int count_numbers(){/*...*/}

count_numbers(data[0]); //horizontal sum of array[0][0..$-1] 
WORKS.
count_numbers(data[][0]); //vertical sum of array[0..$-1][0] 
HYPOTHETICAL

I'm working on an RLE encoding function and I need both vertical 
and horizontal strips. It just occurred to me that the problem is 
essentially the same, if you can "transpose" the matrix.

Oh geez, did I just realize what I need? some sort of matrix 
transpose function? I found this post;

https://forum.dlang.org/post/na8ikk$2ojo$1 digitalmars.com

The problem is though, even if I use [][], instead of [5][5] (or 
try using his conversion function), I can call transposed... but 
I can't call my function with it!

void run_rle3(int [] a){/*...*/}

	run_rle3(data[0]); //works
	run_rle3(data.transposed[0]); //nope [see error below]
	run_rle3(data[0].transposed); //nope (didn't expect this to)
	run_rle3((data.transposed)[0]); //nope [see error below]

Error: function dmap.run_rle3 (int[] a) is not callable using 
argument types (Transversal!(int[][], cast(TransverseOptions)0))
Oct 09 2018
next sibling parent Chris Katko <ckatko gmail.com> writes:
On Tuesday, 9 October 2018 at 10:52:47 UTC, Chris Katko wrote:
 I have a 2-D array:

 int[5][5] data =
 	[
 		[1, 0, 1, 0, 0],
 		[1, 0, 1, 0, 0],
 		[1, 0, 1, 1, 1],
 		[1, 0, 0, 1, 0],
 		[1, 1, 1, 1, 0]
 	];


 1 - Is there a way to foreach vertically through that? (that 
 is, rotated 90 degrees from the usual iteration.)

 2 - Is there a way to send that "vertical slice" to a function?

 int count_numbers(){/*...*/}

 count_numbers(data[0]); //horizontal sum of array[0][0..$-1] 
 WORKS.
 count_numbers(data[][0]); //vertical sum of array[0..$-1][0] 
 HYPOTHETICAL

 I'm working on an RLE encoding function and I need both 
 vertical and horizontal strips. It just occurred to me that the 
 problem is essentially the same, if you can "transpose" the 
 matrix.

 Oh geez, did I just realize what I need? some sort of matrix 
 transpose function? I found this post;

 https://forum.dlang.org/post/na8ikk$2ojo$1 digitalmars.com

 The problem is though, even if I use [][], instead of [5][5] 
 (or try using his conversion function), I can call 
 transposed... but I can't call my function with it!

 void run_rle3(int [] a){/*...*/}

 	run_rle3(data[0]); //works
 	run_rle3(data.transposed[0]); //nope [see error below]
 	run_rle3(data[0].transposed); //nope (didn't expect this to)
 	run_rle3((data.transposed)[0]); //nope [see error below]

 Error: function dmap.run_rle3 (int[] a) is not callable using 
 argument types (Transversal!(int[][], cast(TransverseOptions)0))
So according to this: https://dlang.org/library/std/range/transposed.html It's trying to take my [0] as an argument for the TransverseOptions variable? But even if I wrap it in parenthesis, it still takes it! (See the last line of code.) auto taco = (data.transposed); run_rle3(taco); //same error, but <-------- HERE?
Oct 09 2018
prev sibling next sibling parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Tuesday, 9 October 2018 at 10:52:47 UTC, Chris Katko wrote:
 I have a 2-D array:

 1 - Is there a way to foreach vertically through that? (that 
 is, rotated 90 degrees from the usual iteration.)

 2 - Is there a way to send that "vertical slice" to a function?
Not built-in in the language, no.
 I'm working on an RLE encoding function and I need both 
 vertical and horizontal strips. It just occurred to me that the 
 problem is essentially the same, if you can "transpose" the 
 matrix.
It may be the same on paper, but not in memory.
 Oh geez, did I just realize what I need? some sort of matrix 
 transpose function? I found this post;

 The problem is though, even if I use [][], instead of [5][5] 
 (or try using his conversion function), I can call 
 transposed... but I can't call my function with it!

 void run_rle3(int [] a){/*...*/}

 	run_rle3(data[0]); //works
 	run_rle3(data.transposed[0]); //nope [see error below]
 	run_rle3(data[0].transposed); //nope (didn't expect this to)
 	run_rle3((data.transposed)[0]); //nope [see error below]

 Error: function dmap.run_rle3 (int[] a) is not callable using 
 argument types (Transversal!(int[][], cast(TransverseOptions)0))
That's because your `run_rle3` function takes an `int[]`, which is a contiguous slice of ints. `transposed` does not return an `int[]`, it returns a lazy range (i.e. a struct with a range interface). Moreover, the range that `transposed` returns isn't even random-access, even though the source may be. If you don't need random access and are just iterating over all elements, you can just change the signature of `run_rle3` to: void run_rle3(R)(auto ref R a) { /* ... */ } However, I'd first think hard about doing this. Iterating "vertically" you essentially skip (N-1) elements on each iteration, elements that would still be pulled into the CPU cache only to be ignored. If you're going to be iterating over every column this way, it may be more efficient to just eagerly transpose the whole array and use it as an array without any extra "transposed" abstractions.
Oct 09 2018
prev sibling parent jmh530 <john.michael.hall gmail.com> writes:
On Tuesday, 9 October 2018 at 10:52:47 UTC, Chris Katko wrote:
 I have a 2-D array:

 int[5][5] data =
 	[
 		[1, 0, 1, 0, 0],
 		[1, 0, 1, 0, 0],
 		[1, 0, 1, 1, 1],
 		[1, 0, 0, 1, 0],
 		[1, 1, 1, 1, 0]
 	];


 1 - Is there a way to foreach vertically through that? (that 
 is, rotated 90 degrees from the usual iteration.)

 2 - Is there a way to send that "vertical slice" to a function?

 [snip]
mir has a lot of functionality that can be helpful here, byDim [1] comes to mind. Of course it also has transposed, but you can combine byDim with count to achieve the same thing as what you're trying.
Oct 09 2018