How to avoid “if statement” in Mathematica?












1














I have a list of 100 vectors 2D (x,y) defined by RandomReal[1.0, {100, 2}] and a given forward vector such as {1, 1}. My ultimate objective is to find the vector on the most right hand side of the forward vector. If there is non such a vector, then pick up the first vector on the left of the forward vector.



I can do this by firstly classifying the initial list of vectors into 2 lists: 1 list contains all vectors on the right hand side of the forward vector. The second contains all vectors on its left hand side. The criterion to define whether a vector on the right hand side of the forward vector is that its cross product between the considered vector with the forward vector is positive. Negative result would mean it is on the left of the forward vector.



The next step would be to check if the list of the vectors on the right hand side of the forward vector is empty. If not, check the relative position of the first 2 vectors in that list, only keep the vector on the right hand side, and then check the relative position between the kept vector and the third vector in the list and continue to do so until the end of the list.



If the list of the vectors on the right hand side of the forward vector is empty, do the above process on this list instead.



My questions here are:
1. This algorithm contains a lot of "if" statement, is that we try to stay away from that sort of thing in Mathematica? If that's the case, how can I do it without "if" ?
2. If "if" cannot be avoid, how can I implement the above algorithm in a nice way in Mathematica.



(For more info: I've done this in VB.net but I stuck in Mathematica. This is the task that I have to find a cycle in a graph. The vertices are defined by its 2D coordinates. It requires the cycle to start at the most left vertex and the keep "turn right" at every vertex until the path comes back to the initial vertex.)










share|improve this question





























    1














    I have a list of 100 vectors 2D (x,y) defined by RandomReal[1.0, {100, 2}] and a given forward vector such as {1, 1}. My ultimate objective is to find the vector on the most right hand side of the forward vector. If there is non such a vector, then pick up the first vector on the left of the forward vector.



    I can do this by firstly classifying the initial list of vectors into 2 lists: 1 list contains all vectors on the right hand side of the forward vector. The second contains all vectors on its left hand side. The criterion to define whether a vector on the right hand side of the forward vector is that its cross product between the considered vector with the forward vector is positive. Negative result would mean it is on the left of the forward vector.



    The next step would be to check if the list of the vectors on the right hand side of the forward vector is empty. If not, check the relative position of the first 2 vectors in that list, only keep the vector on the right hand side, and then check the relative position between the kept vector and the third vector in the list and continue to do so until the end of the list.



    If the list of the vectors on the right hand side of the forward vector is empty, do the above process on this list instead.



    My questions here are:
    1. This algorithm contains a lot of "if" statement, is that we try to stay away from that sort of thing in Mathematica? If that's the case, how can I do it without "if" ?
    2. If "if" cannot be avoid, how can I implement the above algorithm in a nice way in Mathematica.



    (For more info: I've done this in VB.net but I stuck in Mathematica. This is the task that I have to find a cycle in a graph. The vertices are defined by its 2D coordinates. It requires the cycle to start at the most left vertex and the keep "turn right" at every vertex until the path comes back to the initial vertex.)










    share|improve this question



























      1












      1








      1







      I have a list of 100 vectors 2D (x,y) defined by RandomReal[1.0, {100, 2}] and a given forward vector such as {1, 1}. My ultimate objective is to find the vector on the most right hand side of the forward vector. If there is non such a vector, then pick up the first vector on the left of the forward vector.



      I can do this by firstly classifying the initial list of vectors into 2 lists: 1 list contains all vectors on the right hand side of the forward vector. The second contains all vectors on its left hand side. The criterion to define whether a vector on the right hand side of the forward vector is that its cross product between the considered vector with the forward vector is positive. Negative result would mean it is on the left of the forward vector.



      The next step would be to check if the list of the vectors on the right hand side of the forward vector is empty. If not, check the relative position of the first 2 vectors in that list, only keep the vector on the right hand side, and then check the relative position between the kept vector and the third vector in the list and continue to do so until the end of the list.



      If the list of the vectors on the right hand side of the forward vector is empty, do the above process on this list instead.



      My questions here are:
      1. This algorithm contains a lot of "if" statement, is that we try to stay away from that sort of thing in Mathematica? If that's the case, how can I do it without "if" ?
      2. If "if" cannot be avoid, how can I implement the above algorithm in a nice way in Mathematica.



      (For more info: I've done this in VB.net but I stuck in Mathematica. This is the task that I have to find a cycle in a graph. The vertices are defined by its 2D coordinates. It requires the cycle to start at the most left vertex and the keep "turn right" at every vertex until the path comes back to the initial vertex.)










      share|improve this question















      I have a list of 100 vectors 2D (x,y) defined by RandomReal[1.0, {100, 2}] and a given forward vector such as {1, 1}. My ultimate objective is to find the vector on the most right hand side of the forward vector. If there is non such a vector, then pick up the first vector on the left of the forward vector.



      I can do this by firstly classifying the initial list of vectors into 2 lists: 1 list contains all vectors on the right hand side of the forward vector. The second contains all vectors on its left hand side. The criterion to define whether a vector on the right hand side of the forward vector is that its cross product between the considered vector with the forward vector is positive. Negative result would mean it is on the left of the forward vector.



      The next step would be to check if the list of the vectors on the right hand side of the forward vector is empty. If not, check the relative position of the first 2 vectors in that list, only keep the vector on the right hand side, and then check the relative position between the kept vector and the third vector in the list and continue to do so until the end of the list.



      If the list of the vectors on the right hand side of the forward vector is empty, do the above process on this list instead.



      My questions here are:
      1. This algorithm contains a lot of "if" statement, is that we try to stay away from that sort of thing in Mathematica? If that's the case, how can I do it without "if" ?
      2. If "if" cannot be avoid, how can I implement the above algorithm in a nice way in Mathematica.



      (For more info: I've done this in VB.net but I stuck in Mathematica. This is the task that I have to find a cycle in a graph. The vertices are defined by its 2D coordinates. It requires the cycle to start at the most left vertex and the keep "turn right" at every vertex until the path comes back to the initial vertex.)







      list-manipulation






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 1 hour ago









      Szabolcs

      158k13432926




      158k13432926










      asked 2 hours ago









      N.T.C

      30717




      30717






















          2 Answers
          2






          active

          oldest

          votes


















          2














          pts = RandomReal[1.0, {100, 2}];
          vec = {1, 1};


          Rotate the elements of pts such that you want the one with small positive first coordinate (or maximal negative first coordinate if no one has positive first coordinate):



          rotated = Transpose[RotationMatrix[{vec, {0, 1}}].Transpose[pts]];


          Add the vector {0, 0} at position 1 and make a list with the vector indices ordering the points from left to right:



          order = Ordering[Prepend[rotated, {0, 0}]]


          Now Ordering[order, 1] yields the position of {0, 0}



          pts[[Extract[Append[order, order[[-2]]], Ordering[order, 1] + 1] - 1]]





          share|improve this answer





























            0














            Here is an implementation of the algorithm that you describe:



            pts = RandomReal[2, {50, 2}];
            vec = {1, 1};

            rhsQ[vec_, pt_] := Sign@Last@Cross[Append[vec, 0], Append[pt, 0]] == -1

            onRHS = rhsQ[vec, #] & /@ pts;

            rhs = Pick[pts, onRHS];
            lhs = Pick[pts, onRHS];

            rightmost[v1_, v2_] := If[rhsQ[v2, v1], v2, v1]
            findRightmost[vecs_] := Fold[rightmost, vecs]

            res = If[
            rhs === {},
            findRightmost[lhs],
            findRightmost[rhs]
            ];

            Graphics[{
            Line[{{0, 0}, Normalize[#]}] & /@ pts,
            Red, Line[{{0, 0}, 1.1 Normalize[vec]}],
            Green, Line[{{0, 0}, 1.1 Normalize[res]}]
            }]


            Mathematica graphics



            There are two ifs in there, but I don't see it as a problem. I do however favor the type of solution that Coolwater posted.





            share





















              Your Answer





              StackExchange.ifUsing("editor", function () {
              return StackExchange.using("mathjaxEditing", function () {
              StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
              StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
              });
              });
              }, "mathjax-editing");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "387"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: false,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f188669%2fhow-to-avoid-if-statement-in-mathematica%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              2














              pts = RandomReal[1.0, {100, 2}];
              vec = {1, 1};


              Rotate the elements of pts such that you want the one with small positive first coordinate (or maximal negative first coordinate if no one has positive first coordinate):



              rotated = Transpose[RotationMatrix[{vec, {0, 1}}].Transpose[pts]];


              Add the vector {0, 0} at position 1 and make a list with the vector indices ordering the points from left to right:



              order = Ordering[Prepend[rotated, {0, 0}]]


              Now Ordering[order, 1] yields the position of {0, 0}



              pts[[Extract[Append[order, order[[-2]]], Ordering[order, 1] + 1] - 1]]





              share|improve this answer


























                2














                pts = RandomReal[1.0, {100, 2}];
                vec = {1, 1};


                Rotate the elements of pts such that you want the one with small positive first coordinate (or maximal negative first coordinate if no one has positive first coordinate):



                rotated = Transpose[RotationMatrix[{vec, {0, 1}}].Transpose[pts]];


                Add the vector {0, 0} at position 1 and make a list with the vector indices ordering the points from left to right:



                order = Ordering[Prepend[rotated, {0, 0}]]


                Now Ordering[order, 1] yields the position of {0, 0}



                pts[[Extract[Append[order, order[[-2]]], Ordering[order, 1] + 1] - 1]]





                share|improve this answer
























                  2












                  2








                  2






                  pts = RandomReal[1.0, {100, 2}];
                  vec = {1, 1};


                  Rotate the elements of pts such that you want the one with small positive first coordinate (or maximal negative first coordinate if no one has positive first coordinate):



                  rotated = Transpose[RotationMatrix[{vec, {0, 1}}].Transpose[pts]];


                  Add the vector {0, 0} at position 1 and make a list with the vector indices ordering the points from left to right:



                  order = Ordering[Prepend[rotated, {0, 0}]]


                  Now Ordering[order, 1] yields the position of {0, 0}



                  pts[[Extract[Append[order, order[[-2]]], Ordering[order, 1] + 1] - 1]]





                  share|improve this answer












                  pts = RandomReal[1.0, {100, 2}];
                  vec = {1, 1};


                  Rotate the elements of pts such that you want the one with small positive first coordinate (or maximal negative first coordinate if no one has positive first coordinate):



                  rotated = Transpose[RotationMatrix[{vec, {0, 1}}].Transpose[pts]];


                  Add the vector {0, 0} at position 1 and make a list with the vector indices ordering the points from left to right:



                  order = Ordering[Prepend[rotated, {0, 0}]]


                  Now Ordering[order, 1] yields the position of {0, 0}



                  pts[[Extract[Append[order, order[[-2]]], Ordering[order, 1] + 1] - 1]]






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 1 hour ago









                  Coolwater

                  14.6k32552




                  14.6k32552























                      0














                      Here is an implementation of the algorithm that you describe:



                      pts = RandomReal[2, {50, 2}];
                      vec = {1, 1};

                      rhsQ[vec_, pt_] := Sign@Last@Cross[Append[vec, 0], Append[pt, 0]] == -1

                      onRHS = rhsQ[vec, #] & /@ pts;

                      rhs = Pick[pts, onRHS];
                      lhs = Pick[pts, onRHS];

                      rightmost[v1_, v2_] := If[rhsQ[v2, v1], v2, v1]
                      findRightmost[vecs_] := Fold[rightmost, vecs]

                      res = If[
                      rhs === {},
                      findRightmost[lhs],
                      findRightmost[rhs]
                      ];

                      Graphics[{
                      Line[{{0, 0}, Normalize[#]}] & /@ pts,
                      Red, Line[{{0, 0}, 1.1 Normalize[vec]}],
                      Green, Line[{{0, 0}, 1.1 Normalize[res]}]
                      }]


                      Mathematica graphics



                      There are two ifs in there, but I don't see it as a problem. I do however favor the type of solution that Coolwater posted.





                      share


























                        0














                        Here is an implementation of the algorithm that you describe:



                        pts = RandomReal[2, {50, 2}];
                        vec = {1, 1};

                        rhsQ[vec_, pt_] := Sign@Last@Cross[Append[vec, 0], Append[pt, 0]] == -1

                        onRHS = rhsQ[vec, #] & /@ pts;

                        rhs = Pick[pts, onRHS];
                        lhs = Pick[pts, onRHS];

                        rightmost[v1_, v2_] := If[rhsQ[v2, v1], v2, v1]
                        findRightmost[vecs_] := Fold[rightmost, vecs]

                        res = If[
                        rhs === {},
                        findRightmost[lhs],
                        findRightmost[rhs]
                        ];

                        Graphics[{
                        Line[{{0, 0}, Normalize[#]}] & /@ pts,
                        Red, Line[{{0, 0}, 1.1 Normalize[vec]}],
                        Green, Line[{{0, 0}, 1.1 Normalize[res]}]
                        }]


                        Mathematica graphics



                        There are two ifs in there, but I don't see it as a problem. I do however favor the type of solution that Coolwater posted.





                        share
























                          0












                          0








                          0






                          Here is an implementation of the algorithm that you describe:



                          pts = RandomReal[2, {50, 2}];
                          vec = {1, 1};

                          rhsQ[vec_, pt_] := Sign@Last@Cross[Append[vec, 0], Append[pt, 0]] == -1

                          onRHS = rhsQ[vec, #] & /@ pts;

                          rhs = Pick[pts, onRHS];
                          lhs = Pick[pts, onRHS];

                          rightmost[v1_, v2_] := If[rhsQ[v2, v1], v2, v1]
                          findRightmost[vecs_] := Fold[rightmost, vecs]

                          res = If[
                          rhs === {},
                          findRightmost[lhs],
                          findRightmost[rhs]
                          ];

                          Graphics[{
                          Line[{{0, 0}, Normalize[#]}] & /@ pts,
                          Red, Line[{{0, 0}, 1.1 Normalize[vec]}],
                          Green, Line[{{0, 0}, 1.1 Normalize[res]}]
                          }]


                          Mathematica graphics



                          There are two ifs in there, but I don't see it as a problem. I do however favor the type of solution that Coolwater posted.





                          share












                          Here is an implementation of the algorithm that you describe:



                          pts = RandomReal[2, {50, 2}];
                          vec = {1, 1};

                          rhsQ[vec_, pt_] := Sign@Last@Cross[Append[vec, 0], Append[pt, 0]] == -1

                          onRHS = rhsQ[vec, #] & /@ pts;

                          rhs = Pick[pts, onRHS];
                          lhs = Pick[pts, onRHS];

                          rightmost[v1_, v2_] := If[rhsQ[v2, v1], v2, v1]
                          findRightmost[vecs_] := Fold[rightmost, vecs]

                          res = If[
                          rhs === {},
                          findRightmost[lhs],
                          findRightmost[rhs]
                          ];

                          Graphics[{
                          Line[{{0, 0}, Normalize[#]}] & /@ pts,
                          Red, Line[{{0, 0}, 1.1 Normalize[vec]}],
                          Green, Line[{{0, 0}, 1.1 Normalize[res]}]
                          }]


                          Mathematica graphics



                          There are two ifs in there, but I don't see it as a problem. I do however favor the type of solution that Coolwater posted.






                          share











                          share


                          share










                          answered 5 mins ago









                          C. E.

                          49.8k397202




                          49.8k397202






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Mathematica Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              Use MathJax to format equations. MathJax reference.


                              To learn more, see our tips on writing great answers.





                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                              Please pay close attention to the following guidance:


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f188669%2fhow-to-avoid-if-statement-in-mathematica%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Understanding the information contained in the Deep Space Network XML data?

                              Ross-on-Wye

                              Eastern Orthodox Church