I'd like to introduce you to ~:/\ ~:/\ is an illustration of one of the things I really like about J. It is equivalent to 2 | +/\ ] but without the possibility of overflow. And it turns out to be really handy when reasoning about bit operations.
One way of describing it is as a slightly flawed self inverting edge detection operation. ~:/\ 0 0 1 0 0 0 1 0 0 0 0 1 1 1 1 0 0 0 ~:/\ ~:/\ 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 Notice how the opening 0 1 transition stays anchored in place, but the closing 1 0 transition drifts just a little bit. Now, if you use Henry's E. suggestion and look for 0 1 1 1 1 1 1 1 1 1 1 E. and 1 1 1 1 1 1 1 1 1 1 0 E. you will have bits marking the beginning of your lines and the endings of your lines. Use +. to combine these bit masks and you have a perfect candidate for ~:/\ Or, almost. You will need to add a leading zero to the beginning of each line if you want to detect lines on columns which are all 1s (and then drop that leading zero, later). For rows, I'd probably just transpose the array and use the version of the code designed for columns. (But you could try doing all the operations at rank 1, also.) Except that's still not quite right. Consider what happens if you encounter 0 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 -- here, you have the same bit marking an opening and a closing position. So, instead of combining the E. results using +. I think you should combine them using ~: -- this will do the right thing both for isolated marking bits and for conflicting marking bits, assuming you are OK with "almost complete lines" being classified as "solid". Good enough? Thanks, -- Raul On Wed, Feb 19, 2014 at 9:43 AM, Joe Bogner <[email protected]> wrote: > On Wed, Feb 19, 2014 at 7:25 AM, Henry Rich <[email protected]> wrote: > > > Look at > > > > (1 10$0) E. image > > > > or > > > > (10 $ 0) E. line > > > > > Thanks Henry, that worked well. I have a version that seems to work now > (albeit clunky) > > ]lines=: 4 10 $ (0 0), (5 $ 1), (3 $ 0),(5 $ 1), (0 0 0), (1 1), (10 $ 1) > lineStarts=:(1 5$1) E. lines > > markPixel=: 3 : 0 > shift1=:0,.(}:"1 y) NB. shift the array by 1 to the right > shift1Marks=: shift1 = 1 > shift1Marks+. y > ) > > s1=:markPixel lineStarts > s2=:markPixel s1 > s3=:markPixel s2 > s4=:markPixel s3 > > viewmat (s4=0) > viewmat (lines=0) > > Basically, I mark the first pixel of the line (having 5 consecutive 1s) and > then shift the array 4 more times and mark each one that is a 1 and OR it > with the input array. > > I'm happy to take any feedback from anyone on how to improve it. I know I > can make makePixel a 1 liner... > > markPixel=: 3 : 0 > y +. (0,.(}:"1 y) = 1) > ) > > NB. from 13 : > markPixel =: ] +. 0 ,. 1 = }:"1 > > I'm more interested in how to avoid the shifting 5 times. The problem is > that I don't know of anything that can look backwards to match, so I think > I need to shift forward. Or, I can use my earlier approach of marking the > last pixel of the line and then look forward, which shouldn't require > shifts. > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm > ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
