www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Replacing nested loops foreach using map/each/etc

reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
Hi,
Is it possible to write such a construction that could push 
immediately to a conditional statement without using nested 
loops? Ie organize search directly in the iterator if provided by 
a map / each / iota and other support functions.
Ie I want to write this code shorter :)

import std.stdio;

void main() {

     const x = 12, y = 65, z = 50, s = 1435;
	
     foreach (i; 0 .. x + 1)
         foreach (j; 0 .. x + 1)
             foreach (k; 0 .. x + 1)
                 if (i * (y + 3 * z) + j * (y + 2 * z) + k * (y + 
z) == s) {
                     writeln(i + j + k);
                     writeln(i * 3 + j * 2 + k);
                     writeln(i * 3 + j * 2 + k);
                     writeln(i, j, k);
                 }
}
-----
http://rextester.com/SJTU87854
May 25 2015
parent reply "Alex Parrill" <initrd.gz gmail.com> writes:
On Monday, 25 May 2015 at 14:25:52 UTC, Dennis Ritchie wrote:
 Hi,
 Is it possible to write such a construction that could push 
 immediately to a conditional statement without using nested 
 loops? Ie organize search directly in the iterator if provided 
 by a map / each / iota and other support functions.
 Ie I want to write this code shorter :)

 import std.stdio;

 void main() {

     const x = 12, y = 65, z = 50, s = 1435;
 	
     foreach (i; 0 .. x + 1)
         foreach (j; 0 .. x + 1)
             foreach (k; 0 .. x + 1)
                 if (i * (y + 3 * z) + j * (y + 2 * z) + k * (y 
 + z) == s) {
                     writeln(i + j + k);
                     writeln(i * 3 + j * 2 + k);
                     writeln(i * 3 + j * 2 + k);
                     writeln(i, j, k);
                 }
 }
 -----
 http://rextester.com/SJTU87854
Hint: Use `cartesianProduct` [1] with three iota ranges to replace the foreachs, and `filter` to replace the if [1]
May 25 2015
parent reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
On Monday, 25 May 2015 at 15:06:45 UTC, Alex Parrill wrote:
 Hint: Use `cartesianProduct` [1] with three iota ranges to 
 replace the foreachs, and `filter` to replace the if

 [1] 

Thank you. Is it possible to replace the loop `foreach` function `each` or `chunkBy` with the auxiliary functions? import std.stdio, std.algorithm, std.range; void main() { const x = 12, y = 65, z = 50, s = 1435; auto a = iota(0, x + 1); foreach (idx; cartesianProduct(a, a, a).filter!(i => i[0] * (y + 3 * z) + i[1] * (y + 2 * z) + i[2] * (y + z) == s)) { writeln(idx[0] + idx[1] + idx[2]); writeln(idx[0] * 3 + idx[1] * 2 + idx[2]); writeln(idx[0] * 3 + idx[1] * 2 + idx[2]); writeln(idx[0], idx[1], idx[2]); } } ----- http://rextester.com/HZP96719
May 25 2015
parent reply "Meta" <jared771 gmail.com> writes:
On Monday, 25 May 2015 at 15:46:54 UTC, Dennis Ritchie wrote:
 On Monday, 25 May 2015 at 15:06:45 UTC, Alex Parrill wrote:
 Hint: Use `cartesianProduct` [1] with three iota ranges to 
 replace the foreachs, and `filter` to replace the if

 [1] 

Thank you. Is it possible to replace the loop `foreach` function `each` or `chunkBy` with the auxiliary functions? import std.stdio, std.algorithm, std.range; void main() { const x = 12, y = 65, z = 50, s = 1435; auto a = iota(0, x + 1); foreach (idx; cartesianProduct(a, a, a).filter!(i => i[0] * (y + 3 * z) + i[1] * (y + 2 * z) + i[2] * (y + z) == s)) { writeln(idx[0] + idx[1] + idx[2]); writeln(idx[0] * 3 + idx[1] * 2 + idx[2]); writeln(idx[0] * 3 + idx[1] * 2 + idx[2]); writeln(idx[0], idx[1], idx[2]); } } ----- http://rextester.com/HZP96719
import std.algorithm; import std.range; import std.stdio; void main() { const x = 12, y = 65, z = 50, s = 1435; auto a = iota(0, x + 1); cartesianProduct(a, a, a) .filter!(i => i[0] * (y + 3 * z) + i[1] * (y + 2 * z) + i[2] * (y + z) == s) .each!((idx) { writeln(idx[0] + idx[1] + idx[2]); writeln(idx[0] * 3 + idx[1] * 2 + idx[2]); writeln(idx[0] * 3 + idx[1] * 2 + idx[2]); writeln(idx[0], idx[1], idx[2]); }); }
May 25 2015
parent reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
On Monday, 25 May 2015 at 16:41:35 UTC, Meta wrote:
 import std.algorithm;
 import std.range;
 import std.stdio;

 void main()
 {
     const x = 12, y = 65, z = 50, s = 1435;
     auto a = iota(0, x + 1);
     cartesianProduct(a, a, a)
       	.filter!(i => i[0] * (y + 3 * z)
             + i[1] * (y + 2 * z)
             + i[2] * (y + z)
             == s)
       	.each!((idx)
               {
                   writeln(idx[0] + idx[1] + idx[2]);
                   writeln(idx[0] * 3 + idx[1] * 2 + idx[2]);
                   writeln(idx[0] * 3 + idx[1] * 2 + idx[2]);
                   writeln(idx[0], idx[1], idx[2]);
               });
 }
Thanks. I do not even know what `each` support braces.
May 25 2015
parent reply "Meta" <jared771 gmail.com> writes:
On Monday, 25 May 2015 at 17:05:35 UTC, Dennis Ritchie wrote:
 On Monday, 25 May 2015 at 16:41:35 UTC, Meta wrote:
 import std.algorithm;
 import std.range;
 import std.stdio;

 void main()
 {
    const x = 12, y = 65, z = 50, s = 1435;
    auto a = iota(0, x + 1);
    cartesianProduct(a, a, a)
      	.filter!(i => i[0] * (y + 3 * z)
            + i[1] * (y + 2 * z)
            + i[2] * (y + z)
            == s)
      	.each!((idx)
              {
                  writeln(idx[0] + idx[1] + idx[2]);
                  writeln(idx[0] * 3 + idx[1] * 2 + idx[2]);
                  writeln(idx[0] * 3 + idx[1] * 2 + idx[2]);
                  writeln(idx[0], idx[1], idx[2]);
              });
 }
Thanks. I do not even know what `each` support braces.
`each` doesn't support braces. There are 4 ways to write a function/delegate literal in D (with a few minor variations): Short form: function(int i) => i; (int i) => i (i) => i i => i Long form: function(int i) { return i; } (int i) { return i; } (i) { return i; } { return 0; } http://dlang.org/expression.html#FunctionLiteral function
May 25 2015
parent reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
On Monday, 25 May 2015 at 17:19:27 UTC, Meta wrote:
 `each` doesn't support braces. There are 4 ways to write a 
 function/delegate literal in D (with a few minor variations):

 Short form:
 function(int i) => i;
 (int i) => i
 (i) => i
 i => i

 Long form:
 function(int i) { return i; }
 (int i) { return i; }
 (i) { return i; }
 { return 0; }

 http://dlang.org/expression.html#FunctionLiteral
 function
Thanks. But why is the solution breaks down when `s = 10000` ? :) import std.stdio, std.algorithm, std.range; int c; const x = 12, y = 65, z = 50, s = 100000; void solve(Range)(Range r) { cartesianProduct(r, r, r).filter!(i => i[0] * (y + 3 * z) + i[1] * (y + 2 * z) + i[2] * (y + z) == s).each!dout; } void main() { auto a = iota(0, x + 1).array; solve(a); writefln(`%s total`, c); } void dout(Tuple)(Tuple idx) { ++c; } ----- http://rextester.com/XGDL26042
May 25 2015
parent reply "anonymous" <anonymous example.com> writes:
On Monday, 25 May 2015 at 17:52:09 UTC, Dennis Ritchie wrote:
 But why is the solution breaks down when `s = 10000` ? :)

 import std.stdio, std.algorithm, std.range;

 int c;
 const x = 12, y = 65, z = 50, s = 100000;
Which is it, now? 4 or 5 zeros?
 void solve(Range)(Range r) {
 	cartesianProduct(r, r, r).filter!(i => i[0] * (y + 3 * z) + 
 i[1] * (y + 2 * z) + i[2] * (y + z) == s).each!dout;
 }

 void main() {

     auto a = iota(0, x + 1).array;

     solve(a);

     writefln(`%s total`, c);
 }

 void dout(Tuple)(Tuple idx) {
     ++c;
 }
 -----
 http://rextester.com/XGDL26042
What do you mean it "breaks down"? Your original code doesn't print anything for s = 10_000 or s = 100_000, either.
May 25 2015
parent "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
On Monday, 25 May 2015 at 19:16:04 UTC, anonymous wrote:
 On Monday, 25 May 2015 at 17:52:09 UTC, Dennis Ritchie wrote:
 But why is the solution breaks down when `s = 10000` ? :)

 import std.stdio, std.algorithm, std.range;

 int c;
 const x = 12, y = 65, z = 50, s = 100000;
Which is it, now? 4 or 5 zeros?
No difference!
 void solve(Range)(Range r) {
 	cartesianProduct(r, r, r).filter!(i => i[0] * (y + 3 * z) + 
 i[1] * (y + 2 * z) + i[2] * (y + z) == s).each!dout;
 }

 void main() {

    auto a = iota(0, x + 1).array;

    solve(a);

    writefln(`%s total`, c);
 }

 void dout(Tuple)(Tuple idx) {
    ++c;
 }
 -----
 http://rextester.com/XGDL26042
What do you mean it "breaks down"? Your original code doesn't print anything for s = 10_000 or s = 100_000, either.
Excuse me, this is my blemish! I forgot that the constant `x` depends on `s`. Everything works correctly: import std.stdio, std.algorithm, std.range; void solve(Range)(Range r) { cartesianProduct(r, r, r).filter!(i => i[0] * (y + 3 * z) + i[1] * (y + 2 * z) + i[2] * (y + z) == s).each!dout; } const y = 65, z = 50, s = 100000; const x = s / (y + z); void main() { auto a = iota(0, x + 1); solve(a); } auto dout(Tuple)(Tuple idx) { writefln(`%s apples`, idx[0] + idx[1] + idx[2]); writefln(`%s gingerbread`, idx[0] * 3 + idx[1] * 2 + idx[2]); writefln(`%s pharynx tea`, idx[0] * 3 + idx[1] * 2 + idx[2]); writefln("Sour: %s; semi-acid: %s; sweet: %s.\n", idx[0], idx[1], idx[2]); } ----- http://rextester.com/MMCI9993
May 25 2015