Sorry - always forget something - bkts ???

    bkts =: 4 2 $'()[]{}<>'

I hope the rest is self-contained,  but apologies for the ungraceful
character non-alignment.  I'd avoided graphic boxing characters and
had sent in fixed-width font where it mattered!

Mike



On 31/12/2021 15:58, 'Michael Day' via Programming wrote:
I _think_ I used a somewhat different approach.  I'll only deal with part 1 as
part 2 doesn't add much complexity.

This approach is simple -  remove adjacent pairs of opening and closing
brackets of the same kind until there are none.  The function is called
reduce:

I've added echo lines only for this email.

reduce =: 3 : 0
a    =. 1 _1 ,2 _2,3 _3,:4 _4
nums =. +/+/"2 a *"2 3 bkts =/ y -.' '
NB. this would have been much better! :
NB. nums =. (,a){~ (,bkts) i.' '-.~{.ex
while. +/ msk =. +/(E.& nums)"1 a do.
  msk =. -. msk + 0, }: msk NB. matching adjacent pair gives 0 0
  nums=. msk#nums
end.
if. 0 > <./ nums do.  NB. "corrupted"
   r =. +/ 3 57 1197 25137 {~ <: |{.(#~ <&0  ) nums
echo 'corrupted'; r
else.                 NB. "incomplete"
echo 'ignore';   ,|.(}."1 bkts){~<: nums
   r =. 0
end.
r
)

We know if a line is corrupted if we can't reduce it any more AND it still contains
some close brackets.

I called the example data "ex" - I held it as a 2-d character array.

Here it goes,  with the echo's firing:

   +/reduce"1 ex
+------+--------+
|ignore|}}]])})]|
+------+--------+
+------+------+
|ignore|)}>]})|
+------+------+
+---------+----+
|corrupted|1197|
+---------+----+
+------+---------+
|ignore|}}>}>))))|
+------+---------+
+---------+-+
|corrupted|3|
+---------+-+
+---------+--+
|corrupted|57|
+---------+--+
+------+---------+
|ignore|]]}}]}]}>|
+------+---------+
+---------+-+
|corrupted|3|
+---------+-+
+---------+-----+
|corrupted|25137|
+---------+-----+
+------+----+
|ignore|])}>|
+------+----+
26397

Cheers,

Mike



On 31/12/2021 02:41, Raul Miller wrote:
https://adventofcode.com/2021/day/10

For day 10's puzzle, the first part was determining whether
collections of braces and brackets were properly formed.  The
allowable pairs were '()', '[]', '{}', and '<>', and the sample data
looked like this:

sample=:{{)n
[({(<(())[]>[[{[]{<()<>>
[(()[<>])]({[<{<<[]>>(
{([(<{}[<>[]}>{[]{[(<()>
(((({<>}<{<{<>}{[]{[]{}
[[<[([]))<([[{}[[()]]]
[{[{({}]{}}([{[{{{}}([]
{<[[]]>}<{[{[{[]{()[[[]
[<(<(<(<{}))><([]([]()
<{([([[(<>()){}]>(<<{{
<{([{{}}[<[[[<>{}]]]>[]]
}}

Specifically, for the first part, we were to find the first illegal
character on each line, each of which were assigned a score, and sum
those scores.

   So the result line for that part would look something like this:

    +/ 3 57 1197 25137 {~ ')]}>' i. bad

So I built a brute force lexical analyzer which returned empty for
legal lines and the first bad character and its index for illegal
lines:

scanline=:{{
   next=.''
   for_ch. y do.
      select. ch
        case.'(' do. next=. next,')'
        case.'[' do. next=. next,']'
        case.'{' do. next=. next,'}'
        case.'<' do. next=. next,'>'
        case.')';']';'}';'>' do.
          if. ch={: next do.
            next=.}: next
          else.
            ch;ch_index return.
          end.
        case. do. echo 'unexpected';ch;ch_index throw.
      end.
   end.
   ''
}}

The basic approach here is to have an intermediate result which is a
stack of the expected terminating characters and to report on failed
matches.

I left the character index in the result to help me debug my code if I
had done something horribly wrong.

Since I was returning boxed characters from that routine for the error
cases, I decided my lookup should normalize both the left and right
arguments to i. to be boxed strings:

aoc10a=:{{
   err=. {."1>(<@scanline;._2 y)-.a:
   +/((;:')]}>')i.&:(,each) err){3 57 1197 25137
}}

For part b, we instead were to report on the lines without illegal
characters and score based on the missing terminating
brackets/braces/...

Here, the scoring was 1 + the index into ')]}>', multiplied by 5 ^
index into that particular string.

So I took the above code and tweaked it to return the unfinished
stacks on "good lines":

scan2=:{{
   next=.''
   for_ch. y do.
      select. ch
        case.'(' do. next=. next,')'
        case.'[' do. next=. next,']'
        case.'{' do. next=. next,'}'
        case.'<' do. next=. next,'>'
        case.')';']';'}';'>' do.
          if. ch={: next do.
            next=.}: next
          else.
            '' return.
          end.
        case. do. echo 'unexpected';ch;ch_index throw.
      end.
   end.
   |.next
}}

My initial implementation of the scoring mechanism was a bit messy,
but there's no point burdening you with that. Instead:

score=:5 #. 1 + ')]}>' i. ]

Though I could have used

score=:5 p.~ 1 + ')]}>' i. |.

To actually complete the second part, we needed to find the median score:

aoc10b=:{{
   compl=. (<@scan2;._2 y)-.a:
   ({~ <.@-:@#)/:~ score every compl
}}

And that was it for day 10.





--
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to