www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - array of randomly generated names

reply spir <denis.spir gmail.com> writes:
Hello,

A few questions raised by a single func.

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
alias char[] Text ;

Text letters =3D ['a','b','c',...] ;

Text[] nameSet (uint count , uint size) {
	/* set of count random names of size size */
	Text[] names ; names.length =3D count ;
	Text name ; name.length =3D size ;
	for (int i=3D0 ; i<count ; i++) {
		for (int j=3D0 ; j<size ; j++)
		    name[j] =3D letters[uniform(0u,26u)] ;
		names[i].length =3D size ;
		names[i][] =3D name ;
	}
	return names ;
}
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

1. In the  inner loop generating name, I have found neither a way to feed d=
irectly ints into name, nore a way to cast ints to chars using to! (also fo=
und no chr()). So, I had to list letters. But this wouldn't work with a wid=
e range of unicode chars... How to build name directly from random ints?

2. I was surprised to get all names equal... Seems that "names[i] =3D name"=
 actually copies a ref to the name. Is there another way to produce a copy =
than "names[i][] =3D name"?

3. As you see, I individually set the length of each names[i] in the outer =
loop. (This, only to be able to copy, else the compiler complains about une=
quals lengths.) How can I set the length of all elements of names once and =
for all?

4. Is there a kind of map(), or a syntax like list comprehension, to genera=
te array content from a formula? (This would here replace both loops.)

5. Seems there is no auto-conversion between char[] and string. Thus, I use=
 only char[], else I'm constantly blocked with immutability. But for this r=
eason I cannot use nice facilities to construct text expressions, like form=
at(). Also, I need to convert every literal, even chars, when they must go =
into a char[]. Grrr! Even to initialise:
    Text text =3D to!Text("start text") ;
Hints welcome.

Thank you,
Denis
-- -- -- -- -- -- --
vit esse estrany =E2=98=A3

spir.wikidot.com
Oct 15 2010
next sibling parent Jesse Phillips <jessekphillips+D gmail.com> writes:
First listen to Jonathan. Data should be accepted in as strings and returned as
strings (supporting wstring, dstring is fine). Your function should then build
on a local dchar[] and convert it to string when finished. There are some
algorithms that will help with the method you are using. However, if you wish
to generate names you'll likely want to have more than just random letters. The
examples below do not compile on ideone because of a bug in the 2.042 compiler
used. They work with 2.049.

http://ideone.com/7c6cr

import alg = std.algorithm;
import std.stdio;
import std.string;
import std.conv;
import std.random;
 
string makeName(uint wordSize) {
    auto rnd = Random(unpredictableSeed);
    dchar[] newWord = new dchar[wordSize];
 
    alg.fill(newWord[], randomCover(lowercase[], rnd));
 
    return to!string(newWord);
}

void main() {
    writeln(makeName(6));
}

As you can see I did not build you an array of words, but this is just to push
you in the correct direction. The slices of newWord and lowercase (provided by
std.string) are required. And now that you know of a few nice library functions
(std.algorithm.fill) Let us move on to creating a Range of names so you can
make use of this to fill an array of names instead of letters.

http://ideone.com/jtbtn

As it is a larger piece of code I do not wish to duplicate it here. The code is
mostly the same just stored in a struct and the functions: front, empty,
popFront, save. By doing this you can use an assortment of functions found in
std.algorithm[1]. Not all of functions will work with the Range I have created,
as there are many types of ranges[2]: InputRange, OutputRange, ForwardRange,
BidirectionalRange, RandomAccessRange, Infinite (I only covered InputRange,
ForwardRange, Infinite). However that is really just the list of named ranges,
there are even more requirements that may come up.

At last I digress. I hope your interest has been obtained on some of this and
maybe it explains why some things just don't work as you are expecting. Any
questions on a specific item you can start a new thread for.

And comments about the code from other onlookers is also welcome.

1. http://digitalmars.com/d/2.0/phobos/std_algorithm.html
2. http://digitalmars.com/d/2.0/phobos/std_range.html
Oct 15 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
spir <denis.spir gmail.com> wrote:

 ===================
 alias char[] Text ;

 Text letters = ['a','b','c',...] ;

 Text[] nameSet (uint count , uint size) {
 	/* set of count random names of size size */
 	Text[] names ; names.length = count ;
 	Text name ; name.length = size ;
 	for (int i=0 ; i<count ; i++) {
 		for (int j=0 ; j<size ; j++)
 		    name[j] = letters[uniform(0u,26u)] ;
 		names[i].length = size ;
 		names[i][] = name ;
 	}
 	return names ;
 }
 ===================

Here's my version of the same, in highly unidiomatic D: auto nameSet( uint count, uint size ) { auto randomWordsRandomLength = map!"a()"( repeat({ return repeat({ return cast(char)iota(65,91)[ uniform( 0, 26 ) ]; }); }) ); return array( take( map!( ( randomWord ){ return array( take( map!"a()"( randomWord ), size ) ); })( randomWordsRandomLength ), count ) ); } -- Simen
Oct 16 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 15 Oct 2010 15:50:53 -0400, spir <denis.spir gmail.com> wrote:

 Hello,

 A few questions raised by a single func.

 ===================
 alias char[] Text ;

 Text letters = ['a','b','c',...] ;

 Text[] nameSet (uint count , uint size) {
 	/* set of count random names of size size */
 	Text[] names ; names.length = count ;
 	Text name ; name.length = size ;
 	for (int i=0 ; i<count ; i++) {
 		for (int j=0 ; j<size ; j++)
 		    name[j] = letters[uniform(0u,26u)] ;
 		names[i].length = size ;
 		names[i][] = name ;
 	}
 	return names ;
 }
 ===================

 1. In the  inner loop generating name, I have found neither a way to  
 feed directly ints into name, nore a way to cast ints to chars using to!  
 (also found no chr()). So, I had to list letters. But this wouldn't work  
 with a wide range of unicode chars... How to build name directly from  
 random ints?

Can't you just use addition? i.e. i = 0-25 mapped to letters a-z is cast(char)('a' + i) If you are going for unicode, I'd suggest using wchar or dchar (which could be directly cast from integers) to build the string, and then use to!(char[])(widename); Finally, I'd suggest accepting a dchar[] letters as a third optional parameter in case someone wants names in a specific language. -Steve
Oct 16 2010