Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

For example, if I want a list of $\phi(n)$ for $1 \leq n \leq 100$ but if $n$ is a multiple of 3 I want to show a 3 instead of $\phi(n)$. I tried

ReplacePart[EulerPhi[Range[100]], Table[{3n}, {n, 33}] -> 3]

but this just feels wrong.

Or a somewhat more involved example: show $4n$ except when $n \equiv 1 \pmod 4$, in which case show just $n$.

I am aware both of these can be accomplished with If. But there's a better way, isn't there?

share|improve this question
1  
expr = Range[20]; expr[[3 ;; ;; 3]] = 3;expr – march Mar 25 at 18:19
    
@march was about to write that... – Sjoerd C. de Vries Mar 25 at 18:21
    
expr = 4 Range[20]; expr[[Range[1, 20, 4]]] = Range[1, 20, 4]; expr :))) – garej Mar 25 at 22:02
up vote 8 down vote accepted

If you're okay with modifying the saved expression:

expr = Range[10]
expr[[3 ;; ;; 3]] = 3;
expr
(* {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} *)
(* {1, 2, 3, 4, 5, 3, 7, 8, 3, 10} *)

If you're not:

expr = Range[10];
MapAt[3 &, expr, {3 ;; ;; 3}]
(* {1, 2, 3, 4, 5, 3, 7, 8, 3, 10} *)

A modified version of OP's

ReplacePart[expr, List /@Range[3, Length@expr, 3] -> 3]

For the second example, a modified version of OP:

expr = Range[10]^2
ReplacePart[expr, Thread[Range[1, 10, 4] -> Range[1, 10, 4]]]
(* {1, 4, 9, 16, 25, 36, 49, 64, 81, 100} *)
(* {1, 4, 9, 16, 5, 36, 49, 64, 9, 100} *)

and also

MapIndexed[If[Mod[First@#2, 4] == 1, First@#2, #1] &, expr]
Module[{i = -3}, MapAt[(i = i + 4) &, expr, {;; ;; 4}]]
share|improve this answer
    
Interesting Part specification for MapAt. Documented? – unlikely Mar 25 at 18:31
    
@unlikely. I don't know. I learned that here! But there is this hint in the documentation: "MapAt works on Association objects, using the same specification for keys as in Part." – march Mar 25 at 18:32
1  
@march, here is another option: # /. Thread[Take[#, {3, -1, 3}] -> 3] &@Range[10] – garej Mar 25 at 19:12
  If[Mod[#, 3] == 0, 3, EulerPhi[#]] & /@ Range[10]
  If[Mod[#, 4] == 1, #, 4 #] & /@ Range[10]
share|improve this answer

You can use pattern also:

 ReplacePart[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, n_ /; IntegerQ[n/3] :> 3]

I did not understand the second part of your question so I did not post answer for that.

share|improve this answer
    
You could've used Divisible[n, 3] for the test. – J. M. Mar 26 at 0:47

Riffle version (relatively fast, by the way):

Riffle[Drop[Range[10], {3, -1, 3}], 3, 3]

{1, 2, 3, 4, 5, 3, 7, 8, 3, 10}


For the second part, using @march:

expr = Range[10]^2;
expr[[Range[1, 10, 4]]] = Range[1, 10, 4]; expr

{1, 4, 9, 16, 5, 36, 49, 64, 9, 100}

share|improve this answer
1  
The Riffle version is very fast! +1. Here's a Riffle for the second part: Riffle[Drop[Range[10]^2, {1, -1, 4}], Range[1, 10, 4], {1, -1, 4}]. – march Mar 28 at 5:05
    
@march, wow, I've missed such extension of Riffle, thanks for the tip... – garej Mar 28 at 6:00

This answer uses a function defined in my answer here. If you find the definition too complicated, also see Mr.Wizards answer.

This does not calculate EulerPhi more often than necessary.

Riffle[EulerPhi /@ nonMultsCondManMod[10, 3], 3, {3, -1, 3}]

For the more involved example

nn = 20;
mm = 4;
Riffle[mm (nonMultsCondManMod[nn, mm] + 1), 
 Range[1, nn, mm], {1, -mm, mm}]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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