4
$\begingroup$

Amateur here! I made a short piece of code that creates a line that turns in the positive direction (up or to the right) if the sum of the digits of the outcome of a function (x^2 in this case) is even, or else it moves in the negative direction.

QUESTION: How can I avoid the use of so many variables (l1 to l5) while maintaining clarity of code?

Especially I feel that doing MapAt twice (for even and odd items) can be done more efficiently.

f[x_] := x^2 length = 600; L1 = If[EvenQ[#], 1, -1] & /@ Total[IntegerDigits[f[Range[0, length]]], {2}]; L2 = MapAt[{#, 0} &, L1, 1 ;; ;; 2]; L3 = MapAt[{0, #} &, L2, 2 ;; ;; 2]; L4 = Table[Sum[L3[[i]], {i, 1, j}], {j, 1, length + 1}]; L5 = PrependTo[L4, {0, 0}]; Graphics[Line[L5]] 
$\endgroup$
4
  • 1
    $\begingroup$ can you rewrite above without using l as first letter in your variables? They look like 1 and makes it hard to read. You can use L1 for example instead of l1 $\endgroup$ Commented Nov 6, 2022 at 20:03
  • $\begingroup$ @Nasser thanks, done! $\endgroup$ Commented Nov 6, 2022 at 20:05
  • 1
    $\begingroup$ Look at AnglePath documentation. $\endgroup$ Commented Nov 6, 2022 at 20:08
  • 1
    $\begingroup$ See also fewer vs. less :) $\endgroup$ Commented Nov 7, 2022 at 5:22

4 Answers 4

8
$\begingroup$

Since OP asks about good programming practice, my answer in this case and in general would be: Write useful functions. Maybe one can add: Avoid global variables, which often means using Module. If you have many functions, organize them in a package.

One could split this up into several small functions, but I think it is readable like this:

funnyPath[pow_,base_,n_] := Graphics[Line[Accumulate[Array[ If[EvenQ[Total[IntegerDigits[#^pow,base]]],1,-1]* If[EvenQ[#],{1,0},{0,1}]&, n]]]]; 

Example 1: This uses OP's settings

funnyPath[2,10,600] 

enter image description here

Example 2:

funnyPath[2,4,2000] 

enter image description here

Example 3: These things sure look funny

GraphicsGrid[Table[ funnyPath[pow,base,1000], {pow,2,7},{base,2,10,2}]] 

enter image description here

$\endgroup$
4
$\begingroup$

No variables (well, except for length)

f[x_] := x^2 length = 600; If[EvenQ[#], 1, -1] & /@ Total[IntegerDigits[f[Range[0, length]]], {2}]; MapAt[{#, 0} &, %, 1 ;; ;; 2]; MapAt[{0, #} &, %, 2 ;; ;; 2]; Table[Sum[%[[i]], {i, 1, j}], {j, 1, length + 1}]; Prepend[%, {0, 0}]; Graphics[Line[%]] 

Mathematica graphics

$\endgroup$
2
  • 1
    $\begingroup$ Is using those % good programming practice? It seems to me that if you add a line somewhere in between you're in trouble? $\endgroup$ Commented Nov 6, 2022 at 21:22
  • 1
    $\begingroup$ Well, you asked How can I avoid the use of so many variables (l1 to l5) while maintaining clarity of code? so I assumed you want to keep the same logic of your code but without using L1,L2,etc... Other than rewriting the whole algorithm in completely new way (which in Mathematica there are 10 ways to do this), that is the only way I could think of. And using % is fine to refer the previous command result without making new variable to store it in, if that is the only reason that variable was used for. Alternative is to use composition, as in f5[f4[f3[f2[f1[x]]]]] . Is this more clear? $\endgroup$ Commented Nov 6, 2022 at 21:36
4
$\begingroup$

With "Map" and "Accumulate" and "Prepend":

c = 0; If[EvenQ[#], 1, -1] & /@ Total[IntegerDigits[f[Range[0, length]]], {2}]; Accumulate[If[EvenQ[c++], {#, 0}, {0, #}] & /@ %] // Prepend[#, {0, 0}] &; Graphics[Line[%]] 

enter image description here

$\endgroup$
4
  • $\begingroup$ What's the use of c here? $\endgroup$ Commented Nov 6, 2022 at 20:29
  • $\begingroup$ c is used to distinguish even and odd indexed entries in L1 (the output of the second line) $\endgroup$ Commented Nov 6, 2022 at 20:34
  • 3
    $\begingroup$ Is using those % good programming practice? It seems to me that if you add a line somewhere in between you're in trouble? $\endgroup$ Commented Nov 6, 2022 at 21:23
  • $\begingroup$ No problem, you may store the output from a line in a temporary variable and use it in the next line. $\endgroup$ Commented Nov 7, 2022 at 7:49
1
$\begingroup$

This is another option:

f[x_] := x^2; length = 600; Total[IntegerDigits[f[Range[0, length]]], {2}] // Map[If[EvenQ[#], 1, -1] &] // MapAt[{#, 0} &, 1 ;; ;; 2] // MapAt[{0, #} &, 2 ;; ;; 2] // FoldList[Plus] // Prepend[{0, 0}] // Line // Graphics 

One function per line.

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.