What people like to do depends on the person. I tend to prefer compact
expressions, but other people have different preferences (and some
people prefer ([: f g) forms.

Generally speaking, if f and g represent verbs, then ([: f g) is
equivalent to f@:g and if g has infinite rank you can go f@g.
However... if f and g represent verb *definitions* then for the
general case you need (f)@:(g) -- you get a free parenthesis effect
with every name, so if you are removing the name you might need the
parenthesis that it provided. That said, if f was not a verb train
then you can go f@:(g) and if g has infinite rank you can go f@(g).
You can only eliminate the parenthesis from f@:(g) if it's g is a
single word -- this gets back to whether f and g represent verbs or
verb definitions ... or something else.

That said, note that if f and g represent something other than verbs
then ([: f g) might be an error, though there's a couple notable
exceptions to that rule which involve certain conjunctions. To see
this, note that @: is a conjunction. You can have f OR g be @: and the
other one be a verb. The result will always generate errors when given
a noun. However, if you instead use the : conjunction, surprisingly,
there will be cases where the result can be evaluated (though one of
the cases will not be the most compact form and will need another verb
before the result is a verb. Also that form is something that you
don't see used a lot (though it does have its uses - it's a "free
parenthesis" case that doesn't get a lot of attention).

Anyways... advent of code...

+/@(>./ - <./) is how I originally expressed the day two problem. I'd
ignore reading from a file, because I wouldn't use files here.

That said, I went and tried it - I put the example data in a ".;._2]0
:0 definition like this:

ss=:".;._2]0 :0
5 1 9 5
7 5 3
2 4 6 8
)

This raises an issue - the rows are "ragged". There's two ways of
dealing with this - one is you can put each row in a box, the other
(which works in this case) is to remove the fill values from the rows
before using them. I went with the latter approach and my solution
became +/@:(>./"1 - (<./@-.&0)"1)

For the second part, the sample data they gave was not ragged, and I
didn't read ahead to notice that I'd be using the same dataset there
(I skipped out on day 1). So my initial solution looked like this:

require'stats'
allpairs=: {~ 2 comb #
cks=: [: +/((>./ % <./)@,@(#~ +./@(e. *./)"1)@allpairs)"1

Then changed it to allpairs=: ({~ 2 comb #)@-.&0"1 though on
reflection that's not necessary.

Not quite as compact as your approach, nor as efficient for the data
we are working with here, but it works.

Thanks,

-- 
Raul


On Sat, Dec 2, 2017 at 1:31 AM, Daniel Lyons <[email protected]> wrote:
> Thanks to everyone for sharing solutions yesterday and especially to those 
> with advice for me, I really appreciate it!
>
> Today's problem has to do with computing checksums. Like yesterday, the first 
> part and the second part bear some kind of family resemblance that you can 
> probably leverage; my first solution doesn't really help with my second, but 
> oh well.
>
> Part one is basically to examine a matrix comparing items row-by-row, finding 
> the differences between the largest and smallest elements of each, and then 
> summing those differences. My solution:
>
>    a =. ".&.>cutLF fread '~/Desktop/input'
>    checksum =. monad def '+/> (>./ - <./) &.> y'
>
> There's a fair amount of boxing and unboxing going on here. The actual input 
> file is a rectangular matrix, but the example input in the problem is not, so 
> I assumed the input wasn't either. This could certainly be simplified. The 
> tacit version is also not too bad:
>
>    [: +/ [: > (>./ - <./)&.>
>
> As a beginner I am kind of suspicious of tacits with a lot of cap. It looks 
> to me like humans usually generate tacits with @: or @ instead, and while it 
> seems to me that "[: f g" ought to transform into "f @: g" 100% of the time, 
> it doesn't seem to be quite right when I try it.
>
> For part two, the conditions change to finding two values such that one 
> divides the other and then taking the result of that division for each row, 
> summing up the result of the divisions.
>
> My first thought was to form the cross product of the divisors, but you get 
> spurious results along the diagonal arising from checking values against 
> themselves. So then I was building the identity matrix to mask that out and 
> then using the (shape shape) #: , I. trick to convert the result back into 
> coordinates, so I could use { to obtain the values, so I could then … and it 
> just felt a bit like a Rube Goldberg device, so I did some chores.
>
> When I came back I had realized that I could avoid a great deal of that work 
> by just multiplying the division result by my conditions (x and y not being 
> equal, x and y being divisors) and then discard the zeros, so I came up with 
> this:
>
>    checksum2 =. monad def '+/ 0 -.~ ,y ((0=|) *. ~: *. (% >. %~))"(0 1) y'
>
> The tacit (% >. %~) is standing in for "do the division whichever way works". 
> So you can see the conditions inside that largeish tacit. I could probably 
> put a reflex operator on there and not pass y in again on the x side, I'm 
> realizing right now. 0 -.~ is discarding the zeros and then I sum up the 
> difference.
>
> Unlike the first, this one is expecting a rectangular matrix rather than a 
> list of boxes, and I obviously profited from that decision and should go back 
> and revisit my first solution.
>
> It still feels a bit like more code than there is work to do, but I'm pleased 
> that I got to the solution.
>
> Tacit version of checksum2 is
>
>    13 : '+/ 0 -.~ ,y ((0=|) *. ~: *. (% >. %~))"(0 1) y'
> [: +/ 0 -.~ [: , ((0 = |) *. ~: *. % >. %~)"0 1~
>
> Ah, see it threw a reflex on the end.
>
> Very fun! Thanks for reading,
>
> --
> Daniel Lyons
>
>
>
>
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to