# How to solve withouts classic variables? Classic List Threaded 12 messages Open this post in threaded view
|

## How to solve withouts classic variables?

 Hello, is there a way to solve this problem without classic variables? The setup is (simplified for this example): In a vector I have a number of vectors that define the dimesions of boxes (length, height). The width for all boxes is fixed, and all these boxes should be placed one immedialety after another, however, when the total length exceeds a given maxWidth, the starting x-position should be reset to zero and y should be increased by width. It is a similar problem to e.g. typesetting words aligned to left In a "normal" scripting language I'd do something like `````` width = 10; maxWidth = 50; boxes = [ [10,10], [25,5], [5,15], [20, 5], … ]; // this should produce first "line" from the boxes long 10 + 25 + 5 // and then, the fourth box should "jump" to second line currentX = 0; currentY = 0; for (box = boxes) { if (currentX + box > maxWidth) { currentX = 0; currentY = currentY + width; } translate([currentX, currentY, 0]) cube([box, width, box); currentX = currentX + box; } `````` But because of the weird behaviour of the non-variable variables in OpenSCAD I'm stuck. Any hint for me? Many thanks. Sent from the OpenSCAD mailing list archive at Nabble.com._______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Open this post in threaded view
|

## Re: How to solve withouts classic variables?

 Personally, i’d probably uses a recursive function like this:width = 10;maxWidth = 50;boxes = [ [10,10], [25,5], [5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5]];function justify(width = 0, index = 0, boxesInLine = []) = (index >= len(boxes)) || (width + boxes[index].x > maxWidth) ? [boxesInLine, width] : justify( concat(boxesInLine, index), width + boxes[index].x, index + 1) ; echo(justify());On Jun 23, 2020, at 2:57 PM, janek <[hidden email]> wrote:Hello,is there a way to solve this problem without classic variables?The setup is (simplified for this example): In a vector I have a number of vectors that define the dimesions of boxes (length, height). The width for all boxes is fixed, and all these boxes should be placed one immedialety after another, however, when the total length exceeds a given maxWidth, the starting x-position should be reset to zero and y should be increased by width.It is a similar problem to e.g. typesetting words aligned to leftIn a "normal" scripting language I'd do something like `````` width = 10; maxWidth = 50; boxes = [ [10,10], [25,5], [5,15], [20, 5], … ]; // this should produce first "line" from the boxes long 10 + 25 + 5 // and then, the fourth box should "jump" to second line currentX = 0; currentY = 0; for (box = boxes) { if (currentX + box > maxWidth) { currentX = 0; currentY = currentY + width; } translate([currentX, currentY, 0]) cube([box, width, box); currentX = currentX + box; } ``````But because of the weird behaviour of the non-variable variables in OpenSCAD I'm stuck.Any hint for me? Many thanks. Sent from the OpenSCAD mailing list archive at Nabble.com._______________________________________________OpenSCAD mailing list[hidden email]http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Open this post in threaded view
|

## Re: How to solve withouts classic variables?

 In reply to this post by janek I had a similar issue recently...   What you're trying is to fit a 1 dimensional problem into a 2 dimensional map. The currentX and CurrentY may look like a good idea, but...   You only need ONE of them. CurrentXJust add up the CurrentX, then divide by Maxwidth, an multiply the integer result by the width to et 'CurrentY.The proper CurrentX position is the modulo of CurrentX and Maxwidth.`translate([CurrentX%maxwidth, floor(CurrentX/Maxwidth, 0])`Something like that, at least...   Why do things complicated?;-)TrygveOn 23 June 2020 at 23:57:33 +02:00, janek <[hidden email]> wrote:Hello,is there a way to solve this problem without classic variables?The setup is (simplified for this example): In a vector I have a number of vectors that define the dimesions of boxes (length, height). The width for all boxes is fixed, and all these boxes should be placed one immedialety after another, however, when the total length exceeds a given maxWidth, the starting x-position should be reset to zero and y should be increased by width.It is a similar problem to e.g. typesetting words aligned to leftIn a "normal" scripting language I'd do something like`````` width = 10; maxWidth = 50; boxes = [ [10,10], [25,5], [5,15], [20, 5], … ]; // this should produce first "line" from the boxes long 10 + 25 + 5 // and then, the fourth box should "jump" to second line currentX = 0; currentY = 0; for (box = boxes) { if (currentX + box > maxWidth) { currentX = 0; currentY = currentY + width; } translate([currentX, currentY, 0]) cube([box, width, box); currentX = currentX + box; } ``````But because of the weird behaviour of the non-variable variables in OpenSCAD I'm stuck.Any hint for me? Many thanks.Sent from theOpenSCAD mailing list archive at Nabble.com._______________________________________________OpenSCAD mailing list _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Open this post in threaded view
|

## Re: How to solve withouts classic variables?

 In reply to this post by boxcarmib Thanks, I must confess, I came to a similar solution. However, since my programming experience tells me that recursion is a powerful tool with huge costs (typically memory and performance killer), suffering also from call stack size limitation (even though it is not my case yet, would I be able to process something, that would produce a matrix of ca. 100 x 200 elements using recursion?), I was wondering if there is a better method. Jan Dne 24.06.2020 v 0:22 Hugo Jackson napsal(a): Personally, i’d probably uses a recursive function like this: width = 10; maxWidth = 50; boxes = [ [10,10], [25,5], [5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5]]; function justify(width = 0, index = 0, boxesInLine = []) = (index >= len(boxes)) || (width + boxes[index].x > maxWidth) ? [boxesInLine, width] : justify( concat(boxesInLine, index), width + boxes[index].x, index + 1) ; echo(justify()); On Jun 23, 2020, at 2:57 PM, janek <[hidden email]> wrote: Hello, is there a way to solve this problem without classic variables? The setup is (simplified for this example): In a vector I have a number of vectors that define the dimesions of boxes (length, height). The width for all boxes is fixed, and all these boxes should be placed one immedialety after another, however, when the total length exceeds a given maxWidth, the starting x-position should be reset to zero and y should be increased by width. It is a similar problem to e.g. typesetting words aligned to left In a "normal" scripting language I'd do something like `````` width = 10; maxWidth = 50; boxes = [ [10,10], [25,5], [5,15], [20, 5], … ]; // this should produce first "line" from the boxes long 10 + 25 + 5 // and then, the fourth box should "jump" to second line currentX = 0; currentY = 0; for (box = boxes) { if (currentX + box > maxWidth) { currentX = 0; currentY = currentY + width; } translate([currentX, currentY, 0]) cube([box, width, box); currentX = currentX + box; } `````` But because of the weird behaviour of the non-variable variables in OpenSCAD I'm stuck. Any hint for me? Many thanks. Sent from the OpenSCAD mailing list archive at Nabble.com. _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org ```_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org ``` _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Open this post in threaded view
|

## Re: How to solve withouts classic variables?

 In reply to this post by Gadgetman! Thank you, Dne 24.06.2020 v 0:50 [hidden email] napsal(a): What you're trying is to fit a 1 dimensional problem into a 2 dimensional map.  That's exactly my problem The currentX and CurrentY may look like a good idea, but...   You only need ONE of them.  CurrentX Just add up the CurrentX, then divide by Maxwidth, an multiply the integer result by the width to et 'CurrentY. The proper CurrentX position is the modulo of CurrentX and Maxwidth. ```translate([CurrentX%maxwidth, floor(CurrentX/Maxwidth, 0])``` Something like that, at least...   This is what I do for fixed-size boxes (I started with those). I can simply loop through the vector and calculate current position using method similar to described. However, here, I cannot calculate "statically" currentX and I cannot find the way to repeatedly add to the currentX inside the loop - at least without recursion. Also, using this method, would boxes be aligned properly? If I understand it, then not. It is not given that the sum of lengths on first line would be divisible by MaxWidth and then all further rows would be shifted, wouldn't they? But yes, that could have been solved by temporal calculation of "remaining space" and another addition to currentX - in case I had a method of summing/incrementing a variable inside a loop. Why do things complicated? My words. I love the idea of OpenScad. I bang my forehead to the closest wall almost every time I try to do something in a normal (for a person with some experience with common programming languages), readable or elegant way and call out a loud WHY! :) Jan ;-) Trygve On 23 June 2020 at 23:57:33 +02:00, janek [hidden email] wrote: Hello, is there a way to solve this problem without classic variables? The setup is (simplified for this example): In a vector I have a number of vectors that define the dimesions of boxes (length, height). The width for all boxes is fixed, and all these boxes should be placed one immedialety after another, however, when the total length exceeds a given maxWidth, the starting x-position should be reset to zero and y should be increased by width. It is a similar problem to e.g. typesetting words aligned to left In a "normal" scripting language I'd do something like `````` width = 10; maxWidth = 50; boxes = [ [10,10], [25,5], [5,15], [20, 5], … ]; // this should produce first "line" from the boxes long 10 + 25 + 5 // and then, the fourth box should "jump" to second line currentX = 0; currentY = 0; for (box = boxes) { if (currentX + box > maxWidth) { currentX = 0; currentY = currentY + width; } translate([currentX, currentY, 0]) cube([box, width, box); currentX = currentX + box; } ``` ``` But because of the weird behaviour of the non-variable variables in OpenSCAD I'm stuck. Any hint for me? Many thanks. Sent from theOpenSCAD mailing list archive at Nabble.com. _______________________________________________ OpenSCAD mailing list ```_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org ``` _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Open this post in threaded view
|

## Re: How to solve withouts classic variables?

 Hi!Also, using this method, would boxes be aligned properly? If I understand it, then not. It is not given that the sum of lengths on first line would be divisible by MaxWidth and then all further rows would be shifted, wouldn't they? But yes, that could have been solved by temporal calculation of "remaining space" and another addition to currentX - in case I had a method of summing/incrementing a variable inside a loop.You're right. That was a mistake on my part. I believe it can be solved by adding an IF clause and an addition, but yeah, I'm on vacation right now, it's midday and I haven't even had breakfast yet. My brain probably won't work properly for at least a couple of weeks more....   Trygve, or possibly a multiplication _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Open this post in threaded view
|

## Re: How to solve withouts classic variables?

 This seems to work. Doing the calculation before starting to generate geometry makes it easier to debug and also there's not really a problem regarding the recursion as pretty much any list that's too long at this point will likely be impossible to render later anyway due to number of vertices generated. The commented out generator will make 10001 objects which takes about a second to preview on my notebook. maxWidth = 9; o = [     [3, "gray"],     [1, "lightblue"],     [4, "orange"],     [2, "indigo"],     [2, "violet"],     [3, "yellow"],     [5, "green"] ]; /* maxWidth = 300; r = rands(1, 10, pow(maxWidth / 3, 2) + 3); o = [ for (i = [0 : len(r) - 3]) [ r[i], [ r[i + 1], r[i + 2], r[i + 3] ] / 10] ]; */ function wadd(w, list, idx, cnt = 0) = cnt < 0     ? w     : w + wadd(idx < len(list) ? list[idx] : 0, list, idx + 1, cnt - 1); function map(list, w) = [     for (         idx = 0, w = 0, y = 0;         idx < len(list);         w0 = wadd(w, list, idx),         w1 = wadd(w, list, idx, 1),         w = w1 > maxWidth ? 0 : w0,         y = y + (w1 > maxWidth ? 1 : 0),         idx = idx + 1     )     [each list[idx], w, y] ]; echo(Number_of_objects = len(o)); %linear_extrude(1) offset(delta = 1) square(maxWidth); for (a = map(o)) {     color(a) translate([a, a, 0]) cube([a.x, 1, rands(2,5,1)]); } _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Torsten
Open this post in threaded view
|

## Re: How to solve withouts classic variables?

 In reply to this post by janek I must confess, I came to a similar solution. However, since my programming experience tells me that recursion is a powerful tool with huge costs (typically memory and performance killer), suffering also from call stack size limitation (even though it is not my case yet, would I be able to process something, that would produce a matrix of ca. 100 x 200 elements using recursion?), I was wondering if there is a better method.Recursion is an invaluable resource you should try to master to easily use OpenSCAD . You don't need recursion to sum up a list of numbers or get its accumulated sum but you can't avoid some functions and list comprehension:// total sum of a list of numbers (or of the rows of a matrix)function sum(l) = [for(i=[0:len(l)-1]) (i=len(l)-1  ? breakp  : breakPoints( l=l, wmax  = wmax  ,i=i+1,                 S = S+l[i]> wmax  ? l[i]:S+l[i],                 breakp = concat(breakp,S+l[i]> wmax  ? [i]: [] ) );That is not an easy way for a beginner but it is a tail recursion elimination solution that doesn't overload stacks. Luckly, an equivalent non-recursive solution may be written using C-like for:function breakPoints(l, wmax) =  [for( i=0, break=false, S=l;        i wmax  , S=break? l[i]: S+l[i]      ) if(break) i]; That might be easier to understand by a beginner used to list comprehension and imperative programming.As soon as you have the break points bp of the length list l, the row lengths may be computed by:function row_lengths(l,bp) =  [ sum([for(j=[0:1:bp-1]) l[j] ]),     for(i=[1:len(bp)-1]) sum([for(j=[bp[i-1]:1:bp[i]-1]) l[j] ]),    sum([for(j=[bp[len(bp)-1]:1:len(l)-1]) l[j] ])  ]; A simple final check of everything:maxWidth = 50;boxes = [ [10,10], [5,5], [45,5], [45,15], [45, 5], [10,10], [25,5],           [5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5]];lens = [for(bi=boxes) bi.x];echo(lens=lens);accS = accumSum(lens);echo(accumSum=accS);bp = breakPoints(lens,maxWidth);echo(break_points=bp);echo(row_lengths=row_lengths(lens,bp));/*ECHO: lens = [10, 5, 45, 45, 45, 10, 25, 5, 20, 10, 25, 5, 20]ECHO: accumSum = [10, 15, 60, 105, 150, 160, 185, 190, 210, 220, 245, 250, 270]ECHO: break_points = [2, 3, 4, 5, 8, 10]ECHO: row_lengths = [15, 45, 45, 45, 40, 30, 50] */Using the break points how to find the Y displacement of the rows?( list comprehension => https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/List_Comprehensions ) _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Open this post in threaded view
|

## Re: How to solve withouts classic variables?

 In sum() why do you test for i < len(l) when the loop terminates at len(l) - 1 ? And why would you want a zero in the vector of ones?On Thu, 25 Jun 2020 at 12:45, Ronaldo Persiano <[hidden email]> wrote:I must confess, I came to a similar solution. However, since my programming experience tells me that recursion is a powerful tool with huge costs (typically memory and performance killer), suffering also from call stack size limitation (even though it is not my case yet, would I be able to process something, that would produce a matrix of ca. 100 x 200 elements using recursion?), I was wondering if there is a better method.Recursion is an invaluable resource you should try to master to easily use OpenSCAD . You don't need recursion to sum up a list of numbers or get its accumulated sum but you can't avoid some functions and list comprehension:// total sum of a list of numbers (or of the rows of a matrix)function sum(l) = [for(i=[0:len(l)-1]) (i=len(l)-1  ? breakp  : breakPoints( l=l, wmax  = wmax  ,i=i+1,                 S = S+l[i]> wmax  ? l[i]:S+l[i],                 breakp = concat(breakp,S+l[i]> wmax  ? [i]: [] ) );That is not an easy way for a beginner but it is a tail recursion elimination solution that doesn't overload stacks. Luckly, an equivalent non-recursive solution may be written using C-like for:function breakPoints(l, wmax) =  [for( i=0, break=false, S=l;        i wmax  , S=break? l[i]: S+l[i]      ) if(break) i]; That might be easier to understand by a beginner used to list comprehension and imperative programming.As soon as you have the break points bp of the length list l, the row lengths may be computed by:function row_lengths(l,bp) =  [ sum([for(j=[0:1:bp-1]) l[j] ]),     for(i=[1:len(bp)-1]) sum([for(j=[bp[i-1]:1:bp[i]-1]) l[j] ]),    sum([for(j=[bp[len(bp)-1]:1:len(l)-1]) l[j] ])  ]; A simple final check of everything:maxWidth = 50;boxes = [ [10,10], [5,5], [45,5], [45,15], [45, 5], [10,10], [25,5],           [5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5]];lens = [for(bi=boxes) bi.x];echo(lens=lens);accS = accumSum(lens);echo(accumSum=accS);bp = breakPoints(lens,maxWidth);echo(break_points=bp);echo(row_lengths=row_lengths(lens,bp));/*ECHO: lens = [10, 5, 45, 45, 45, 10, 25, 5, 20, 10, 25, 5, 20]ECHO: accumSum = [10, 15, 60, 105, 150, 160, 185, 190, 210, 220, 245, 250, 270]ECHO: break_points = [2, 3, 4, 5, 8, 10]ECHO: row_lengths = [15, 45, 45, 45, 40, 30, 50] */Using the break points how to find the Y displacement of the rows?( list comprehension => https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/List_Comprehensions ) _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Open this post in threaded view
|

## Re: How to solve withouts classic variables?

 In sum() why do you test for i < len(l) when the loop terminates at len(l) - 1 ? And why would you want a zero in the vector of ones?  You are right, the if is unnecessary. I just have done a lazy change in a more general version of it:// total sum of the first n elements a list of numbers (or of the rows of a matrix)function sum(l,n) = [for(i=[0:len(l)-1]) (i