That problem took a lot of reading!
Like you, Brian, I started with the boustrophedon cycles:
example NB. my data has 2 rows: depth,: range:
0 1 4 6
3 2 4 4
(Brian forms the data into a simple vector of ranges
3 2 0 0 4 0 4 )
My verb, cycle, is used to assemble a look-up table of scan positions.
(7$(delay |. cycle)) every <: 3 2 4 4 [ delay =. 0 NB. delay needed
for part 2
0 1 2 1 0 1 2
0 1 0 1 0 1 0
0 1 2 3 2 1 0
0 1 2 3 2 1 0
Note that the period for a range of r is 2 * (r - 1), and that the
third and fourth
row (origin 1!) are identical.
My problem data had 40 odd pairs, with depth between 0 and 92, but
only 12 distinct values for range, so I set up 12 cycles of length
93, and
looked up the one I needed for each depth used in a make-once use-often
table.
The function below does part 1 - and tries to do part 2 - with a
negative
left argument repesenting the trial delay - its right argument is the 2
row
representation of the given input. (It grew rather more complicated
than
necessary for part 1 in order to try to solve part 2.)
dostates=: 3 : 0
0 dostates y
:
if. x > 0 do. e =. echo else. e =. ] end. NB. debugging stuff
'd r' =. y
s =. 0#~#r
l =. *./ +: <: r NB. lcm of
cycle lengths
if. x < 0 do.
delay =. - 0 <. x
else.
delay =. 0
end.
c =. ((l <. 2 + >./d) $ (delay |. cycle)) every <: ur =. ~.r NB.
look-up table of range-positions
e (;~$) c
t =. 0
max =. >:>./d
if. x > 0 do. max =. | x <. max end.
for_layer. i.max do.
if. layer e. d do.
id =. d i. layer NB.
rlayer =. id{r NB. which range
rlu =. ur i. rlayer NB. where in nub of ranges
scanid =. (<rlu, layer) { c NB. scan position
if. scanid = 0 do.
e 'caught'; layer, rlayer
t =. t + (delay~:0) + layer * rlayer * delay = 0
end.
end.
if. x * x < >:>./d do. e layer; d,: (ur i.r) { (l|layer) {"1 c end.
end.
t
)
It works ok, as does Brian's corrected function:
ts'day13 datas'
0.0338706 8448
ts'dostates input13'
0.000846644 25728
But then I realised this does the job even better! :-
13 : '+/*/y{"1~ I. 0 =|~/({.,: (2*(<:@{:)))y' input13
1580
That is, the probe is detected by "scanners" for those pairs
where a range's cycle period divides the corresponding depth.
It is faster than both the above loopy functions, uses
more space than Brian's, less than mine.
ts '13 : ''+/*/y{"1~ I. 0 =|~/({.,: (2*(<:@{:)))y'' input13'
5.18354e_5 12288
The following variant shows how I managed to do part 2, albeit
very slowly!
10 (13 : '+/*/y{"1~ I. 0 =|~/(0,~x) + ({.,: (2*(<:@{:)))y') example
0
ie, you add the delay to the cycle period, so that now
(a range's cycle-period plus the delay) divides the corresponding
depth.
We seek the lowest delay such that for none of these modified pairs
is the period-plus-delay a divisor of the depth.
I suspect there's a better way for part 2, but haven't looked!
Cheers,
Mike
On 21/12/2017 12:08, Brian Schott wrote:
> I found my error.
> ud =: i. , }:@}.@i.@- NB. added }:@
>
> Also, the approach is very inefficient, but works, now.
>
> On Wed, Dec 20, 2017 at 6:29 PM, Brian Schott <schott.brian@gmail.
com>
> wrote:
>
>> I am getting the wrong answer for part 1 of day 13.
>> Can someone give me a hint what I am misunderstanding?
>>
>> My main verb is day13, but it depends on the following simple verbs.
>>
>> ud =: i.,}.@i.@-
>> spos =: [{.@:|."0 1 ud@]
>> (i. 6) spos"0/ ]3 2 0 0 4 0 4
>> 0 0 0 0 0 0 0
>> 1 1 0 0 1 0 1
>> 2 0 0 0 2 0 2
>> 1 0 0 0 3 0 3
>> 0 1 0 0 2 0 2
>> 0 0 0 0 1 0 1
>>
>>
>> day13 =: verb define
>> ranges =. y
>> severity =. 0
>> for_secs. i. # ranges do.
>> state =. secs spos"0 ranges
>> if. 0 = secs { state do.
>> if. secs{ ranges do.
>> severity =. severity+secs*secs{ranges
>> end.
>> end.
>> end.
>> severity
>> )
>> day13 3 2 0 0 4 0 4
>> 24
>> day13 $.^:_1 datas
>> 2052
>>
>>
>>
>> For more completeness, my data collection used the following ideas.
>>
>> datam =: data rplc ':';' '
>> datas =: ({:|: ". ;._2 datam)({.|: ". ;._2 datam)} 1 $. 99
>>
>> TIA,
>>
>> --
>> (B=)
>>
>
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm