11
$\begingroup$

How to write this small piece in a functional way (ie. without state variables)?:

test[oldJ_List, newJ_List] := Total[Abs[oldJ - newJ]] > 1;
relax[j_List, x_?NumericQ] := Mean[Nearest[j, x, 4]];

j = Range[100]; (* any numeric list *)
j1 = j/2; (*some initial value for the While[] test to return True*)

While[test[j1, j],
 j1 = j; 
 (j[[#]] = relax[j, j[[#]]]) & /@ Range@Length@j]
$\endgroup$
1
  • $\begingroup$ test[] can also be defined as test[oldJ_List, newJ_List] := ManhattanDistance[oldJ, newJ] > 1. $\endgroup$ Sep 30, 2012 at 9:52

2 Answers 2

10
$\begingroup$

Let me first redefine your relax to return a list as:

Clear@relax1
relax1[j_List, i_Integer] := MapAt[Mean[Nearest[j, #, 4]] &, j, i]

Then, the algorithm can be written in a functional way without state variables using Fold and NestWhile as follows (if I understood your intentions correctly):

With[{indx = Range@Length@#}, NestWhile[Fold[relax1[#1, #2] &, #, indx] &, #, test, 2]] &@j
$\endgroup$
2
  • 2
    $\begingroup$ Very nice! thanks! $\endgroup$ Sep 29, 2012 at 21:45
  • $\begingroup$ BTW. This is the first iterative structure I used in this answer. I'm still thinking about the second one $\endgroup$ Sep 30, 2012 at 3:21
2
$\begingroup$

This also works:

fold = Function[{lst},Fold[(ReplacePart[#1, #2 ->relax[#1, #1[[#2]]]]) &, 
  lst,  Range@Length@lst]]; 
fxpnt = FixedPoint[fold, #, SameTest -> (Not[test[#1, #2]] &)] &;
fxpnt@j
$\endgroup$
3
  • $\begingroup$ nice! Why the N@? $\endgroup$ Sep 30, 2012 at 22:17
  • 1
    $\begingroup$ forgot to remove N (i was using it to simplify the printed output) ... removed now. $\endgroup$
    – kglr
    Sep 30, 2012 at 22:23
  • $\begingroup$ @belisarius, on second thought (and few limited timing tests with j=Range[1000]) it seems that N is actually cruical for speed. $\endgroup$
    – kglr
    Sep 30, 2012 at 23:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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