March 20, 2014
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
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
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
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
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
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
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
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
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
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)
{
}