7
$\begingroup$

Given the list

o = {xmin, xmax, ymin, ymax};

how can I generate the following list?

op = {{{xmin, ymin}, {xmax, ymin}}, {{xmin, ymin}, {xmin, 
    ymax}}, {{xmin, ymax}, {xmax, ymax}}, {{xmax, ymin}, {xmax, 
    ymax}}};

Thank you very much.

(Just for the sake of completeness and since it was asked, I give more details. I just wanted to generate a "Box". This was used to draw the bounding box of a rotated Ellipses, where the xmin, xmax etc are evaluated through the formulas in the article here. The replies were very helpful. I think I can generate now the 3D analog:-)!)

$\endgroup$
  • 1
    $\begingroup$ How do you mean that? $\endgroup$ – Coolwater Apr 27 '15 at 13:42
  • 2
    $\begingroup$ I do not see the pattern. Please describe it further. If there is no pattern, then I suppose typing the list out is the best way to generate it. $\endgroup$ – Michael E2 Apr 27 '15 at 13:49
  • 1
    $\begingroup$ @MichaelE2 I see the pattern. All min and all max are excluded, but otherwise it is a pairing the x's and the y's. $\endgroup$ – rcollyer Apr 27 '15 at 14:09
  • $\begingroup$ I just edited the post where I describe how it appeared the pattern. rcollyer is right. $\endgroup$ – Dimitris Apr 27 '15 at 14:20
2
$\begingroup$

You can get the bounding-box for an n-dimensional box like so:

bounds = {{xmin, xmax}, {ymin, ymax}};
Select[Subsets[Tuples[bounds], {2}], HammingDistance @@ # == 1 &]
(*
  {{{xmin, ymin}, {xmin, ymax}}, {{xmin, ymin}, {xmax, ymin}},
   {{xmin, ymax}, {xmax, ymax}}, {{xmax, ymin}, {xmax, ymax}}}
*)

If you just want to traverse each point, and not necessarily generate every edge, you can order tuples according to Gray code and then partition:

Partition[Tuples[bounds][[{1,2,4,3}]],2,1,1]
(*
  {{{xmin, ymin}, {xmin, ymax}}, {{xmin, ymax}, {xmax, ymax}},
   {{xmax, ymax}, {xmax, ymin}}, {{xmax, ymin}, {xmin, ymin}}}
*)

This can be drawn without lifting a pen, and while it's almost identical in 2D, it will have fewer elements in higher dimensions.

$\endgroup$
8
$\begingroup$

One way:-

o = {xmin, xmax, ymin, ymax};

op = {{{#1, #3}, {#2, #3}}, {{#1, #3}, {#1, #4}},
   {{#1, #4}, {#2, #4}}, {{#2, #3}, {#2, #4}}} & @@ o

{{{xmin, ymin}, {xmax, ymin}}, {{xmin, ymin}, {xmin, ymax}},

{{xmin, ymax}, {xmax, ymax}}, {{xmax, ymin}, {xmax, ymax}}}

Alternatively, (output in a slightly different order).

x = DeleteCases[Tuples[{ymin, ymax}, 2], {ymax, ymin}];

y = Transpose /@ Flatten[Map[Function[z, {z, #} & /@ x],
      DeleteCases[Tuples[{xmin, xmax}, 2], {xmax, xmin}]], 1] /.
   {a_, a_} -> Sequence[];

DeleteCases[y, {{xmin, ymin}, {xmax, ymax}}]

{{{xmin, ymin}, {xmin, ymax}}, {{xmin, ymin}, {xmax, ymin}},

{{xmin, ymax}, {xmax, ymax}}, {{xmax, ymin}, {xmax, ymax}}}

$\endgroup$
  • 1
    $\begingroup$ OK, I'll give it a +1, since it made me laugh. :D $\endgroup$ – Michael E2 Apr 27 '15 at 14:02
  • 2
    $\begingroup$ I'm pretty sure this brute force method requires less time and effort than identifying the pattern. $\endgroup$ – bobthechemist Apr 27 '15 at 14:16
  • $\begingroup$ @MichaelE2 - I added a more thoughtful version :-) $\endgroup$ – Chris Degnen Apr 27 '15 at 16:28
  • $\begingroup$ Actually, now that I can see the pattern, I see that the Slot numbers reflect the pattern rather well. Just couldn't see it before. $\endgroup$ – Michael E2 Apr 28 '15 at 15:15
4
$\begingroup$

Here's a way, but it's in the wrong order:

Thread /@ (Partition[o, 2] /. {{___, #, ___} -> #} & /@ o)
(*
  {{{xmin, ymin}, {xmin, ymax}}, {{xmax, ymin}, {xmax, ymax}},
   {{xmin, ymin}, {xmax, ymin}}, {{xmin, ymax}, {xmax, ymax}}}
*)

If the order matters:

Thread /@ (Partition[o, 2] /. {{___, #, ___} -> #} & /@ 
   o[[{3, 1, 4, 2}]])
(*
  {{{xmin, ymin}, {xmax, ymin}}, {{xmin, ymin}, {xmin, ymax}},
   {{xmin, ymax}, {xmax, ymax}}, {{xmax, ymin}, {xmax, ymax}}}
*)

P.S. A fairly easy way, given the OP has included the explicit output pattern is to use it for a replacement rule:

Replace[o, {xmin_, xmax_, ymin_, ymax_} :>
  {{{xmin, ymin}, {xmax, ymin}}, {{xmin, ymin}, {xmin, ymax}},
   {{xmin, ymax}, {xmax, ymax}}, {{xmax, ymin}, {xmax, ymax}}}]
$\endgroup$
2
$\begingroup$

ox = Partition[o, 2];

p = Table[{ox[[1, i]], ox[[2, j]]}, {i, 1, 2}, {j, 1, 2}]

{{{xmin, ymin}, {xmin, ymax}}, {{xmax, ymin}, {xmax, ymax}}}

Not sure if this is what you want.

(The original post do not have a logic pattern...)

$\endgroup$
2
$\begingroup$

In n-dimensions it can be done this way

dim = 2
o = Flatten[ToExpression[Table["x" <> ToString[i] <> j, {i, dim}, {j, {"min", "max"}}]]]
(*{x1min, x1max, x2min, x2max}*)

Select[Subsets[Tuples[Partition[o, 2]], {2}], Count[#[[1]] - #[[2]], 0] == dim - 1 &]
(*{{{x1min, x2min}, {x1min, x2max}}, {{x1min, x2min}, {x1max, x2min}}, {{x1min, x2max}, {x1max, x2max}}, {{x1max, x2min}, {x1max, x2max}}}*)
$\endgroup$
  • $\begingroup$ Wow! Thanks a lot! $\endgroup$ – Dimitris Apr 27 '15 at 15:02
2
$\begingroup$
parts = Partition[o, 2]

(*
    {{xmin,xmax},{ymin,ymax}}
*)

Thread[{#, parts[[2]]}] & /@ parts[[1]]

(*
    {{{xmin,ymin},{xmin,ymax}},{{xmax,ymin},{xmax,ymax}}}
*)

Thread[{parts[[1]], #}] & /@ parts[[2]]

(*
    {{{xmin,ymin},{xmax,ymin}},{{xmin,ymax},{xmax,ymax}}}
*)

The above result has the Transpose relation, so, combine them

{Transpose[#], #} &@(Thread[{#, parts[[2]]}] & /@ parts[[1]])

(*
    {{{{xmin,ymin},{xmax,ymin}},{{xmin,ymax},{xmax,ymax}}},{{{xmin,ymin},{xmin,ymax}},{{xmax,y
min},{xmax,ymax}}}}
*)

{Transpose[#], #} &@(Through /@ Outer @@ parts)

(*
    {{{xmin[ymin],xmin[ymax]},{xmax[ymin],xmax[ymax]}},{{xmin[ymin],xmax[ymin]},{xmin[ymax],xm
ax[ymax]}}}
*)
$\endgroup$
2
$\begingroup$
With[{aa = Most[Subsets[Flatten[{o[[#]], Drop[o, 2]}], {2}]] & /@ Range@2}, 
{First@# & /@ aa, aa[[1]], Last@# & /@ aa, aa[[2]]}]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.