2019-12-06 09:56:14 +01:00
fun main ( ) {
2019-12-06 11:06:35 +01:00
val input = generateSequence ( :: readLine ) . map { it . split ( " ) " ) } . toList ( )
val parentToChildren = input . groupBy { it [ 0 ] } . mapValues { it . value . map { it [ 1 ] } }
val childToParent = input . associateBy { it [ 1 ] } . mapValues { it . value [ 0 ] }
val rootNode = ( parentToChildren . keys - parentToChildren . values . flatten ( ) . toSet ( ) ) . first ( )
println ( " Part 1: ${countOrbiters(parentToChildren, rootNode, 0)} " )
val santaParents = getParents ( childToParent , " SAN " )
val myParents = getParents ( childToParent , " YOU " )
val commonParent = firstCommon ( santaParents , myParents )
println ( " Part 2: ${santaParents.indexOf(commonParent) + myParents.indexOf(commonParent)} " )
2019-12-06 09:56:14 +01:00
}
2019-12-06 11:06:35 +01:00
fun < T > countOrbiters ( graph : Map < T , List < T > > , key : T , acc : Int ) : Int =
2019-12-06 10:16:50 +01:00
acc + ( graph [ key ] ?. map { countOrbiters ( graph , it , acc + 1 ) } ?. sum ( ) ?: 0 )
2019-12-06 11:06:35 +01:00
fun < T > getParents ( graph : Map < T , T > , key : T ) : List < T > =
graph [ key ] ?. let { curr -> listOf ( curr ) + getParents ( graph , curr ) } ?: emptyList ( )
fun < T > firstCommon ( first : List < T > , second : List < T > ) : T {
val seen = mutableSetOf < T > ( )
for ( i in 0. . first . size ) {
if ( first [ i ] in seen ) return first [ i ]
seen . add ( first [ i ] )
if ( second [ i ] in seen ) return second [ i ]
seen . add ( second [ i ] )
}
error ( " should be unreachable " )
}