A slightly cleaner version of my day2b

day2b =: (+/) @: (+/) @: ((% * ~: *. 0&=@|~)"0/~)

+/ day2b"1 (". every LF cut input)



thanks Raul & Henry for helping with the rank question on the other thread

On Sat, Dec 2, 2017 at 9:21 AM, Joe Bogner <[email protected]> wrote:

> I only have a few minutes this morning but here is my unrefined solutions
> to partA and partB
>
> day2a =:  +/ @: ([: (>./ - <./) @:". every LF cut ])
>
> input =: 0 : 0
> 5 1 9 5
> 7 5 3
> 2 4 6 8
> )
>
> day2a input
>
>
>
> day2b =: ([: +/ (+/ @: (%/~ * (~:/~ *. ( (0&=@|~))/~) )))
>
> +/ day2b"1 (". every LF cut input)
>
>
>
> On Sat, Dec 2, 2017 at 6:12 AM, Raul Miller <[email protected]> wrote:
>
>> 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
>>
>
>
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to