cancel
Showing results for 
Search instead for 
Did you mean: 

Binary iteration question

MG4
New Contributor II

Hi All,

Given a binary list of any length e.g:
test:00001111000111001101000b

Is there some way to iterate through this with 2 values - e.g input:3 , output:2

So that every time the input is 1 at least 3 times in a row (input param) , we let the result equal 1 and only when there are more consecutive 0's than the output param, do we reset.

Example output for test above:

00000011110001111111110b

 

Another sample:
Input: 110010111001111b

Output: 000000001111111b

 

I tried to use msum so if input is 3:
3 msum test

Gives the points where 3 consecutive 1's have been detected however can't seem to carry this value for the next two iterations.

 

Any help appreciated!

1 ACCEPTED SOLUTION

rocuinneagain
Contributor II
Contributor II

This becomes easier by splitting the problem in 2 parts.

  1. Finding the indexes where needed number of 1b is hit
  2. Finding the indexes where needed number of 0b is hit

These are the only indexes that matter. Then a prototype list can be populated with nulls before having the important indexes overlaid. Then the prevailing values are carried forward by fills.

q)f:{o:count[z]#0N;o:@[o;where x=x msum z;:;1];y:y+1;"b"$0^fills @[o;where y=y msum not z;:;0]}
q)f[3;2] 00001111000111001101000b
00000011110001111111110b
q)f[3;2] 110010111001111b
000000001111111b

 

View solution in original post

3 REPLIES 3

rocuinneagain
Contributor II
Contributor II

This becomes easier by splitting the problem in 2 parts.

  1. Finding the indexes where needed number of 1b is hit
  2. Finding the indexes where needed number of 0b is hit

These are the only indexes that matter. Then a prototype list can be populated with nulls before having the important indexes overlaid. Then the prevailing values are carried forward by fills.

q)f:{o:count[z]#0N;o:@[o;where x=x msum z;:;1];y:y+1;"b"$0^fills @[o;where y=y msum not z;:;0]}
q)f[3;2] 00001111000111001101000b
00000011110001111111110b
q)f[3;2] 110010111001111b
000000001111111b

 

MG4
New Contributor II

Nice solution, thanks!

Rian’s excellent logic can be refactored to use the Over iterator. (You might not be familiar with Over with a ternary or quaternary function.)

 

q)g:{"b"$0^fills@/[;(x,y+1){where x=x msum y}'1 not\z;:;1 0]count[z]#0N}
q)g[3;2] 00001111000111001101000b
00000011110001111111110b
q)g[3;2] 110010111001111b
000000001111111b

 

The key concept here is that the first argument of Amend At Over @/ is the initial state: count[z]#0N. The other (right) arguments are same-length lists, or atoms.  Over works through the argument lists in succession.

Once again we see the Zen monks as a point-free alternative to writing (z;not z).

The refactoring here doesn’t save much time, but spotting opportunities like this improves your ability to find iterator solutions, some of which will save you significant CPU.