That's the kind of code I'm aspiring to write :D

Still some distance away.

Great job!

Missatge de Raul Miller <rauldmil...@gmail.com> del dia dv., 16 de des.
2022 a les 2:47:

> Here's a somewhat presentable implementation of part 2 for day 15.
> it's a bit different from what I described in my previous email, but
> most of the concepts are the same.
>
> NUM=: '-',~.":i.10
> parse=: 0 ". (#~ e.&NUM);._2
> prep=: {{ 'S Be'=: _2 j./\ |: (\: 1{"1]) parse y }}
> mhd=: +/@:|@+.@-
> edge=: {{ |:(+/,-~/)@+. S(+,.-)j.D=:mhd/prep y }}
> maybe=: {{~.(j.**&(=<.)**&(0&<)**&(x&>))/(-/,:&,+/)/-:1 _1+"2 y}}
> filter=: {{ y #~ */D < S mhd/ y }}
> B=: {{ 4e6#.<.+. filter x maybe edge y }}
>
>    timespacex'4e6 B input'
> 0.0143791 723680
>
> 'NUM' is characters which I care about: digits, space, the minus sign.
> 'parse' converts the text of the puzzle into a 4 column array of integers
> 'prep' further converts that into a row of sensor coordinates and a
> row of beacon coordinates
> 'mhd' is manhattan distance
>
> Note that I'm representing x,y coordinate pairs as x j. y complex
> numbers, in 'prep', and I rely on this representation from there on
> down.
>
> -------------------
>
> 'edge' finds the y intercept of the bounding lines corresponding to
> these sensor/beacon pairs. This array has three dimensions, and one
> integer for each line.
>
> The first dimension is indexed by _1^.slope of the bounding line. (In
> other words 0 for slope of 1, 1 for slope of _1).
>
> The second dimension is indexed by _1^.*y component of becon
> coordinate - sensor coordinate. (In other words, 0 if the beacon y
> coordinate is greater than the S y coordinate, _1 if it's less).
>
> The final dimension corresponds to the sensor/beacon pair.
>
> For example:
>
>    edge 'Sensor at x=2, y=0: closest beacon is at x=2, y=10;'
>
>  12
>  _8
>
>   8
> _12
>
> Here, the top two numbers have a positive slope (y increases with x),
> and the bottom two numbers have a negative slope (y decreases when x
> increases). The first number of each pair are offset from the sensor
> in the same direction as the beacon. The second number of each pair is
> offset in the opposite direction.
>
> -------------------
>
> 'maybe' takes these lines and finds points that might be the result we
> want based on where these lines intersect and which direction the
> beacon is from the sensor. I add an offset to each y intercept based
> on its direction from the corresponding sensor, then get potential x
> coordinates (half of all positive slope values mine half of all
> negative slope values) and the corresponding potential y coordinates
> (average of those two values). (I factored out the divide by 2 to
> happen all at once here).
>
> Then I convert these coordinate pairs to complex, forcing obviously
> invalid values (with non-integer coordinates or where they're outside
> the search area) to zero, discarding duplicates. A lot of zeros get
> discarded here (and the remaining zero will be discarded shortly).
>
> -------------------
>
> 'filter' discards points which are too close to a sensor. It might be
> slightly faster if I filtered the result down, one sensor at a time,
> and I was going to do that (which is why I am assigning the
> sensor-to-beacon distances to D in 'edge'). But this is probably fast
> enough already...
>
> And, finally, B assembles the result.
>
> -------------------
>
> There's a few problem specific quirks here -- for example, I rely on a
> sensor never having a y coordinate which matches the y coordinate of a
> beacon. I didn't encounter that issue, so I ignored it as a
> possibility. So maybe the code itself doesn't entirely make sense. But
> it was fairly straightforward to put together within these
> constraints.
>
> Anyways, ... maybe this will make sense to someone...
>
> Thanks,
>
> --
> Raul
>
>
>
> On Thu, Dec 15, 2022 at 3:51 PM Raul Miller <rauldmil...@gmail.com> wrote:
> >
> > Yes, after I sent that suggestion, I realized that I could do a better
> > job of describing the approach.
> >
> > So, I sat down and implemented the thing that way.
> >
> > My implementation could do with some code cleanup, but as it stands
> > now, it looks like this performance wise:
> >
> >    timespacex '4e6 B input'
> > 0.0232526 1883360
> >
> > This was on a 1.2GHz laptop.
> >
> > A rough outline of the code is this:
> >
> > (1) Parse the raw text into numbers (four numbers per line), and sort
> > them (descending order by sensor y value to simplify finding candidate
> > points).
> >
> > (I then combine them in pairs as complex numbers, and work with
> > coordinates in x j. y format.)
> >
> > (2) Find the boundary edges, represent this as a three-column table
> >    slope (1 or _1), y direction from sensor (1 or _1), y intercept
> >
> > (3) Find a list of candidate points to consider:
> >    (a) add the y direction to the y intercept to get a y offset
> > immediately outside the sensor's range
> >    (b) find an intersection point for every pair of edges (difference
> > of y offsets for x average of y offsets for y)
> >
> > There will be duplication here, so toss the duplicates.
> >
> > (4) Filter these candidate
> >   (a) discard any candidates with an x or y which is negative
> >   (b) discard any candidates with an x or y which is too large
> >   (c) project each candidate to the y axis using a positive or negative
> slope
> >   (d) discard any candidate whose positive slope intercept is larger
> > than the smallest positive slope y intercept for any edge
> >   (e) discard any candidate whose negative slope intercept is smaller
> > than the largest negative slope y intercept for any edge
> >
> > And then: find the Manhattan distance from each remaining candidate to
> > each sensor and discard those which are too close to any sensor
> >
> > Then convert the coordinate to the required index value.
> >
> > So, B looked like:
> >
> > B=: {{4e6 #.<.+. (x filter candidates) edges y}}
> >
> > ('filter' was an adverb with x, m and y as parameters.)
> >
> > FYI,
> >
> > --
> > Raul
> >
> > On Thu, Dec 15, 2022 at 1:28 PM Jaume <greenni...@gmail.com> wrote:
> > >
> > > I went one way ahead. Increased the range in 1, so the point would be
> on an
> > > intersection, fewer points to check.
> > >
> > > Ways one could check:
> > > Go point by point, check if it's the good one.
> > > Do something like in part 1, checking for an empty space checking line
> by
> > > line.
> > > Check the positions just beyond the range of all the sensors.
> > > Check around the intersections of the scanning range of all the
> sensors.
> > > (your suggestion)
> > > Check the intersections of an extra range in all the sensors.
> > > Find sensors with ranges r1 and r2 that are at a distance 1+r1+r2. The
> > > point should be in the middle.
> > >
> > > I implemented them all except the first, last (read about it
> afterwards)
> > > and yours. I think they are (roughly) in the correct cpu burning level
> > > (first the ones that require more computation).
> > > I had the right point from my 2nd test, but I had a bad calculation.
> > >
> > > Missatge de Raul Miller <rauldmil...@gmail.com> del dia dj., 15 de
> des.
> > > 2022 a les 19:04:
> > >
> > > > I think your approach here, with a slight change, would be superior
> to
> > > > the approach I used.
> > > >
> > > > In other words, treat the problem as defining a small set of lines
> > > > bounding the scannable regions. These will all be diagonal lines,
> > > > though they'll have two different orientations.
> > > >
> > > > The point you're looking for has to be adjacent to an intersection of
> > > > two of those lines.
> > > >
> > > > --
> > > > Raul
> > > >
> > > > On Thu, Dec 15, 2022 at 9:22 AM Jaume <greenni...@gmail.com> wrote:
> > > > >
> > > > > Hello all
> > > > >
> > > > > Once again with questions, now more on the performance side, mostly
> > > > because
> > > > > it's taking too long, and giving me a wrong answer some of the
> time.
> > > > >
> > > > > Talking about part 2. I'll share all of the code, so if you see
> anything
> > > > > glaringly wrong please let me know.
> > > > > read=:{{cutopen 1!:1 <y}}
> > > > > filter=: 0". 'Sensoratx=,y:clbi'-.~]
> > > > > init=: 3 : 0
> > > > > map=:>filter each read y
> > > > > sensors=:0 1 {"1 map
> > > > > beacons=: 2 3{"1 map
> > > > > $map
> > > > > )
> > > > > With init 'filename' we set up the rest.
> > > > > In case you don't know we have to find the point thats outside the
> range
> > > > of
> > > > > all the sensors and still inside 0...4000000 in both coordinates.
> > > > > Let's go to the last approach I took.
> > > > > sol2=: 4 : 0
> > > > > NB. range occ sensor,beacon
> > > > > cx=:x
> > > > > cy=:y
> > > > > sensors= 0 1 {"1 y
> > > > > beacons= 2 3 {"1 y
> > > > > distances=:1+sensors d"1 beacons
> > > > > param=:sensors,.((#distances), 1)$distances
> > > > > digs=:x diag"1 param
> > > > > dg=:digs
> > > > > for_i. i.#digs do.
> > > > > here=:testdiag dg
> > > > > if. here do.
> > > > > ccx=:{.here
> > > > > ccy=:{:here
> > > > > ccx,ccy,ccy+ccx*400000 return.
> > > > > end.
> > > > > dg=:}.dg
> > > > > end.
> > > > > 'none'
> > > > > )
> > > > > d=:[:+/[:|-
> > > > > union=: ~.@,
> > > > > unboxedunion=:([: > [) union [: > ]
> > > > > intersect=: e. # [
> > > > > remx=:([ >: [: {."1 ]) *. [ >: [: {:"1 ]
> > > > > rem0=:(0 <: {."1) (*.) 0 <: {:"1
> > > > > remove=: 4 : 0
> > > > > mask=:rem0 y
> > > > > mask=:mask*.x remx y
> > > > > (>mask)#y
> > > > > )
> > > > > diag=: 4 : 0
> > > > > cx=:x
> > > > > cy=:y
> > > > > range=:i.>:{:y NB. [2]->3->0 1 2
> > > > > egnar=:i.->:{:y NB. [2]->-3->2 1 0
> > > > > px=:0{y
> > > > > py=:1{y
> > > > > NB. (x-d,y)->(x,y+d)
> > > > > NB. (x,y+d)->(x+d,y)
> > > > > NB. (x+d,y)->(x,y-d)
> > > > > NB. (x,y-d)->(x-d,y)
> > > > > d1=:(px-egnar),.(py+range)
> > > > > d2=:(px+range),.(py+egnar)
> > > > > d3=:(px+egnar),.(py-range)
> > > > > d4=:(px-range),.(py-egnar)
> > > > > <~.x remove d1,d2,d3,d4
> > > > > )
> > > > > testpoint=: 3 : 0
> > > > > dc=:1 y&d"1\sensors
> > > > > *./dc>:distances
> > > > > )
> > > > > testdiag=: 3 : 0
> > > > > excl=: }.y
> > > > > rest=:]F.:unboxedunion excl
> > > > > interest=:rest intersect > {.y
> > > > > for_i. i.#interest do.
> > > > > val=:testpoint i{interest
> > > > > if.val do.
> > > > > i{interest return.
> > > > > end.
> > > > > end.
> > > > > 0
> > > > > )
> > > > >
> > > > > So I create the limits that are just outside the range of each
> sensor,
> > > > > intersect those, examine if the points have all the distances
> greater
> > > > than
> > > > > the distance each sensor reaches, and if so that's the point.
> > > > > On the test it's blazingly fast:
> > > > >
> > > > > 20 sol2 map
> > > > >
> > > > > 14 11 5600011
> > > > >
> > > > > But on the real data it's amazingly slow... and according to AoC
> also
> > > > wrong.
> > > > >
> > > > > 4000000 sol2 map
> > > > >
> > > > > 3270298 2638237 1308121838237 NB. too low!!!!
> > > > > But.. AFAIK this answers checks the marks:
> > > > >
> > > > > |: dc
> > > > >
> > > > > 4298885 1215898 1684048 845656 3691920 1327934 1042406 682945
> 599242
> > > > > 3471784 3639831 841599 1106070 4582032 3552311 2682122 967943
> 845585
> > > > > 1809437 1835842 1806964 962164 663951 532696 2570491 706217 654163
> > > > 1476664
> > > > > 2198682 1669886 4144166 985137 1181113 4234...
> > > > >
> > > > > distances N.B. 1+ real distance
> > > > >
> > > > > 1595477 33564 434944 166994 803986 656108 285496 682945 599242
> 1465583
> > > > > 700194 171415 143036 1694098 1742449 1433018 121373 226445 1150021
> 945766
> > > > > 479064 383562 663951 429356 453359 185151 654163 455680 1350302
> 860094
> > > > > 178581 92581 67993 126159 1178851 325282...
> > > > >
> > > > > |: dc>:distances
> > > > >
> > > > > 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
> 1 1 1
> > > > 1 1
> > > > > 1 1
> > > > >
> > > > >
> > > > > So now I'm lost. I can't see the error and it's too slow to try new
> > > > > alternatives.
> > > > >
> > > > >
> > > > > I'm attaching my input, but do not give me the numeric answer
> please,
> > > > that
> > > > > would be trivial using any already working solution.
> > > > >
> > > > > Can you spot the error and or help me make this go faster?
> > > > >
> > > > > Thanks.
> > > > >
> ----------------------------------------------------------------------
> > > > > For information about J forums see
> http://www.jsoftware.com/forums.htm
> > > >
> ----------------------------------------------------------------------
> > > > For information about J forums see
> http://www.jsoftware.com/forums.htm
> > > >
> > >
> > >
> > > --
> > > The fact that an opinion has been widely held is no evidence whatever
> that
> > > it is not utterly absurd. -- Bertrand Russell
> > > ----------------------------------------------------------------------
> > > For information about J forums see http://www.jsoftware.com/forums.htm
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
>


-- 
The fact that an opinion has been widely held is no evidence whatever that
it is not utterly absurd. -- Bertrand Russell
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to