I had a little problem with your code here. You had a lot of long
lines, which got wrapped in email (mostly comment lines). I think I
have those all sorted out now, But, I also got this:
|value error: in
| i12=:(sl{."1)([:sl[:<;._2,&'-');._2 in 12
If I change that line to
i12=:(sl{."1)([:sl[:<;._2,&'-');._2
this seems to work:
(a12,b12) t1
10 36
(a12,b12) t2
19 103
Does that match your expectations?
Thanks,
--
Raul
On Sun, Jan 2, 2022 at 10:21 AM Jan-Pieter Jacobs
<[email protected]> wrote:
>
> I think mine is pretty much the same idea as Raul's for part 1, tough I
> used symbols rather than integers for encoding the caves (nodes).
>
> NB. Day 12: Cave mapping paths
> sl=: (\: #&>) NB. sort boxes by descending length
> NB. remove - and sort boxes by length s.t. start, end are first: unordered
> edges, so sorting does not matter.
> i12=: (sl {."1)([: sl [: <;._2 ,&'-') ;._2 in 12
> NB. find all paths from start to end through caves, visiting each lowercase
> cave max once
> islc=: (97 ([+i.@>:@-~) 122) *./@e.~ a.&i. NB. is all lower case?
>
> a12=:{{
> links=. s: (, |."1) y NB. bidirectional links, so that can look up based
> on {."1
> lcn =. s: (#~ islc&>) ~. ({."1,{:"1)y NB. lowercase nodes
> paths=. ,: s: ' start' NB. list of distinct paths (no box because equal
> length)
> complete=. 0$a: NB. boxed because ~: lengths
> while. *#paths do.
> NB. add possible nodes to paths (excluding visited lowercase and the
> last)
> NB. raze bx path apd lcn in path rem from excllast dest where
> source is last
> paths =. ;@:(<@(,"1 0 (#~ e.&lcn) -.~ links (]-.~ {:"1@[ #~ {."1@[
> = ]) {:)"1) paths
> NB. remove complete paths & add to complete
> iscomp=. (s:<'end')={:"1 paths
> complete=. complete, <iscomp#paths
> paths=. paths #~ -.iscomp
> end. NB. end if no incomplete paths left
> +/#&>complete
> }}
>
> For part B, I first made a misinterpretation of the problem: I thought
> *any* lowercase node could be visited twice, which lead to a ridiculous
> number of solutions, prompting aggressive optimisations (in b12 below),
> while the same approach of a12 would have worked as well (see b12a), though
> quite a bit slower.
>
> NB. part B: the same, but one lcn can be visited twice; start, end only
> once.
> b12a=: {{
> NB. bidirectional links, so that can look up based on {."1
> links=. s: (, |."1) y
> NB. remove start as destination
> links=. (#~ (s:<'start')~:{:"1) links
> lcn =. s: (#~ islc&>) ~. ({."1,{:"1)y NB. lowercase nodes
> NB. list of distinct paths (no box because equal length); don't store
> start
> paths=. ,:s:<'start'
> ncomplete=. 0
> NB. complete=: 0$a:
> NB. *wrong*: only a single lcn can be picked twice
> NB. eligible =: (lcn ([#~2<:+/@:="0 1) [) -.~ ]
> NB. correct:
> eligible =: (lcn ([ (#~ ]>:1+2>>./@]) (+/@:="0 1)) [) -.~ ]
> NB. newlinks: make list of connected nodes, removing last (inf loop)
> newlinks=: links (]-.~ {:"1@[ #~ {."1@[ = ]) {:
> while. *#paths do.
> NB. add possible nodes to paths (excluding visited lowercase and the
> last)
> NB. raze bx apd start rm lcn in path rem from excllast dest
> where source is last
> paths =. ;@:(<@(,"1 0 ] eligible newlinks)"1) paths
> NB. remove complete paths & add to complete
> iscomp=. (s:<'end')={:"1 paths
> ncomplete=. ncomplete++/iscomp
> NB. complete=: complete,<iscomp#paths
> paths=. paths #~ -.iscomp
> end. NB. end if no incomplete paths left
> ncomplete
> }}
> NB. outcome: a: 10; b: 36
> t1=: (sl {."1)([: sl [: <;._2 ,&'-') ;._2{{)n
> start-A
> start-b
> A-c
> A-b
> b-d
> A-end
> b-end
> }}
> NB. outcomes: a: 19; b: 103
> t2=: (sl {."1)([: sl [: <;._2 ,&'-') ;._2{{)n
> dc-end
> HN-start
> start-kj
> dc-start
> dc-HN
> LN-dc
> HN-end
> kj-sa
> kj-HN
> kj-dc
> }}
>
>
> b12 is my heavily optimised version, based on the consideration that only
> the last node and set of visited lower case nodes (not quite a set, since
> elements can appear multiple times, but order not important) matter in this
> problem, the rest can safely be abstracted away. Doing so would lead to
> many duplicate paths that can also be collapsed to a single one if one
> keeps counts.
> Result: 40x faster, 78x leaner
> This would be able to keep track of all paths also if all lcn's would be
> allowed to be visited twice, and likely more.
>
> b12=: {{
> NB. bidirectional links, so that can look up based on {."1
> links=. s: (, |."1) y
> NB. remove start as destination; start is not revisited
> links=. (#~ (s:<'start')~:{:"1) links
> NB. list of distinct paths
> paths=. <"0 links ({:"1@[ #~ {."1@[ = ]) (s:<'start')
> cts=. #/.~ paths NB. keeps track of duplicity of tracks
> NB. remove start as source (already in paths)
> links=. (#~ (s:<'start')~:{."1) links
> NB. set of lowercase nodes
> lcn =. s: (#~ islc&>) ~. ({."1,{:"1)y
> NB. set of uppercase nodes
> ucn =. s: (#~ -.@:islc&>) ~. ({."1,{:"1)y
> ncomplete=. 0 NB. number of complete paths
>
> NB. helper verbs:
> NB. filter to remove non-eligible lcn's; x: path; y:reachable links
> NB. wrong: only a *single* lcn can be picked twice, while the commented
> one allowed *every* lcn to appear twice.
> NB. eligible =: (lcn ([#~2<:+/@:="0 1) [) -.~ ]
> eligible =. (lcn ([ (#~ ]>:1+2>>./@]) (+/@:="0 1)) [) -.~ ]
> NB. newlinks: make list of connected nodes, removing last (inf loop)
> newlinks=. links (]-.~ {:"1@[ #~ {."1@[ = ]) {:
>
> NB. Breadth-first search:
> while. *#paths do.
> NB. add possible nodes to paths (excluding visited lowercase and the
> last)
> NB. sorted lcn's in path append eligible newlinks
> newpaths =. (/:~@(}:^:(ucn e.~ {:)) <@,"1 0 ] eligible newlinks )&.>
> paths
> NB. ^sort essential to trim possible dupes v
> newcts=. cts #~ #&> newpaths NB. duplicate original counts for each
> new path
> NB. flatten newpaths
> newpaths=. ;newpaths
> NB. sum counts for equivalent paths
> newcts=. newpaths +//. newcts
> NB. unique new paths, reduces maintenance cost
> newpaths=. ~. newpaths
>
> NB. remove complete new paths & add to ncomplete
> NB. complete paths end in 'end'
> iscomp=. (s:<'end')={:&> newpaths
> NB. add complete counts
> ncomplete=. ncomplete++/iscomp#newcts
> NB. remove complete paths
> paths=. newpaths #~ -.iscomp
> NB. remove complete counts
> cts=. newcts #~ -.iscomp
> end. NB. end if no incomplete paths left
> ncomplete
> }}
> (a12;b12)i12
>
>
> Jan-Pieter
>
> On Sun, Jan 2, 2022, 05:52 Raul Miller <[email protected]> wrote:
>
> > https://adventofcode.com/2021/day/12
> >
> > For day 12, we had a "cave map" which was a list of connections
> > between named pairs of rooms.
> >
> > unpack=:-.&;:&'-';._2
> >
> > sample=: unpack {{)n
> > start-A
> > start-b
> > A-c
> > A-b
> > b-d
> > A-end
> > b-end
> > }}
> >
> > Here, our puzzle task, for part A, was to explore the cave system. We
> > needed to visit each room at least once. Rooms with lower case names
> > needed to be visited exactly once. Rooms with ALL CAPS names could be
> > visited as many times as we wanted. Specifically, we needed to count
> > how many distinct paths lead from 'start' to 'end'.
> >
> > I could have solved this more elegantly, but here was my approach for
> > that part of the puzzle:
> >
> > a12=:{{
> > c=. (#~ (<'end')~:{."1) (#~ (<'start')~:{:"1) y,|."1 y
> > ref=. ~.a:,,c
> > 'from to'=. |:ref i.c
> > 'start end'=. ref i.;:'start end'
> > r=. i.0 0
> > paths=. (start = from)#from,.to
> > reps=. (i. (#~ ] = toupper each)) ref
> > while.#paths do.
> > done=. end = {:"1 paths
> > r=. r, done#paths
> > paths=. (-.done)#paths
> > nexts=. (-.to e."1 paths -."1 reps)*({:"1 paths)=/from
> > paths=. ((+/"1 nexts)#paths),.(,nexts)#(#,nexts)$to
> > end.
> > ;:inv r { ref
> > }}
> >
> > Basically, the connection pairs were two way (except for start and
> > end), so the first thing I did was convert the bidirectional
> > connection pairs to unidirectional connection pairs (c).
> >
> > Then, I assigned integer cave ids and set up my initial state (a list
> > of incomplete paths from the start location -- technically, I could
> > have left the start node out of my 'ref' of connection pairs, since I
> > would never use those connections again).
> >
> > Once I had that, I started tracing through to all the possible next
> > available connections for each of my paths (breadth first search), and
> > moving each complete path to my result variable.
> >
> > At the end, so I could comprehend the result, I converted the paths
> > back to a textual form. The actual result I needed was #a12
> >
> > #a12 sample
> > 10
> >
> > For part B, the rules changed. Except for start and end, we could also
> > visit one (and only one) of the rooms with lower case names twice.
> >
> > Again, there's certainly tidier ways of solving this, but here's how I
> > approached that:
> >
> > b12=: {{
> > c=. (#~ (<'end')~:{."1) (#~ (<'start')~:{:"1) y,|."1 y
> > ref=. ~.a:,,c
> > 'from to'=. |:ref i.c
> > 'start end'=. ref i.;:'start end'
> > r=. i.0 0
> > paths=. (start = from)#from,.to
> > reps=. (i. (#~ ] = toupper each)) ref
> > while.#paths do.
> > done=. end = {:"1 paths
> > r=. r, done#paths
> > paths=. (-.done)#paths
> > any=. 1 = >./"1 }."1 #/.~("1) 0,.paths -."1 reps
> > nexts=. (any+.-.to e."1 paths -."1 reps)*({:"1 paths)=/from
> > paths=. ((+/"1 nexts)#paths),.(,nexts)#(#,nexts)$to
> > end.
> > ;:inv r { ref
> > }}
> >
> > The big difference here was that I was tracking whether any
> > destination room was viable or only unvisited and ALL CAPS rooms were
> > viable destinations. Other than that, it's the same as the part A
> > implementation.
> >
> > And, similar to part A, the actual result I needed was #b12
> >
> > #b12 sample
> > 36
> >
> > --
> > Raul
> > ----------------------------------------------------------------------
> > 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