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
Valued Contributor
Valued Contributor

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
Valued Contributor
Valued Contributor

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!

SJT
Valued Contributor
Valued Contributor

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.