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

Reply via email to