@ file : Suppress (" Spread Operator ") Ċ Ċ package Ġnet . tw ister rob . challenges . ad vent Of Code 2 0 1 8 . day 7 Ċ Ċ import Ġjava . io . File Ċ Ċ fun Ġmain ( var arg Ġargs : ĠString ) Ġ{ ĊĠĠĠ Ġval Ġfile Ġ= Ġargs . first () ĊĠĠĠ Ġval Ġfile Contents Ġ= ĠFile ( file ). read Text () ĊĠĠĠ Ġsolve ( file Contents ) Ċ } Ċ Ċ fun Ġsolve ( input : ĠString ): ĠString Ġ{ ĊĠĠĠ Ġval Ġline Pattern Ġ= ĠRegex (""" ^ Step Ġ([ A - Z ]) Ġmust Ġbe Ġfinished Ġbefore Ġstep Ġ([ A - Z ]) Ġcan Ġbegin .$ """) ĊĠĠĠ Ġfun ĠMatch Result . group As Step ( group : ĠInt ) Ġ= Ġthis . groups [ group ] !!. value [ 0 ] ĊĠĠĠ Ġfun Ġparse Line ( line : ĠString ): ĠPair < Char , ĠChar > Ġ= ĊĠĠĠĠĠĠĠ Ġline Pattern . match Ent ire ( line ) !!. let Ġ{ Ġmatch Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmatch . group As Step ( 1 ) Ġto Ġmatch . group As Step ( 2 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġconstraints Ġ= Ġinput ĊĠĠĠĠĠĠĠ Ġ. lines () ĊĠĠĠĠĠĠĠ Ġ. filter ( String :: isNotEmpty ) ĊĠĠĠĠĠĠĠ Ġ. map (:: parse Line ) ĊĊĠĠĠ Ġreturn Ġsolve (* constraints . to Typed Array ()) Ċ } Ċ Ċ fun Ġsolve ( var arg Ġpart Constraints : ĠPair < Char , ĠChar >): ĠString Ġ= ĊĠĠĠ Ġfind Order (* part Constraints ). join ToString ( separator Ġ= Ġ"") Ċ Ċ /** Ċ Ġ* Ġ@ see Ġ[ https :// en . wikipedia . org / wiki / Top ological _ sorting # K ah n 's _ algorithm ] Ċ Ġ*/ Ċ private Ġfun Ġfind Order ( var arg Ġedges : ĠPair < Char , ĠChar >): ĠList < Char > Ġ{ ĊĊĠĠĠ Ġclass ĠGraph ( var arg Ġedges : ĠPair < Char , ĠChar >) Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġgraph Ġ= Ġmutable Set Of (* edges ) ĊĊĠĠĠĠĠĠĠ Ġoperator Ġfun Ġminus Assign ( edge : ĠPair < Char , ĠChar >) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgraph Ġ-= Ġedge ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġhas Incoming Edges ( node : ĠChar ) Ġ= Ġgraph . any Ġ{ Ġit . second Ġ== Ġnode Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġthis Ġblow s Ġup Ġthe ĠO Ġcomplexity , Ġbut Ġthe Ġsol vable Ġinput Ġis Ġsmall ĊĠĠĠĠĠĠĠ Ġfun Ġdepend ents From ( node : ĠChar ) Ġ= Ġgraph . filter Ġ{ Ġit . first Ġ== Ġnode Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġhas Any Edges () Ġ= Ġgraph . isNotEmpty () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġgraph Ġ= ĠGraph (* edges ) ĊĠĠĠ Ġval Ġall Nodes Ġ= Ġedges . flatMap Ġ{ ĠlistOf ( it . first , Ġit . second ) Ġ}. toSet () ĊĠĠĠ Ġ// ĠSorted Set Ġto Ġsatisfy Ġ" If Ġmore Ġthan Ġone Ġstep Ġis Ġready , Ġchoose Ġthe Ġstep Ġwhich Ġis Ġfirst Ġalphabet ically ." ĊĠĠĠ Ġval Ġpossible Next Nodes Ġ= Ġall Nodes . filter Not ( graph :: has Incoming Edges ). to Sorted Set () ĊĊĠĠĠ Ġval Ġresult Ġ= Ġmutable ListOf < Char >() ĊĠĠĠ Ġwhile Ġ( possible Next Nodes . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnode Ġ= Ġpossible Next Nodes . first () ĊĠĠĠĠĠĠĠ Ġpossible Next Nodes Ġ-= Ġnode ĊĠĠĠĠĠĠĠ Ġresult Ġ+= Ġnode ĊĠĠĠĠĠĠĠ Ġval Ġnext Edges Ġ= Ġgraph . dependent s From ( node ) ĊĠĠĠĠĠĠĠ Ġnext Edges . forEach Ġ{ Ġedge Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgraph Ġ-= Ġedge ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! graph . has Incoming Edges ( edge . second )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpossible Next Nodes Ġ+= Ġedge . second ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġif Ġ( graph . has Any Edges ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġerror (" cycle ") ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġresult ĊĠĠĠ Ġ} Ċ } Ċ