March 20, 2014 Re: Function to print a diamond shape | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 20 March 2014 at 22:46:53 UTC, Ali Çehreli wrote: > On 03/20/2014 03:03 PM, Brad Anderson wrote: > > > I'm not entirely happy with it but: > > I am not happy with my attempt either. :) > > > void main() > > { > > import std.algorithm, std.range, std.stdio, std.conv; > > > > enum length = 5; > > auto rng = > > chain(iota(length), iota(length, -1, -1)) > > Ooh. I like that. That would have never occurred to me. :) It felt kind of clumsy when I ended up with it. I don't think it shows my intent very well (repeat the range in reverse). I wish Phobos had something like a mirror() range (i.e. chain(rng, rng.retro())). > > > .map!((a => " ".repeat(length-a)), > > (a => "#".repeat(a*2+1))) > > .map!(a => chain(a[0].joiner, a[1].joiner, "\n")) > > .joiner; > > > > writeln(rng); > > } > > Does that compile for you? Failed for me with v2.066-devel-d0f461a: > [snip] > A regression? > I did it on dpaste which is using 2.065 so I suspect regression. http://dpaste.dzfl.pl/71c331960cb0 > > Had some trouble with the result coming out as integers > instead of > > something string-like. > > I had the same problem at one point. I will try to understand when that happens. > > Ali I was getting the integers when I was using character literals with repeat() rather than string literals. |
March 21, 2014 Re: Function to print a diamond shape | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | Ali Çehreli: > This is a somewhat common little exercise: Write a function that takes the size of a diamond and produces a diamond of that size. > > When printed, here is the output for size 11: > > * > *** > ***** > ******* > ********* > *********** > ********* > ******* > ***** > *** > * Some of my solutions (using each() in the last two is easy): import std.stdio, std.array, std.string, std.range, std.algorithm, std.math; void printDiamond1(in uint n) { immutable k = (n % 2 == 1) ? 1 : 2; for (int i = k; i <= n; i += 2) writeln("*".replicate(i).center(n)); for (int i = n - 2; i >= k; i -= 2) writeln("*".replicate(i).center(n)); } void printDiamond2(in int n) { iota(!(n % 2), n) .map!(i => "*" .replicate((n % 2) + ((n / 2) - abs(i - (n / 2))) * 2) .center(n)) .join("\n") .writeln; } void printDiamond3(in int n) { writefln("%-(%s\n%)", iota(!(n % 2), n) .map!(i => "*" .replicate((n % 2) + ((n / 2) - abs(i - (n / 2))) * 2) .center(n))); } void main() { foreach (immutable i; 0 .. 15) { printDiamond3(i); writeln; } } Output: * ** * *** * ** **** ** * *** ***** *** * ** **** ****** **** ** * *** ***** ******* ***** *** * ** **** ****** ******** ****** **** ** * *** ***** ******* ********* ******* ***** *** * ** **** ****** ******** ********** ******** ****** **** ** * *** ***** ******* ********* *********** ********* ******* ***** *** * ** **** ****** ******** ********** ************ ********** ******** ****** **** ** * *** ***** ******* ********* *********** ************* *********** ********* ******* ***** *** * ** **** ****** ******** ********** ************ ************** ************ ********** ******** ****** **** ** Bye, bearophile |
March 21, 2014 Re: Function to print a diamond shape | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 03/20/2014 02:25 PM, Ali Çehreli wrote:
> Write a function that takes
> the size of a diamond and produces a diamond of that size.
I have learned a lot, especially the following two:
1) chain'ing iotas is an effective way of producing non-monotonic number intervals (and more).
2) There is std.string.center. :)
Also considering readability, here is my favorite so far:
auto diamondShape(size_t N, dchar fillChar = '*')
{
import std.range : chain, iota, repeat;
import std.algorithm : map;
import std.conv : text;
import std.string : center, format;
import std.exception : enforce;
enforce(N % 2, format("Size must be an odd number. (%s)", N));
return
chain(iota(1, N, 2),
iota(N, 0, -2))
.map!(i => fillChar.repeat(i))
.map!(s => s.text)
.map!(s => s.center(N));
}
unittest
{
import std.exception : assertThrown;
import std.algorithm : equal;
assertThrown(diamondShape(4));
assert(diamondShape(3, 'o').equal([ " o ", "ooo", " o " ]));
}
void main()
{
import std.stdio : writefln;
writefln("%-(%s\n%)", diamondShape(11));
}
Ali
|
March 21, 2014 Re: Function to print a diamond shape | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Friday, 21 March 2014 at 00:31:58 UTC, bearophile wrote: >> This is a somewhat common little exercise: Write a function > > Bye, > bearophile I like that replicate but easier for me to keep track of the counts if I work from the center. int blanks[]; blanks.length = n; int stars[]; stars.length = n; int c = n/2; // center of diamond int cp1 = c+1; blanks[c]=0; stars[c]=n; // calculate stars and blanks in each row for(int i=1; i<cp1; i++){ blanks[c-i] = blanks[c+i] = i; stars[c-i] = stars[c+i] = n - (i*2); } for (int i=0; i<n; i++){ write(" ".replicate(blanks[i])); writeln("*".replicate(stars[i])); } |
March 21, 2014 Re: Function to print a diamond shape | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 20 March 2014 at 21:25:03 UTC, Ali Çehreli wrote:
> This is a somewhat common little exercise: Write a function that takes the size of a diamond and produces a diamond of that size.
>
> When printed, here is the output for size 11:
>
> *
> ***
> *****
> *******
> *********
> ***********
> *********
> *******
> *****
> ***
> *
>
> What interesting, boring, efficient, slow, etc. ways are there?
>
> Ali
Probably, the most boring way is
foreach(i; 0..N)
{
foreach(j; 0..N)
write(" *"[i + j >= N/2 && i + j < 3*N/2 && i - j <= N/2 && j - i <= N/2]);
writeln;
}
|
March 21, 2014 Re: Function to print a diamond shape | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jay Norwood | This one calculates, then outputs subranges of the ba and sa char arrays. int n = 11; int blanks[]; blanks.length = n; int stars[]; stars.length = n; char ba[]; ba.length = n; ba[] = ' '; // fill full ba array char sa[]; sa.length = n; sa[] = '*'; // fill full sa array int c = n/2; // center of diamond int cp1 = c+1; blanks[c]=0; stars[c]=n; // calculate stars and blanks in each row for(int i=1; i<cp1; i++){ blanks[c-i] = blanks[c+i] = i; stars[c-i] = stars[c+i] = n - (i*2); } // output subranges of the ba and sa char arrays for (int i=0; i<n; i++){ write(ba[$-blanks[i]..$]); writeln(sa[$-stars[i]..$]); } |
March 21, 2014 Re: Function to print a diamond shape | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sergei Nosov | On Friday, 21 March 2014 at 12:32:58 UTC, Sergei Nosov wrote:
> Probably, the most boring way is
>
> foreach(i; 0..N)
> {
> foreach(j; 0..N)
> write(" *"[i + j >= N/2 && i + j < 3*N/2 && i - j <= N/2 && j - i <= N/2]);
> writeln;
> }
A single foreach(i; 0..N*N) is more boring!
|
March 21, 2014 Re: Function to print a diamond shape | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sergei Nosov | On Friday, 21 March 2014 at 12:32:58 UTC, Sergei Nosov wrote: > On Thursday, 20 March 2014 at 21:25:03 UTC, Ali Çehreli wrote: >> This is a somewhat common little exercise: Write a function that takes the size of a diamond and produces a diamond of that size. >> >> When printed, here is the output for size 11: >> >> * >> *** >> ***** >> ******* >> ********* >> *********** >> ********* >> ******* >> ***** >> *** >> * >> >> What interesting, boring, efficient, slow, etc. ways are there? >> >> Ali > > Probably, the most boring way is > > foreach(i; 0..N) > { > foreach(j; 0..N) > write(" *"[i + j >= N/2 && i + j < 3*N/2 && i - j <= N/2 && j - i <= N/2]); write(" *"[abs(i-N/2) + abs(j-N/2) <= N/2]); > writeln; > } |
March 21, 2014 Re: Function to print a diamond shape | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vladimir Panteleev | On Friday, 21 March 2014 at 13:59:27 UTC, Vladimir Panteleev wrote:
> On Friday, 21 March 2014 at 12:32:58 UTC, Sergei Nosov wrote:
>> On Thursday, 20 March 2014 at 21:25:03 UTC, Ali Çehreli wrote:
>>> This is a somewhat common little exercise: Write a function that takes the size of a diamond and produces a diamond of that size.
>>>
>>> When printed, here is the output for size 11:
>>>
>>> *
>>> ***
>>> *****
>>> *******
>>> *********
>>> ***********
>>> *********
>>> *******
>>> *****
>>> ***
>>> *
>>>
>>> What interesting, boring, efficient, slow, etc. ways are there?
>>>
>>> Ali
>>
>> Probably, the most boring way is
>>
>> foreach(i; 0..N)
>> {
>> foreach(j; 0..N)
>> write(" *"[i + j >= N/2 && i + j < 3*N/2 && i - j <= N/2 && j - i <= N/2]);
>
> write(" *"[abs(i-N/2) + abs(j-N/2) <= N/2]);
>
>> writeln;
>> }
Beat me. Yours is even more boring. =)
|
March 22, 2014 Re: Function to print a diamond shape | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sergei Nosov | The computation times of different methods can differ a lot. How do you suggest to measure this effectively without the overhead of the write and writeln output? Would a count of 100001 and stubs like below be reasonable, or would there be something else that would prevent the optimizer from getting too aggressive? void writelnx(T...)(T args) { } void writex(T...)(T args) { } |
Copyright © 1999-2021 by the D Language Foundation