January 19, 2014
On Sunday, 19 January 2014 at 02:10:01 UTC, CJS wrote:

> That's more concise but I also think it's more confusing. I assume that to!string is doing the exact same thing, but I was hoping for something to do the appropriate implicit conversations. Especially to a range of length 1, though I can understand that kind of auto-magical conversion would be annoying in a number of important instances.

Does not compute. You mean implicit conversion of single character to a range?

> I changed the code to this:
>
> import std.stdio : writeln;
> import std.range : chunks, chain;
> import std.algorithm;
> import std.array;
> import std.conv;
>
> auto cross(R1, R2)(R1 A, R2 B) {
>     return cartesianProduct(A, B).map!(ab => ab[].text).array;
> }
>
>
> void main(){
>     const string letters = "ABCDEFGHI";
>     const string digits = "123456789";
>
>     auto cols = digits;
>     auto rows = letters;
>
>     auto squares = cross(rows, cols);
>     string[][] unitlist;

You may want to use an appender here. It's more efficient than ~= , and lets you transform those foreach loops into one-liners :)

      auto app = appender(&unitlist);

      /+
      foreach(c; cols){
          unitlist ~= cross(rows, to!string(c));
      }
      foreach(r; rows){
          unitlist ~= cross(to!string(r), cols);
      }
      foreach(r; chunks(rows, 3)){
          foreach(c; chunks(cols, 3)){
              unitlist ~= cross(to!string(r),to!string(c));
          }
      }
      +/
      app.put(cols.map!(x => cross(rows, x.text)));
      app.put(rows.map!(x => cross(x.text, cols)));
      app.put(chunks(rows,3).map!(r => chunks(cols,3).map!(c => cross(r.text, c.text))));

>     string[][][string] units;
>     string[][string] peers;
>
>     foreach(s; squares){
>         units[s] = unitlist.filter!(x => any!(y => s==y)); \\line 37
>     }

This one seems like it should be unitlist.filter!(x => x.any!(y => s==y)).array();

>     foreach(s; squares){
>         peers[s] = remove(chain(units[s]), s); \\line 41
>     }

This one I don't understand. chain(units[s]) ? That's the same as units[s]. remove() returns a range, in this case string[][].
January 19, 2014
Thanks!

>
>       auto app = appender(&unitlist);
>

Ah, I'd been wondering if there was something like this. But why does it need unitlist's address? (Assume & has the same meaning as in C and C++.)

>
> This one seems like it should be unitlist.filter!(x => x.any!(y => s==y)).array();
>

Oh. Duh. But what is the .array() at the end doing? Allocating a new array for the results of the filter, since it's basically just a lazily computed range rather than actual storage for the results?

>>    foreach(s; squares){
>>        peers[s] = remove(chain(units[s]), s); \\line 41
>>    }
>
> This one I don't understand. chain(units[s]) ? That's the same as units[s]. remove() returns a range, in this case string[][].

I'm just trying to match what the python code was doing. In that case the line

peers = dict((s, set(sum(units[s],[]))-set([s]))
             for s in squares)

was using sum to concatenate a bunch of lists together and then remove the element. But I miscounted the parentheses and didn't notice the '-' was after the concatenated lists were tured into a set. The following code appears to do what I want, but the string temporary and appender are a bit ugly. Any suggestions on getting rid of them?

   foreach(s; squares){
        string[] tmp;
        auto app2 = appender(&tmp);
        foreach(t; units[s]) {app2.put(t);}
        peers[s] = tmp.sort().uniq().filter!(a => a!=s).array();
    }


January 19, 2014
On Sunday, 19 January 2014 at 06:57:37 UTC, CJS wrote:

> Ah, I'd been wondering if there was something like this. But why does it need unitlist's address? (Assume & has the same meaning as in C and C++.)

Look at the docs for Appender. It can either provide its own storage, or use an existing one. In the latter case you feed it a pointer to your array and it uses that.

>
>>
>> This one seems like it should be unitlist.filter!(x => x.any!(y => s==y)).array();
>>
>
> Oh. Duh. But what is the .array() at the end doing? Allocating a new array for the results of the filter, since it's basically just a lazily computed range rather than actual storage for the results?

Yes. But in this case you'd have to allocate anyways, to fill the units[s] array.

> I'm just trying to match what the python code was doing. In that case the line

Ah, I see.

>
> peers = dict((s, set(sum(units[s],[]))-set([s]))
>              for s in squares)
>
> was using sum to concatenate a bunch of lists together and then remove the element. But I miscounted the parentheses and didn't notice the '-' was after the concatenated lists were tured into a set. The following code appears to do what I want, but the string temporary and appender are a bit ugly. Any suggestions on getting rid of them?
>
	foreach(s; squares){
		peers[s] = units[s].join().sort().uniq().filter!(a => a!=s).array();
	}

That's std.array.join() there. However, I notice that the output (the order of elements) differs from the one on that page you linked earlier.
January 19, 2014
>
> That's std.array.join() there. However, I notice that the output (the order of elements) differs from the one on that page you linked earlier.

The order shouldn't be a problem. Join is a great idea. I'd thought it was only for an array of strings. Thanks for all the help!
1 2
Next ›   Last »