Reputation: 722
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
Reputation: 1211
(# ~.)
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