1

I figure this question has many solutions, and if an answer already exists it would be nice just to be referred to it.

I need a function that 'maps' over my list and produces a list of equal length of either 1 or 0 with particular conditions that switch the the result from 1 to 0.

The result starts as 0 and is carried into the next step unless one of these conditions is met:

  1. That when both the first and element is 1 we set our result to 1; this can happen on the first element of the list.

  2. When the last element is 0 we set our result to 0.

  3. However if we don't find a 1 at position two in any even numbered list counting from the switch to 1 before the next switch back to 0, then leave the result as 0 for the entire period.

Essentially step 3 requires that if for the period that the result could be 1 (according to steps 1. and 2.) that at least once the even numbered elements in that period have [[2]]=1.

For example if the data is {{0, 0, 1}, {1, 0, 1}, {0, 0, 1}, {1, 0, 1}, {0, 0, 1}, {1, 0, 1}, {0, 0, 0}} then the result of this algorithm is {0, 0, 0, 0, 0, 0}. Without the third condition it would yield {0, 1, 1, 1, 1, 1, 0}.

However if the data is {{0, 0, 1}, {1, 0, 1}, {0, 1, 1}, {1, 0, 1}, {0, 0, 1}, {1, 0, 1}, {0, 0, 0}} (note the third element has a 1 at position 2 which meets the criteria that is in the element that is in a odd position after the switch, in this case 1 element after), then the result should be {0, 1, 1, 1, 1, 0}.

So far I have tried a Which function in a Table. This is fine for steps 1. and 2., but not so good for 3.

Table[
 Which[
  i == 1 && data[[i, 1]] == 1 && data[[i, -1]] == 1, 1,
  i == 1, 0,
  i > 1 && (data[[i, 1]] == 1 || data[[i, 2]] == 1) && 
   data[[i, -1]] == 1, 1,
  i > 1 && (data[[i - 1, 1]] == 1 || newALtest[[i - 1, 2]] == 1) && 
   data[[i - 1, -1]] == 1 && data[[i, -1]] == 1, 1,
  i > 1, 0], {i, 1, Length[data]}]

Some example data is here

data={{0, 0, 0}, {0, 0, 0}, {0, 0, 1}, {1, 0, 1}, {0, 0, 1}, {1, 0, 1}, {0, 0, 1}, {1, 0, 1}, {0, 0, 0}, {0, 0, 0}, {1, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {1, 0, 0}, {1, 0, 1}, {0, 1, 1}, {1, 0, 0}, {0, 0, 0}, {1, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {1, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 1}, {1, 0, 1}, {0, 1, 1}, {0, 0, 0}, {0, 0, 1}, {0, 0, 1}, {1, 0, 1}, {0, 1, 1}, {0, 1, 1}, {0, 1, 1}, {0, 1, 1}, {0, 1, 1}}

Any tips about the approach to take would probably get me heading in the right direction (I'm trying steps 1. and 2. first, then using that result for another test, but I'm still mighty confused).

For the above table, the result will be

result= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
Cameron Murray
  • 921
  • 7
  • 16
  • 5
    -1 and -2 are perfectly valid indices. However I find your description very hard to follow, especially point 3. Please try to clarify it and perhaps show a small example of how 3 is decided. – rm -rf Aug 26 '13 at 05:16
  • I edited your data to add missing brackets. The results still don't seem to match the problem description. – Mr.Wizard Aug 26 '13 at 06:48
  • Also, what exactly is a "period?" Additionally, could you please provide the result for data without condition #3 so I can see if I understand conditions #1 and #2? – Mr.Wizard Aug 26 '13 at 06:51
  • 1
    My mistake Mr. Wizard. The second condition had the wrong part of the element in it. Maybe it is clearer now?

    The period between when condition 1. is satisfied, and then condition 2. is satisfied.

    – Cameron Murray Aug 26 '13 at 07:08
  • There appears to be a contradiction still. In one paragraph you say: "at least once the even numbered elements in that period" and in another "the criteria that is in the element that is in a odd position after the switch, in this case 1 element after" -- what does this mean? – Mr.Wizard Aug 26 '13 at 07:40
  • Cameron, I refined my answer and gave a better description of the process. – Mr.Wizard Aug 26 '13 at 16:26

1 Answers1

11

I believe I have a solution for you, assuming we've worked out all the discrepancies in the original question.

You will need my dynamicPartition function or one of its "core function" equivalents.

process[data_List] :=
  Module[{f, s1, s2},
    f[_, {1, ___, 1}] = 1;
    f[_, {___, 0}] = 0;
    f[x_, _] := x;
    s1 = Split @ Rest @ FoldList[f, 0, data];
    s2 = s1; s2[[All, ;; ;; 2]] = 0;
    dynamicPartition[data[[All, 2]], Length /@ s1] //
     Flatten[s1 * Unitize @ Total[s2 * #, {2}]] &
  ]

process[data] === result

True

Here is a terse description:

  • The function f is a pattern-based function that performs your steps #1 and #2

  • f is used in FoldList to apply it to each sublist, keeping track of the prior value which is used in the case that neither the #1 or #2 rule matches.

  • Split partitions the resulting list into "periods" as you describe them. (s1)

  • The Split result is copied to s2, then s2[[All, ;; ;; 2]] = 0 replaces all values at odd positions within the periods with zeros, which is needed for condition #3.

  • dynamicPartition is used to split the column-2 data into the periods.

  • This data is then multiplied with the s2 data: only non-zero values at the same place in both data sets will give a positive result. Each period is then totaled, then these totals are unitized, multiplied with the original Split data (s1), and finally flattened.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Beauty! Give my some time to decipher it. I really needed pointing in the right direction. Thanks – Cameron Murray Aug 26 '13 at 08:00
  • @Cameron I took pity and added at least a basic description so you don't pull your hair out. :^) – Mr.Wizard Aug 26 '13 at 08:07
  • That will definitely save me some hair loss ;-) – Cameron Murray Aug 26 '13 at 08:54
  • I voted for this, even though I have no clue what the code does, but only because it looks cool. – Nasser Aug 26 '13 at 08:56
  • @Nasser Thanks. It took more than the usual effort to make sense of this question so I appreciate the compensation. :D – Mr.Wizard Aug 26 '13 at 08:58
  • "It took more than the usual effort to make sense of this question" Yeah, I apologise for that. My mind was so wrecked after trying for half the day that I was confusing recent attempts with previous attempts and simply couldn't get my words out straight. – Cameron Murray Aug 26 '13 at 09:12
  • +1 for compensation and creative use of Part :). It kind of makes me want to use lisp instead though :P – Jacob Akkerboom Aug 26 '13 at 10:09
  • @Cameron Don't worry, it happens. Myself, I can't sleep right the last few days and I'm seriously sleep deprived, so I'm making a lot of mistakes; you'd do well to carefully check this answer. – Mr.Wizard Aug 26 '13 at 15:09
  • @Jacob how would you write this in Lisp? – Mr.Wizard Aug 26 '13 at 15:11
  • @Mr.Wizard ahh I wish I knew (syntaxwise) :), I've only read one book about it I am afraid. But it has this thing called generic setters. This is basically what I read. It is the right book too :). – Jacob Akkerboom Aug 26 '13 at 15:18
  • 1
    I'd like to give two upvotes really, one for the answer and one for figuring out the question :-) – Simon Woods Aug 26 '13 at 16:11