0

I have this snippet:

points = CirclePoints[{10, 0}, 4];

The result will be an array of 2D coordinates.

{{10, 0}, {0, 10}, {-10, 0}, {0, -10}}

I want to shift all of them by a certain vector $\mathbf{p}$.

p = {4, 5};
points + {p, p, p, p}

Nothing is wrong up to now. But instead of a square, suppose I want a dodecagon. Then the code changes to:

points = CirclePoints[{10, 0}, 12];
p = {4, 5};
points + {p, p, p, p, p, p, p, p, p, p, p, p}

How can I avoid entering all those repeated p's ?

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
AHB
  • 311
  • 1
  • 12

1 Answers1

3

Try this:

 points /. {x_, y_} -> {x, y} + p

(* {{14, 5}, {4, 15}, {-6, 5}, {4, -5}} *)

Have fun!

Alexei Boulbitch
  • 39,397
  • 2
  • 47
  • 96
  • I'm not fully comfortable with this solution for the following reason: {{1, 2}, {3, 4}, {5, 6}} /. {x_, y_} -> {x, y} + {a, b} gives {{1 + a, 2 + b}, {3 + a, 4 + b}, {5 + a, 6 + b}} but {{1, 2}, {3, 4}} /. {x_, y_} -> {x, y} + {a, b} gives {{1 + a, 2 + a}, {3 + b, 4 + b}}. Replace[..., {1}] instead of ReplaceAll would avoid this. – Szabolcs Jun 08 '16 at 09:13
  • @Szabolcs You are right. Have you an idea, why this phenomenon is met with the list of two items and disappears in the list with the three ones? – Alexei Boulbitch Jun 08 '16 at 09:19
  • That is because if the list if {{1,2}, {3,4}} then the pattern will match as x = {1,2} and y = {3,4} first. ReplaceAll has the property that it matches elements "from the outside towards the inside", i.e. it first tries the complete expression. If that does match, it tries its subexpressions. Then the subexpressions of subexpressions, etc. Until there is a match. When there is a match, it performs the replacement and doesn't look at deeper subexpressions anymore. – Szabolcs Jun 08 '16 at 09:21
  • With Replace, we can control at which level to do the pattern matching. Try both Replace[{{1, 2}, {3, 4}}, {x_, y_} -> {x, y} + {a, b}, {1}] and Replace[{{1, 2}, {3, 4}}, {x_, y_} -> {x, y} + {a, b}, {0}] and see the different results. Now try to ask Replace to match at all levels: Replace[{{1, 2}, {3, 4}}, {x_, y_} -> {x, y} + {a, b}, {0, Infinity}]. The result is now {{1 + 2 a, 2 + a + b}, {3 + a + b, 4 + 2 b}}. This is because of two differences with ReplaceAll: (1) the search is done from the inside towards the outside, starting with the deepest subexpressions ... – Szabolcs Jun 08 '16 at 09:25
  • ... (2) once a match is found, the replacement does not stop. Replace keeps looking at larger containing expressions and keeps doing more replacements. – Szabolcs Jun 08 '16 at 09:26
  • Why would anybody use this when CirclePoints[{4, 5}, {10, 0}, 12] will do the job? That is: the built-in function already provides translation. – m_goldberg Jun 08 '16 at 09:27
  • OK, I tried to illustrate this and it turns out I don't understand Replace. In short, I don't know why it prints {1,2} and {3,4} a second time a the end: Replace[{{1, 2}, {3, 4}}, {x_, y_} :> (Print[{x, y}]; {x, y} + {a, b}), {0, Infinity}]. I have a vague feeling I asked about this once but now I can't remember .. – Szabolcs Jun 08 '16 at 09:31
  • I figured it out. The reason is that Replace does all replacements on the expression first without allowing anything to be evaluated. When the replacements are complete, it allows the full expression to get finally evaluated. Illustration: Replace[{1, 2}, x_ :> Hold[Print[x]; x], {0, Infinity}] gives Hold[Print[{Hold[Print[1]; 1], Hold[Print[2]; 2]}]; {Hold[Print[1]; 1], Hold[Print[2]; 2]}]. If we now remove Hold and allow Print to evaluate, we get exactly the sequence of expression we observed above. – Szabolcs Jun 08 '16 at 09:44