Re: 2-D array initialization

2020-08-04 Thread tastyminerals via Digitalmars-d-learn

On Sunday, 2 August 2020 at 19:19:51 UTC, Andy Balba wrote:

On Sunday, 2 August 2020 at 06:37:06 UTC, tastyminerals wrote:

You haven't said anything about efficiency because if you care 
and your arrays are rather big, you better go with 
https://github.com/libmir/mir-algorithm as mentioned above. It 
might be a little finicky at the start but this post: 
https://tastyminerals.github.io/tasty-blog/dlang/2020/03/22/multidimensional_arrays_in_d.html should get you up to speed.



Keep in mind that std.array.staticArray is not efficient for  
large arrays.


If you want to stick to standard D, I would not initialize a 
2D array because it is just cumbersome but rather use a 1D 
array and transform it into 2D view on demand via ".chunks" 
method. Here is an example.


import std.range;
import std.array;

void main() {
int[] arr = 20.iota.array;
auto arr2dView = arr.chunks(5);
}

Should give you

┌  ┐
│ 0  1  2  3  4│
│ 5  6  7  8  9│
│10 11 12 13 14│
│15 16 17 18 19│
└  ┘

whenever you need to access its elements as arr.chunks(5)[1][1 
.. 3] --> [6, 7].


@ tastyminerals  Thanks for your help on this. These comments, 
combined with the others, are making my climb of the D learning 
curve much quicker.


I'm not a gitHub fan, but I like the mir functions; and it 
looks like I have to download mir before using it.
mir has quite a few .d files..Is there a quick way to download 
it ?


mir is a D package (akin to Python pip package). You can easily 
include it into your program by adding at the top of your file 
the following code:


/+ dub.sdl:
name "my_script"
dependency "mir-algorithm" version="~>3.9.12"
+/

And then just run your script with "dub my_script.d", dub will 
fetch the necessary dependencies, compile and run the file. 
However, it will not generate compiled versions of your 
my_script.d for that, you better set a dub project. Here, see to 
do it: 
https://tastyminerals.github.io/tasty-blog/dlang/2020/03/01/how_to_use_external_libraries_in_d_project.html




Re: 2-D array initialization

2020-08-02 Thread jmh530 via Digitalmars-d-learn

On Sunday, 2 August 2020 at 19:19:51 UTC, Andy Balba wrote:



I'm not a gitHub fan, but I like the mir functions; and it 
looks like I have to download mir before using it.
mir has quite a few .d files..Is there a quick way to download 
it ?


dub [1] is now packaged with dmd, which is the easiest way to use 
it, by far.


You can also play around with it at run.dlang.org (though it has 
some limitations).


I encourage you to get familiar with git and github, but if you 
want to avoid downloading files one-by-one from the website, 
there should be a big green button on the front page that says 
"Code". If you click on that, there is button for downloading a 
zip file.



[1] https://dub.pm/getting_started


Re: 2-D array initialization

2020-08-02 Thread Andy Balba via Digitalmars-d-learn

On Sunday, 2 August 2020 at 06:37:06 UTC, tastyminerals wrote:

You haven't said anything about efficiency because if you care 
and your arrays are rather big, you better go with 
https://github.com/libmir/mir-algorithm as mentioned above. It 
might be a little finicky at the start but this post: 
https://tastyminerals.github.io/tasty-blog/dlang/2020/03/22/multidimensional_arrays_in_d.html should get you up to speed.



Keep in mind that std.array.staticArray is not efficient for  
large arrays.


If you want to stick to standard D, I would not initialize a 2D 
array because it is just cumbersome but rather use a 1D array 
and transform it into 2D view on demand via ".chunks" method. 
Here is an example.


import std.range;
import std.array;

void main() {
int[] arr = 20.iota.array;
auto arr2dView = arr.chunks(5);
}

Should give you

┌  ┐
│ 0  1  2  3  4│
│ 5  6  7  8  9│
│10 11 12 13 14│
│15 16 17 18 19│
└  ┘

whenever you need to access its elements as arr.chunks(5)[1][1 
.. 3] --> [6, 7].


@ tastyminerals  Thanks for your help on this. These comments, 
combined with the others, are making my climb of the D learning 
curve much quicker.


I'm not a gitHub fan, but I like the mir functions; and it looks 
like I have to download mir before using it.
mir has quite a few .d files..Is there a quick way to download it 
?


Re: 2-D array initialization

2020-08-02 Thread Ali Çehreli via Digitalmars-d-learn

On 8/1/20 7:00 PM, Andy Balba wrote:

>> >> ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35,
>> 35,35]  ];

> Although not detailed in my original question, in my actual app
> I have array ubyte [1000][3] Big which consists of research data I
> obtained,
>   and from which I want to randomly select 4 observations to construct
> ubyte c[ ][ ].

It depends on how the data is layed out. Your original question makes me 
think the data is "code generated" into a D module and that's where you 
want to initialize that 2D fixed-length (static) array.


So, you simply want to import that module in your analysis program:

import data;

However, I really think the type should be ubyte[3][].

The following option reads the data from a file before analysis. 
Assuming the data is formatted one ubyte on a line:


--- 8< ---
5
5
5
15
15
15
25
25
25
35
35
35
--- 8< ---

then the following program does what you want:

import std.stdio : File, writefln;
import std.algorithm : map;
import std.range : array, chunks;
import std.string : strip;
import std.conv : to;
import std.random : choice;

auto parseData(string fileName) {
  return
File(fileName)   // - Open the file
.byLine  // - Iterate line-by-line as a range
 //   (WARNING: same line buffer is
 //   shared use byLineCopy if
 //   necessary.)
.map!strip   // - Strip the element
.map!(to!ubyte)  // - Convert to ubyte
.chunks(3)   // - Treat 3 consecutive elements as one
 //   unit
.map!(c => c.array)  // - Make an array from each chunk
;

  // NOTE: The returned range object is a chain of
  // operations to apply on fileName. Nothing will be read
  // from the file until the returned range is actually
  // used (i.e. the range is "lazy").
}

void main() {
  auto c = parseData("research_data")  // - The lazy range
   .array; // - As we want to pick
   //   random elements; we
   //   convert the data
   //   range to an
   //   array. This step is
   //   "eager": the entire
   //   file is parsed here.

  // Demonstrate that the type is a 2D array
  static assert (is (typeof(c) == ubyte[][]));

  // The rest is a random choice from that array:
  foreach (_; 0 .. 10) {
auto chosen = c.choice;
writefln!"chosen: %s"(chosen);
  }
}

If the three ubytes should actually be used as parts of a struct like 
Color, here is another approach:


import std.stdio;
import std.algorithm;
import std.range;
import std.string;
import std.conv;
import std.random;

struct Color {
  ubyte r;
  ubyte g;
  ubyte b;
}

// Assumes data is one ubyte per line
auto parseData(string fileName) {
  return
File(fileName)
.byLine
.map!strip
.map!(to!ubyte);
}

auto makeColors(R)(R range) {
  Color[] colors;

  while (!range.empty) {
ubyte pop() {
  auto value = range.front;
  range.popFront();
  return value;
}

auto r = pop();
auto g = pop();
auto b = pop();

colors ~= Color(r, g, b);
  }

  return colors;
}

void main() {
  auto data = parseData("research_data");

  auto c = makeColors(data);
  writefln!"data:\n%(%s\n%)"(c);

  foreach (_; 0 .. 10) {
auto chosen = c.choice;
writefln!"chosen: %s"(chosen);
  }
}

Sorry my liberal use of 'auto', which hides types. You can define 'c' 
with explicit types like Color[], or you can expose a variable's type at 
compile time with pragma(msg):


  pragma(msg, "the type: ", typeof(c));

That prints Color[] for the second program above.

Ali



Re: 2-D array initialization

2020-08-02 Thread tastyminerals via Digitalmars-d-learn

On Sunday, 2 August 2020 at 02:00:46 UTC, Andy Balba wrote:

On Saturday, 1 August 2020 at 22:00:43 UTC, Ali Çehreli wrote:

On 8/1/20 12:57 PM, Andy Balba wrote:

> On Saturday, 1 August 2020 at 00:08:33 UTC, MoonlightSentinel
wrote:
>> On Friday, 31 July 2020 at 23:42:45 UTC, Andy Balba wrote:
>>> How does one initialize c in D ?
>>
>> ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35,
35,35]  ];

> I'm a D newbie. moving over from C/C++, and I'm really
finding it hard
> to adjusting to D syntax, which I find somewhat cryptic
compared to C/C++.

That's surprising to me. I came from C++03 year ago but 
everything in D was much better for me. :)


I wanted to respond to your question yesterday and started 
typing some code but then I decided to ask first: Do you 
really need a static array? Otherwise, the following is a 
quite usable 2D array:


  ubyte[][] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 
35,35]  ];


However, that's quite different from a ubyte[3][4] static 
array because 'c' above can be represented like the following 
graph in memory. (Sorry if this is already known to you.)


c.ptr --> | .ptr | .ptr | .ptr | .ptr |
  |  |  |  |
  .  .  |   --> | 35 | 35 | 35 | 35 |
 etc.   etc. --> | 25 | 25 | 25 | 25 |

In other words, each element is reached through 2 dereferences 
in memory.


On the other hand, a static array consists of nothing but the 
elements in memory. So, a ubyte[3][4] would be the following 
elements in memory:


  | 5 | 5 | ... | 35 | 35 |

One big difference is that static arrays are value types, 
meaning that all elements are copied e.g. as arguments during 
function calls. On the other hand, slices are copied just as 
fat pointers (ptr+length pair), hence have reference semantics.


Here are some ways of initializing a static array. This one is 
the most natural one:


  ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 
35,35]  ];


Yes, that works! :) Why did you need to cast to begin with? 
One reason may be you had a value that could not fit in a 
ubyte so the compiler did not agree. (?)


This one casts a 1D array as the desired type:

  ubyte[3][4] c = *cast(ubyte[3][4]*)(cast(ubyte[])[ 5, 5, 5, 
15, 15, 15, 25, 25, 25, 35, 35, 35 ]).ptr;


The inner cast is required because 5 etc. are ints by-default.

There is std.array.staticArray as well but I haven't used it.

Ali


Although not detailed in my original question, in my actual app
I have array ubyte [1000][3] Big which consists of research 
data I obtained,
 and from which I want to randomly select 4 observations to 
construct

ubyte c[ ][ ].

i.e. construct c= [ Big[r1][3], Big[r2][3], Big[r3][3], 
Big[r4][3] ]

where r1, r2, r3 and r4 are 4 random integers in 0..1001

Being a D newbie, my naive way of doing this was to declare c 
using:
ubyte[3][4] c= [ Big[r1][3], Big[r2][3], Big[r3][3], Big[r4][3] 
]


Obviously, I want to learn how to this the smart D way, but I 
not smart enough at this point.


You haven't said anything about efficiency because if you care 
and your arrays are rather big, you better go with 
https://github.com/libmir/mir-algorithm as mentioned above. It 
might be a little finicky at the start but this post: 
https://tastyminerals.github.io/tasty-blog/dlang/2020/03/22/multidimensional_arrays_in_d.html should get you up to speed.



Keep in mind that std.array.staticArray is not efficient for 
large arrays.


If you want to stick to standard D, I would not initialize a 2D 
array because it is just cumbersome but rather use a 1D array and 
transform it into 2D view on demand via ".chunks" method. Here is 
an example.


import std.range;
import std.array;

void main() {
int[] arr = 20.iota.array;
auto arr2dView = arr.chunks(5);
}

Should give you

┌  ┐
│ 0  1  2  3  4│
│ 5  6  7  8  9│
│10 11 12 13 14│
│15 16 17 18 19│
└  ┘

whenever you need to access its elements as arr.chunks(5)[1][1 .. 
3] --> [6, 7].




Re: 2-D array initialization

2020-08-01 Thread Andy Balba via Digitalmars-d-learn

On Saturday, 1 August 2020 at 22:00:43 UTC, Ali Çehreli wrote:

On 8/1/20 12:57 PM, Andy Balba wrote:

> On Saturday, 1 August 2020 at 00:08:33 UTC, MoonlightSentinel
wrote:
>> On Friday, 31 July 2020 at 23:42:45 UTC, Andy Balba wrote:
>>> How does one initialize c in D ?
>>
>> ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35,
35,35]  ];

> I'm a D newbie. moving over from C/C++, and I'm really
finding it hard
> to adjusting to D syntax, which I find somewhat cryptic
compared to C/C++.

That's surprising to me. I came from C++03 year ago but 
everything in D was much better for me. :)


I wanted to respond to your question yesterday and started 
typing some code but then I decided to ask first: Do you really 
need a static array? Otherwise, the following is a quite usable 
2D array:


  ubyte[][] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 
35,35]  ];


However, that's quite different from a ubyte[3][4] static array 
because 'c' above can be represented like the following graph 
in memory. (Sorry if this is already known to you.)


c.ptr --> | .ptr | .ptr | .ptr | .ptr |
  |  |  |  |
  .  .  |   --> | 35 | 35 | 35 | 35 |
 etc.   etc. --> | 25 | 25 | 25 | 25 |

In other words, each element is reached through 2 dereferences 
in memory.


On the other hand, a static array consists of nothing but the 
elements in memory. So, a ubyte[3][4] would be the following 
elements in memory:


  | 5 | 5 | ... | 35 | 35 |

One big difference is that static arrays are value types, 
meaning that all elements are copied e.g. as arguments during 
function calls. On the other hand, slices are copied just as 
fat pointers (ptr+length pair), hence have reference semantics.


Here are some ways of initializing a static array. This one is 
the most natural one:


  ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 
35,35]  ];


Yes, that works! :) Why did you need to cast to begin with? One 
reason may be you had a value that could not fit in a ubyte so 
the compiler did not agree. (?)


This one casts a 1D array as the desired type:

  ubyte[3][4] c = *cast(ubyte[3][4]*)(cast(ubyte[])[ 5, 5, 5, 
15, 15, 15, 25, 25, 25, 35, 35, 35 ]).ptr;


The inner cast is required because 5 etc. are ints by-default.

There is std.array.staticArray as well but I haven't used it.

Ali


Although not detailed in my original question, in my actual app
I have array ubyte [1000][3] Big which consists of research data 
I obtained,
 and from which I want to randomly select 4 observations to 
construct

ubyte c[ ][ ].

i.e. construct c= [ Big[r1][3], Big[r2][3], Big[r3][3], 
Big[r4][3] ]

where r1, r2, r3 and r4 are 4 random integers in 0..1001

Being a D newbie, my naive way of doing this was to declare c 
using:

ubyte[3][4] c= [ Big[r1][3], Big[r2][3], Big[r3][3], Big[r4][3] ]

Obviously, I want to learn how to this the smart D way, but I not 
smart enough at this point.





Re: 2-D array initialization

2020-08-01 Thread Ali Çehreli via Digitalmars-d-learn

On 8/1/20 12:57 PM, Andy Balba wrote:

> On Saturday, 1 August 2020 at 00:08:33 UTC, MoonlightSentinel wrote:
>> On Friday, 31 July 2020 at 23:42:45 UTC, Andy Balba wrote:
>>> How does one initialize c in D ?
>>
>> ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 35,35]  ];

> I'm a D newbie. moving over from C/C++, and I'm really finding it hard
> to adjusting to D syntax, which I find somewhat cryptic compared to 
C/C++.


That's surprising to me. I came from C++03 year ago but everything in D 
was much better for me. :)


I wanted to respond to your question yesterday and started typing some 
code but then I decided to ask first: Do you really need a static array? 
Otherwise, the following is a quite usable 2D array:


  ubyte[][] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 35,35]  ];

However, that's quite different from a ubyte[3][4] static array because 
'c' above can be represented like the following graph in memory. (Sorry 
if this is already known to you.)


c.ptr --> | .ptr | .ptr | .ptr | .ptr |
  |  |  |  |
  .  .  |   --> | 35 | 35 | 35 | 35 |
 etc.   etc. --> | 25 | 25 | 25 | 25 |

In other words, each element is reached through 2 dereferences in memory.

On the other hand, a static array consists of nothing but the elements 
in memory. So, a ubyte[3][4] would be the following elements in memory:


  | 5 | 5 | ... | 35 | 35 |

One big difference is that static arrays are value types, meaning that 
all elements are copied e.g. as arguments during function calls. On the 
other hand, slices are copied just as fat pointers (ptr+length pair), 
hence have reference semantics.


Here are some ways of initializing a static array. This one is the most 
natural one:


  ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 35,35]  ];

Yes, that works! :) Why did you need to cast to begin with? One reason 
may be you had a value that could not fit in a ubyte so the compiler did 
not agree. (?)


This one casts a 1D array as the desired type:

  ubyte[3][4] c = *cast(ubyte[3][4]*)(cast(ubyte[])[ 5, 5, 5, 15, 15, 
15, 25, 25, 25, 35, 35, 35 ]).ptr;


The inner cast is required because 5 etc. are ints by-default.

There is std.array.staticArray as well but I haven't used it.

Ali



Re: 2-D array initialization

2020-08-01 Thread Andy Balba via Digitalmars-d-learn
On Saturday, 1 August 2020 at 00:08:33 UTC, MoonlightSentinel 
wrote:

On Friday, 31 July 2020 at 23:42:45 UTC, Andy Balba wrote:

How does one initialize c in D ?


ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 
35,35]  ];



none of the statements below works

 c = cast(ubyte) [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 
35,35]  ];


This is an invalid cast because it tries to coerce the entire 
literal into an ubyte. Also  it would be an assignment instead 
of an initialization because this is independent of c's 
declaration.



c[0] = ubyte[3] [5, 5, 5]   ;  c[1] = ubyte[3] [15, 15,15] ;
c[2] = ubyte[3] [25, 25,25] ;  c[3] = ubyte[3] [35, 35,35] ;


A cast is usually specified as `cast(TargetType) value` but not 
necesseray in this example. Use this instead:


c[0] = [5, 5, 5]   ;  c[1] = [15, 15,15] ;
c[2] = [25, 25,25] ;  c[3] = [35, 35,35] ;

for (int i= 0; i<3; i++) for (int j= 0; i<4; j++) c[i][j]= 
cast(ubyte)(10*i +j) ;


The array indices and the inner loop condition are wrong

for (int i= 0; i<3; i++) for (int j= 0; j<4; j++) c[j][i]= 
cast(ubyte)(10*i +j) ;


You could also use foreach-loops, e.g.

foreach (j, ref line; c)
foreach (i, ref cell; line)
cell = cast(ubyte) (10 * i + j);


@ MoonlightSentinel: sorry about the typo in for (int i= 0; i<3; 
i++) for (int j= 0; j<4; j++)


I'm a D newbie. moving over from C/C++, and I'm really finding it 
hard to adjusting to D syntax, which I find somewhat cryptic 
compared to C/C++.
After going thru a D on-line tutorial, I decided D was much 
better than C/C++, so I began by journey into D by converting one 
of my less complicated C++ apps.
I'm surprised at the enormous amount of time this D-conversion 
has taken compared to GO conversion of the very same app. 
Obviously, I need a faster way of climbing the D learning curve, 
so I would appreciate any suggestions.


Re: 2-D array initialization

2020-07-31 Thread MoonlightSentinel via Digitalmars-d-learn

On Friday, 31 July 2020 at 23:42:45 UTC, Andy Balba wrote:

How does one initialize c in D ?


ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 
35,35]  ];



none of the statements below works

 c = cast(ubyte) [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 
35,35]  ];


This is an invalid cast because it tries to coerce the entire 
literal into an ubyte. Also  it would be an assignment instead of 
an initialization because this is independent of c's declaration.



c[0] = ubyte[3] [5, 5, 5]   ;  c[1] = ubyte[3] [15, 15,15] ;
c[2] = ubyte[3] [25, 25,25] ;  c[3] = ubyte[3] [35, 35,35] ;


A cast is usually specified as `cast(TargetType) value` but not 
necesseray in this example. Use this instead:


c[0] = [5, 5, 5]   ;  c[1] = [15, 15,15] ;
c[2] = [25, 25,25] ;  c[3] = [35, 35,35] ;

for (int i= 0; i<3; i++) for (int j= 0; i<4; j++) c[i][j]= 
cast(ubyte)(10*i +j) ;


The array indices and the inner loop condition are wrong

for (int i= 0; i<3; i++) for (int j= 0; j<4; j++) c[j][i]= 
cast(ubyte)(10*i +j) ;


You could also use foreach-loops, e.g.

foreach (j, ref line; c)
foreach (i, ref cell; line)
cell = cast(ubyte) (10 * i + j);



Re: 2-D array initialization

2020-07-31 Thread jmh530 via Digitalmars-d-learn

On Friday, 31 July 2020 at 23:42:45 UTC, Andy Balba wrote:

ubyte[3][4] c ;

How does one initialize c in D ?  none of the statements below 
works


 c = cast(ubyte) [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 
35,35]  ];


c[0] = ubyte[3] [5, 5, 5]   ;  c[1] = ubyte[3] [15, 15,15] ;
c[2] = ubyte[3] [25, 25,25] ;  c[3] = ubyte[3] [35, 35,35] ;

for (int i= 0; i<3; i++) for (int j= 0; i<4; j++) c[i][j]= 
cast(ubyte)(10*i +j) ;


Below is for a dynamic array. You can also try mir 
(https://github.com/libmir/mir-algorithm).


import std.stdio: writeln;

void main()
{
auto c = cast(ubyte[][]) [ [5, 5, 5], [15, 15,15], [25, 
25,25], [35, 35,35]  ];

writeln(c);
}


2-D array initialization

2020-07-31 Thread Andy Balba via Digitalmars-d-learn

ubyte[3][4] c ;

How does one initialize c in D ?  none of the statements below 
works


 c = cast(ubyte) [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 
35,35]  ];


c[0] = ubyte[3] [5, 5, 5]   ;  c[1] = ubyte[3] [15, 15,15] ;
c[2] = ubyte[3] [25, 25,25] ;  c[3] = ubyte[3] [35, 35,35] ;

for (int i= 0; i<3; i++) for (int j= 0; i<4; j++) c[i][j]= 
cast(ubyte)(10*i +j) ;