APL/D Source Code: ──────────────────────────────────────────────────────────────────────────────── trip←{⎕IO ⎕ML←1 0 ⍝ Trip from/to ⍵ in network space ⍺. 0=⍺.⎕NC'graph':⍺{ ⍝ source not compiled for this space. ⎕←'compiling graph ...' ⍝ explain slight delay. (compile ⍺)trip ⍵ ⍝ try again with compiled graph. }⍵ access←⍺.((1=≡¨labels)/labels) ⍝ access via station entrances. legs←{ ⍝ start and end station indices. hits←∨/⍵⍷↑access ⍝ stations containing supplied string. best←1+⊃⍋↑⍴¨hits/access ⍝ best (tightest) fit. best⊃0,hits/⍳⍴hits ⍝ index of chosen station. }¨⍵ ⍝ for each leg of the journey. 0∊legs:'Can''t find: ',↑{ ⍝ misspelled station name: ⍺,' or ',⍵ ⍝ (one or more stations) }/(0=legs)/⍵ ⍝ give up :-( find←⍺.graph{⍺⍺ path ⍺ ⍵} ⍝ find one leg of the route. route←↑{⍺,1↓⍵}/2 find/legs ⍝ suggested route via all points. labels←⍺.labels[route] ⍝ labels for all legs of route. masks←1 2=⊂≡¨labels ⍝ masks of stations and stops. stats stops←masks/¨⊂labels ⍝ station and stop labels. zip←{↓⍉↑⍵} ⍝ transpose vector-of-vectors. cat←{↑,/⍵} ⍝ concatenate .. .. pad←{↓↑⍵} ⍝ pad vectors with blanks. slabs←cat¨zip pad¨zip stops ⍝ aligned stop labels. ↑(stats,slabs)[⍋⍋2⊃masks] ⍝ merged stations and stops. } ──────────────────────────────────────────────────────────────────────────────── compile←{⎕IO ⎕ML←1 0 ⍝ Compile graph from ⍵.source. zip←{↓⍉↑⍵} ⋄ cat←{↑,/⍵} ⍝ transpose/concatenate vec-of-vecs. lines stats ctrls←zip zip¨{ ⍝ first pass: source → line sections. vecs←{↓⎕FMT↑⍵} ⍝ normalise source to vector-of-vectors. rcom←{(∧\~'//'⍷⍵)/⍵} ⍝ remove comments '// ···' from line. rbls←{(∨/¨' '≠⍵)/⍵} ⍝ remove blanks lines: '' '' ··· segt←{(' '≠⊃¨⍵)⊂⍵} ⍝ segment at non-blank first column. trim←{(∨\⍵≠' ')/⍵}{⌽⍺⍺⌽⍺⍺ ⍵} ⍝ remove blanks, fore and aft. tupl←'+↓∊'{⍺(trim ⍵~⍺⍺)(⍺⍺∩⍵)} ⍝ tupl: (line stat ctrl). tups←{(⊂trim⊃⍵)tupl¨1↓⍵} ⍝ tuples: tupl tupl ···. tups¨segt rbls rcom¨vecs ⍵ ⍝ line segments. }⍵.source seqs←{(⍳¨⍵)+0,+\¯1↓⍵} ⍝ sequence of sequences. csids←{⍵\¨seqs+/¨⍵}'+'∊¨¨ctrls ⍝ stations marked as cross-tracks. stops←zip¨zip lines stats csids ⍝ subway stops. plats←{↓⍵∘.,'^∨'}¨stops ⍝ platform for each direction. slist←{⍵[⍋↑⍵]}∪cat stats ⍝ sorted station list. verts←slist,∪cat cat plats ⍝ graph vertices. platx←{↓verts⍳↑⍵}¨plats ⍝ platform indices within graph. statx←{2/¨verts⍳⍵}¨stats ⍝ station indices within graph. linex←{(∪⍵)⍳⍵}⊃¨lines ⍝ line indices per segment. rests←'↓∊'∘∊¨¨ctrls ⍝ restrictions: 1-way sects and forks. plinks←cat¨2{ ⍝ platform-to-platform links / section. links((ow fk)_)←zip ⍺ ⍵ ⍝ directions and restrictions. rev←{⌽⍵}\ ⍝ reverse second pair. oway←{⍺:1↑⍵ ⋄ rev ⍵} ⍝ one-way section. fork←{⍺:⌽zip rev ⍵ ⋄ zip ⍵} ⍝ fork. ow oway fk fork links ⍝ ⍺←→⍵ links. }/¨zip¨zip platx rests ⍝ pairwise for each line section. clinks←((∪linex)=⊂linex)/¨⊂plinks ⍝ link sections collected by line. llinks←cat↑{ ⍝ connected sections for all lines. next←⍺~⍵ ⍝ next section, duplicates removed. clash←↑∪zip∩⌿↑zip¨next ⍵ ⍝ incompatible directions. diffs←⍉¯1 1∘.×-/clash ⍝ vertex index differences. avecs←↑+/,diffs×clash=⊂next ⍝ adjustment vectors. (next+avecs),⍵ ⍝ connected line subsections. }/¨clinks ⍝ for each section of each line. slinks←cat zip¨zip cat¨statx platx ⍝ (stat plat) ··· links. elinks←0 1∘.⌽slinks ⍝ station-platform each-way links. nlinks←{⍵[⍋↑⍵]}∪(,elinks),llinks ⍝ combined network-wide links. ⍵.graph←↑{(⍺≠¯1⌽⍺)⊂⍵}/zip nlinks ⍝ network graph. stags←2/⌽¨2↑¨∪cat stops ⍝ (stop line) label pairs. slabs←cat¨zip¨zip(⊂4 1↑¨⊂'')stags ⍝ indented stop labels. ⍵.labels←slist,slabs ⍝ station/stop labels. 1:shy←⍵ ⍝ shy result: namespace ref. } ──────────────────────────────────────────────────────────────────────────────── path←{ ⍝ Shortest path from/to ⍵ in graph ⍺. graph←⍺ ⍝ ⍺ is graph vector. fm to←⍵ ⍝ starting and target vertex(ices). tree←¯2+(⍳⍴⍺)∊fm ⍝ initial spanning tree. free←{(¯2=tree[⍵])/⍵} ⍝ free vertices in ⍵. ⍬{ ⍝ path accumulator. ⍵<0:(⍵=¯2)↓⍺ ⍝ root or unvisited vertex: finished. (⍵,⍺)∇ ⍵⊃tree ⍝ otherwise: prefix previous (parent) vertex. }{ ⍝ find partial spanning tree: ⍵≡⍬:¯1 ⍝ no vertices left: stitched. 1∊to∊⍵:1↑⍵∩to ⍝ found target: finished. next←free¨graph[⍵] ⍝ next vertices to visit. back←↑,/⍵+0×next ⍝ back links. wave←↑,/next ⍝ vertex wave front. tree[wave]←back ⍝ set back links in tree. ∇∪wave ⍝ advance wave front. }fm ⍝ from starting vertex. } ──────────────────────────────────────────────────────────────────────────────── ed←{ ⍝ Edit source for subway ⍵. _←'→'⍵.⎕ED'source' ⍝ edit source. _←⍵.⎕EX'graph' ⍝ force recompilation by removing: graph, _←⍵.⎕EX'labels' ⍝ and vertex labels. } ──────────────────────────────────────────────────────────────────────────────── test←{ ⍝ Run test script: no news => good news. ⍺←0 ⍝ default: don't show progress. ⍵≡'':⍺ ∇ ⎕NL 2 ⍝ null: test all scripts. 2=⍴⍴⍵:⍺ ∇↓⍵ ⍝ matrix: each row is a script. 2=≡⍵:⍺ ∇¨⍵ ⍝ nested: test each script. tag scr←{ ⍝ name and content of script. ⎕PATH←'' ⍝ isolate test. 6::{'' ''}⎕←'No test.',⍵ ⍝ value error:: display message. ⍵(⍎⍵) ⍝ name and content. }⍵ exec←{⎕ML←0 ⍝ execute script lines in tmp space. 0=⍴⍵:⍺ ⍝ no more, finished. ⎕←show⊃⍵ ⍝ show expression. exp←unc⊃⍵ ⍝ uncommented first line. ''≡exp~' ':⍺ ∇ 1↓⍵ ⍝ ignore blank line. 1∊'←{'⍷unq exp:⍺ ∇ dfn ⍵ ⍝ make local dfn. '←'∊unq exp:⍺ ∇ asgn ⍵ ⍝ make local var. act←tmp{6::0 0⍴'' ⋄ ⍺⍎⍵}exp ⍝ actual result. ⎕←show act ⍝ show result. ok rem←act check 1↓⍵ ⍝ check against expected result. (⍺∧ok)∇ rem ⍝ check remaining script. } check←{⎕ML←0 act←↓tmp.⎕FMT ⍺ ⍝ actual result, exp←(⍴act)↑⍵ ⍝ expected result, act≡exp:1,⊂(⍴act)↓⍵ ⍝ match: continue. dexp dact←dots¨exp act ⍝ dots for spaces in, ⎕←tag,⊂dexp'→'dact ⍝ display of differences. 0,⊂(⍴act)↓⍵ ⍝ and continue. } dfn←{ ⍝ fix temp dfn. raw←unq∘unc¨⍵ ⍝ raw code depth←+\{⊃⌽-⌿+\'{}'∘.=⍵}¨raw ⍝ {}-nesting depth per line. lines←1++/∧\×depth ⍝ no of lines in defn. _←tmp.⎕FX↑lines↑⍵ ⍝ fix dfn in temp space. ⎕←show↑1↓lines↑⍵ ⍝ show dfn body. lines↓⍵ ⍝ continue with remaining lines. } nest←{⎕ML←0 ⍝ split line vector, nl←⊃2↓⎕TC ⍝ at nl char into, 1↓¨(1,⍵=nl)⊂nl,⍵ ⍝ vector of char vecs. } dots←{⎕IO←0 ⍝ replace ' ' with '·' in diff display. sx←⎕AV⍳' ' ⍝ index of space. to←(sx↑⎕AV),'·',1↓sx↓⎕AV ⍝ [·/ ]⎕av ↑{(⎕AV⍳⍵)⊃¨⊂to}¨⍵ ⍝ translated value. } asgn←{_←tmp⍎⊃⍵ ⋄ 1↓⍵} ⍝ assign local name. unq←{(~≠\''''=⍵){⍺\⍺/⍵}⍵} ⍝ unquoted chars. unc←{(∧\'⍝'≠unq ⍵)/⍵} ⍝ uncommented line. show←⍺∘{↑⍺/↓⎕FMT ⍵} ⍝ show progress. tmp←##.(⎕NS ⎕NL 3 4 9) ⍝ tmp space for evaluation. ''≡scr:ok←0 ⍝ bad script name. 2=≡⍵:ok←1 exec scr ⍝ vector of vectors: go ahead, 1:ok←1 exec nest scr ⍝ split line vector. } ──────────────────────────────────────────────────────────────────────────────── Back to: contents