dukereg
dukereg

Reputation: 722

How to force grouping of monadic verbs?

I came up with an incorrect J verb in my head, which would find the proportion of redundant letters in a string. I started with just a bunch of verbs with no precedence defined, and tried grouping inwards:

   c=. 'cool' NB. The test data string, 1/4 is redundant.
   box =. 5!:2 NB. The verb to show the structure of another verb in a box.
   p=.%#~.%# NB. First attempt. Meant to read "inverse of (tally of unique divided by tally)".
   box < 'p'
┌─┬─┬────────┐
│%│#│┌──┬─┬─┐│
│ │ ││~.│%│#││
│ │ │└──┴─┴─┘│
└─┴─┴────────┘
   p2=.%(#~.%#) NB. The first tally is meant to be in there with the nub sieve, so paren everything after the inverse monad.
   box < 'p2'
┌─┬────────────┐
│%│┌─┬────────┐│
│ ││#│┌──┬─┬─┐││
│ ││ ││~.│%│#│││
│ ││ │└──┴─┴─┘││
│ │└─┴────────┘│
└─┴────────────┘
   p3=. %((#~.)%#) NB. The first tally is still not grouped with the nub sieve, so paren the two together directly. 
   box < 'p3'
┌─┬────────────┐
│%│┌──────┬─┬─┐│
│ ││┌─┬──┐│%│#││
│ │││#│~.││ │ ││
│ ││└─┴──┘│ │ ││
│ │└──────┴─┴─┘│
└─┴────────────┘
   p3 c  NB. Looks about right, so test it!
|length error: p3
|       p3 c
   (#~.)c  NB. Unexpected error, but I guessed as to what part had the problem.
|length error
|       (#~.)c

My question is, why did my approach to grouping fail with this length error, and how should I have grouped it to get the desired effect? (I assume it is something to do with turning it into a hook instead of grouping, or it just not realising it needs to use the monad forms, but I don't know how to verify or get around it if so.)

Upvotes: 1

Views: 85

Answers (1)

Dane
Dane

Reputation: 1211

Fork and compose.

(# ~.) is a hook. This is probably what you're not expecting. (# ~.) 'cool' is applying ~. to 'cool' to give you 'col'. But as it's a monadic hook, it is then attempting 'cool' # 'col', which isn't what you're intending and which gives a length error.

To get 0.25 as the ratio of redundant characters in a string, don't use the reciprocal (%). You just subtract from 1 the ratio of unique characters. This is pretty straightforward with a fork:

   (1 - #&~. % #) 'cool'
0.25
   p9 =. 1 - #&~. % #
   box < 'p9'
┌─┬─┬──────────────┐
│1│-│┌────────┬─┬─┐│
│ │ ││┌─┬─┬──┐│%│#││
│ │ │││#│&│~.││ │ ││
│ │ ││└─┴─┴──┘│ │ ││
│ │ │└────────┴─┴─┘│
└─┴─┴──────────────┘

Compose (&) ensures that you tally (#) the nub (~.) together, so that the fork grabs it as a single verb. The fork is a series of three verbs that applies the first and third verb, and then applies the middle verb to the results. So #&~. % # is the fork, where #&~. is applied to the string, resulting in 3. # is applied, resulting in 4. And then % is applied to those results, as 3 % 4, giving you 0.75. That's our ratio of unique characters.

1 - is just to get us 0.25 instead of 0.75. % 0.75 is the same as 1 % 0.75, which gives you 1.33333.

Upvotes: 2

Related Questions