How to avoid “if statement” in Mathematica?
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
add a comment |
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
add a comment |
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
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
list-manipulation
edited 1 hour ago
Szabolcs
158k13432926
158k13432926
asked 2 hours ago
N.T.C
30717
30717
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
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]]
add a comment |
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]}]
}]
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.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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]]
add a comment |
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]]
add a comment |
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]]
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]]
answered 1 hour ago
Coolwater
14.6k32552
14.6k32552
add a comment |
add a comment |
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]}]
}]
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.
add a comment |
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]}]
}]
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.
add a comment |
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]}]
}]
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.
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]}]
}]
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.
answered 5 mins ago
C. E.
49.8k397202
49.8k397202
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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