# List, map function based on a condition

I have the following list:

input = {{0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1,
0, 1}, {0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1,
0, 1}, {1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0,
1, 0, 1}}


there are two conditions:

• When a '0' is followed by '1', the value of '0' change to .5
• When a '1' is followed by '0', the value of '0' change to .5

the desired output is:

output = [{{0, 0, 0, .5, 1, 1, 1, .5, 1, .5, 0, .5, 1, 1, .5, 1, .5,
0, .5, 1, .5, 1}, {.5, 1, .5, 1, .5, .5, 1, .5, 0, 0, 0, .5, 1,
1, .5, 1, .5, 0, .5, 1, .5, 1}, {1, 1, .5, .5, 1, 1, 1, .5, 0, 0,
0, .5, 1, 1, .5, 1, 0, 0, .5, 1, .5, 1}}]


Who has a suggestion how to get the desired output

• should desired[[3]] be {1, 1, 0.5, 0.5, 1, 1, 1, 0.5, 0, 0, 0, 0.5, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1}? – user1066 Aug 15 at 14:28

Using ReplaceRepeated (//.) and pattern matching:

input //. {{x___, 0, 1, y___} :> {x, 0.5, 1, y}, {x___, 1, 0, y___} :> {x, 1, 0.5, y}}


{{0, 0, 0, 0.5, 1, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1}, {0.5, 1, 0.5, 1, 0.5, 0.5, 1, 0.5, 0, 0, 0, 0.5, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1}, {1, 1, 0.5, 0.5, 1, 1, 1, 0.5, 0, 0, 0, 0.5, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1}}

Note that there is a slight difference between this and your suggested output, highlighted in bold. As @Nasser received this result by his method as well, I suspect that the original suggested output was in error.

• Tricky. I tried it similar inside Cases but only one substitution is made. What could be the reason? Thanks! – Ulrich Neumann Aug 15 at 14:08
• /. only tries to replace once per complete match, as I understand, so since each list matches {x___, 1, 0, y___} or the other it only undergoes one substitution each. //. explicitly retries until no matches remain. I think Cases works more like /. in that respect. – eyorble Aug 15 at 14:12
• Thanks, I have to think about it. – Ulrich Neumann Aug 15 at 14:17

You can also use a combination of SequenceReplace and FixedPoint:

f = Map[SequenceReplace[{{0, 1} -> Sequence[.5, 1], {1, 0} -> Sequence[1, .5]}]],

FixedPoint[f, input]


{{0, 0, 0, 0.5, 1, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1},
{0.5, 1, 0.5, 1, 0.5, 0.5, 1, 0.5, 0, 0, 0, 0.5, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1},
{1, 1, 0.5, 0.5, 1, 1, 1, 0.5, 0, 0, 0, 0.5, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1}}

You can also use Nest in place of FixedPoint:

Nest[f , input, 2] == %


True

For a rewriting problem, use rewriting explicitly:

input //. {
{x___, 0, 1, y___} -> {x, 0.5, 1, y},
{x___, 1, 0, y___} -> {x, 1, 0.5, y}
}
(*
{{0, 0, 0, 0.5, 1, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1},
{0.5, 1, 0.5, 1, 0.5, 0.5, 1, 0.5, 0, 0, 0, 0.5, 1,1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1},
{1, 1, 0.5, 0.5, 1, 1, 1, 0.5, 0, 0, 0, 0.5, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1}}
*)


This is not a "functional" way to do it. But an old fashioned loop and few if's. But it gives the result you show

foo[input_List] := Module[{n, i, current, next, before},
n = Length[input];

(*handle edge cases*)
If[n == 1, Return[input, Module]];
If[n == 2,
Return[If[input[[1]] == 0 && input[[2]] == 1, {0.5, 1},
If[input[[2]] == 0 && input[[1]] == 1, {1, 0.5}, input]],
Module]];

(*general case for list of length \[GreaterEqual] 3*)
Table[
current = input[[i]];
If[i == 1,
If[input[[i]] == 0 && input[[i + 1]] == 1, 0.5, input[[i]]]
,
If[i == n,
If[input[[n]] == 0 && input[[n - 1]] == 1, 0.5, input[[n]]]
,
before = input[[i - 1]];
next = input[[i + 1]];
If[current == 0 && next == 1, 0.5,
If[current == 0 && before == 1, 0.5, current]]
]
],
{i, 1, Length[input]}
]
]

input = {{0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1,
0, 1}, {0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0,
1, 0, 1}, {1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0,
0, 1, 0, 1}};


Now map foo on the input

 result = foo[#] & /@ input


gives

{{0, 0, 0, 0.5, 1, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 1, 0.5, 1, 0.5, 0,
0.5, 1, 0.5, 1}, {0.5, 1, 0.5, 1, 0.5, 0.5, 1, 0.5, 0, 0, 0, 0.5, 1,
1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1}, {1, 1, 0.5, 0.5, 1, 1, 1, 0.5,
0, 0, 0, 0.5, 1, 1, 0.5, 1, 0.5, 0, 0.5, 1, 0.5, 1}}


I suspect there might be a shorter way to do this if one works harder on it.