import scala.
collection.
mutable.
_ import scala.
collection.
{Map
=> CMap, Seq
=> CSeq
} import scala.
collection.
immutable.
{Map
=> IMap, Seq
=> ISeq
} 'AB -> IMap('NB -> 5.0, 'AY -> 2.5, 'AG -> 3.0),
'AY -> IMap('AB -> 2.5, 'AG -> 2.0, 'DY -> 3.0),
'AG -> IMap('AY -> 2.0, 'AB -> 3.0, 'BG -> 2.0),
'BG -> IMap('AG -> 2.0, 'CG -> 2.0),
'CG -> IMap('DG -> 1.0, 'BG -> 2.0),
'DG -> IMap('CG -> 1.0, 'EG -> 1.0, 'DY -> 1.5),
'DY -> IMap('AY -> 3.0, 'GY -> 3.0, 'DG -> 1.5),
'EG -> IMap('DG -> 1.0, 'FG -> 2.0),
'FG -> IMap('EG -> 2.0, 'GG -> 2.0),
'GG -> IMap('GY -> 1.5, 'FG -> 2.0, 'JG -> 3.0),
'GY -> IMap('GG -> 1.5, 'DY -> 3.0, 'HY -> 2.0),
'HY -> IMap('GY -> 2.0, 'IY -> 2.0),
'IY -> IMap('HY -> 2.0, 'JY -> 1.0),
'JY -> IMap('IY -> 1.0, 'KY -> 2.0, 'JG -> 1.5),
'KY -> IMap('JY -> 2.0, 'LY -> 2.0),
'LY -> IMap('KY -> 2.0, 'MY -> 1.0),
'MY -> IMap('MG -> 1.5, 'MB -> 1.0, 'LY -> 1.0),
'MG -> IMap('MY -> 1.5, 'MB -> 2.0, 'JG -> 3.0),
'MB -> IMap('MG -> 2.0, 'MY -> 1.0, 'NB -> 5.0),
'NB -> IMap('NP -> 2.0, 'AB -> 5.0, 'MB -> 5.0),
'NP -> IMap('ZP -> 6.0, 'NB -> 2.0),
'ZP -> IMap('NP -> 6.0)
)
def getPath
(chart
: CMap
[Symbol, CMap
[Symbol, Double
]], start
: Symbol, end
: Symbol
): CSeq
[Symbol
] = { val paths
= new Map.
WithDefault[Symbol, CSeq
[Symbol
]](Map.
empty[Symbol, CSeq
[Symbol
]], k
=> ISeq.
empty[Symbol
]) val distance
= new Map.
WithDefault[Symbol, Double
](Map
(current -
> 0.0), k
=> 1000000.0) val parent
= Map.
empty[Symbol, Symbol
] val unvisited
= Set.
empty[Symbol
] ++ chart.
keys - current
while (unvisited contains end
) { val neighbors
= chart
(current
) neighbors.keys.filter(unvisited contains _).foreach(s => {
distance
(s
) = if (distance
(s
) > (distance
(current
) + chart
(current
)(s
))) { parent(s) = current
distance(current) + chart(current)(s)
})
unvisited -= current
val head
= unvisited.
toSeq.
sortBy(distance.
apply).
head paths(head) = parent(head) +: paths(parent(head))
current = head
}
paths(end).reverse :+ end
}
def getDistance
(chart
: CMap
[Symbol, CMap
[Symbol, Double
]], seq
: CSeq
[Symbol
]): Double
= { i <- Range(0, seq.length - 1)
sym1 = seq(i)
sym2 = seq(i+1)
} yield chart
(sym1
)(sym2
) (0.0 /: distances) (_ + _)
}
def parse
(s
: Symbol
): String
= { }
str(0) + " " + color
}
def getBest
(chart
: CMap
[Symbol, CMap
[Symbol, Double
]], char1
: Char, char2
: Char
): CSeq
[Symbol
] = { sym1 <- chart.keys.filter(_.name(0) == char1)
sym2 <- chart.keys.filter(_.name(0) == char2)
} yield getPath
(chart, sym1, sym2
) paths.toSeq.sortBy(getDistance(chart, _)).head
}
Seq(('M', 'Z'), ('Z', 'B')).foreach(p => println(s"Path: ${getBest(chart, p._1, p._2).map(parse).mkString(", ")}, time: ${getDistance(chart, getBest(chart, p._1, p._2))} minutes"))
}
aW1wb3J0IHNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5fCmltcG9ydCBzY2FsYS5jb2xsZWN0aW9uLntNYXAgPT4gQ01hcCwgU2VxID0+IENTZXF9CmltcG9ydCBzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS57TWFwID0+IElNYXAsIFNlcSA9PiBJU2VxfQpvYmplY3QgTWFpbiBleHRlbmRzIEFwcCB7Cgl2YWwgY2hhcnQgPSBJTWFwKAoJCSdBQiAtPiBJTWFwKCdOQiAtPiA1LjAsICdBWSAtPiAyLjUsICdBRyAtPiAzLjApLAoJCSdBWSAtPiBJTWFwKCdBQiAtPiAyLjUsICdBRyAtPiAyLjAsICdEWSAtPiAzLjApLAoJCSdBRyAtPiBJTWFwKCdBWSAtPiAyLjAsICdBQiAtPiAzLjAsICdCRyAtPiAyLjApLAoJCSdCRyAtPiBJTWFwKCdBRyAtPiAyLjAsICdDRyAtPiAyLjApLAoJCSdDRyAtPiBJTWFwKCdERyAtPiAxLjAsICdCRyAtPiAyLjApLAoJCSdERyAtPiBJTWFwKCdDRyAtPiAxLjAsICdFRyAtPiAxLjAsICdEWSAtPiAxLjUpLAoJCSdEWSAtPiBJTWFwKCdBWSAtPiAzLjAsICdHWSAtPiAzLjAsICdERyAtPiAxLjUpLAoJCSdFRyAtPiBJTWFwKCdERyAtPiAxLjAsICdGRyAtPiAyLjApLAoJCSdGRyAtPiBJTWFwKCdFRyAtPiAyLjAsICdHRyAtPiAyLjApLAoJCSdHRyAtPiBJTWFwKCdHWSAtPiAxLjUsICdGRyAtPiAyLjAsICdKRyAtPiAzLjApLAoJCSdHWSAtPiBJTWFwKCdHRyAtPiAxLjUsICdEWSAtPiAzLjAsICdIWSAtPiAyLjApLAoJCSdIWSAtPiBJTWFwKCdHWSAtPiAyLjAsICdJWSAtPiAyLjApLAoJCSdJWSAtPiBJTWFwKCdIWSAtPiAyLjAsICdKWSAtPiAxLjApLAoJCSdKWSAtPiBJTWFwKCdJWSAtPiAxLjAsICdLWSAtPiAyLjAsICdKRyAtPiAxLjUpLAoJCSdLWSAtPiBJTWFwKCdKWSAtPiAyLjAsICdMWSAtPiAyLjApLAoJCSdMWSAtPiBJTWFwKCdLWSAtPiAyLjAsICdNWSAtPiAxLjApLAoJCSdNWSAtPiBJTWFwKCdNRyAtPiAxLjUsICdNQiAtPiAxLjAsICdMWSAtPiAxLjApLAoJCSdNRyAtPiBJTWFwKCdNWSAtPiAxLjUsICdNQiAtPiAyLjAsICdKRyAtPiAzLjApLAoJCSdNQiAtPiBJTWFwKCdNRyAtPiAyLjAsICdNWSAtPiAxLjAsICdOQiAtPiA1LjApLAoJCSdOQiAtPiBJTWFwKCdOUCAtPiAyLjAsICdBQiAtPiA1LjAsICdNQiAtPiA1LjApLAoJCSdOUCAtPiBJTWFwKCdaUCAtPiA2LjAsICdOQiAtPiAyLjApLAoJCSdaUCAtPiBJTWFwKCdOUCAtPiA2LjApCgkpCgkKCWRlZiBnZXRQYXRoKGNoYXJ0OiBDTWFwW1N5bWJvbCwgQ01hcFtTeW1ib2wsIERvdWJsZV1dLCBzdGFydDogU3ltYm9sLCBlbmQ6IFN5bWJvbCk6IENTZXFbU3ltYm9sXSA9IHsKCQl2YXIgY3VycmVudCA9IHN0YXJ0CgkJdmFsIHBhdGhzID0gbmV3IE1hcC5XaXRoRGVmYXVsdFtTeW1ib2wsIENTZXFbU3ltYm9sXV0oTWFwLmVtcHR5W1N5bWJvbCwgQ1NlcVtTeW1ib2xdXSwgayA9PiBJU2VxLmVtcHR5W1N5bWJvbF0pCgkJdmFsIGRpc3RhbmNlID0gbmV3IE1hcC5XaXRoRGVmYXVsdFtTeW1ib2wsIERvdWJsZV0oTWFwKGN1cnJlbnQgLT4gMC4wKSwgayA9PiAxMDAwMDAwLjApCgkJdmFsIHBhcmVudCA9IE1hcC5lbXB0eVtTeW1ib2wsIFN5bWJvbF0KCQl2YWwgdW52aXNpdGVkID0gU2V0LmVtcHR5W1N5bWJvbF0gKysgY2hhcnQua2V5cyAtIGN1cnJlbnQKCQl3aGlsZSAodW52aXNpdGVkIGNvbnRhaW5zIGVuZCkgewoJCQl2YWwgbmVpZ2hib3JzID0gY2hhcnQoY3VycmVudCkKCQkJbmVpZ2hib3JzLmtleXMuZmlsdGVyKHVudmlzaXRlZCBjb250YWlucyBfKS5mb3JlYWNoKHMgPT4gewoJCQkJZGlzdGFuY2UocykgPSBpZiAoZGlzdGFuY2UocykgPiAoZGlzdGFuY2UoY3VycmVudCkgKyBjaGFydChjdXJyZW50KShzKSkpIHsKCQkJCQlwYXJlbnQocykgPSBjdXJyZW50CgkJCQkJZGlzdGFuY2UoY3VycmVudCkgKyBjaGFydChjdXJyZW50KShzKQoJCQkJfSBlbHNlIGRpc3RhbmNlKHMpCgkJCX0pCgkJCXVudmlzaXRlZCAtPSBjdXJyZW50CgkJCXZhbCBoZWFkID0gdW52aXNpdGVkLnRvU2VxLnNvcnRCeShkaXN0YW5jZS5hcHBseSkuaGVhZAoJCQlwYXRocyhoZWFkKSA9IHBhcmVudChoZWFkKSArOiBwYXRocyhwYXJlbnQoaGVhZCkpCgkJCWN1cnJlbnQgPSBoZWFkCgkJfQoJCXBhdGhzKGVuZCkucmV2ZXJzZSA6KyBlbmQKCX0KCQoJZGVmIGdldERpc3RhbmNlKGNoYXJ0OiBDTWFwW1N5bWJvbCwgQ01hcFtTeW1ib2wsIERvdWJsZV1dLCBzZXE6IENTZXFbU3ltYm9sXSk6IERvdWJsZSA9IHsKCQl2YWwgZGlzdGFuY2VzID0gZm9yIHsKCQkJaSA8LSBSYW5nZSgwLCBzZXEubGVuZ3RoIC0gMSkKCQkJc3ltMSA9IHNlcShpKQoJCQlzeW0yID0gc2VxKGkrMSkKCQl9IHlpZWxkIGNoYXJ0KHN5bTEpKHN5bTIpCgkJKDAuMCAvOiBkaXN0YW5jZXMpIChfICsgXykKCX0KCQoJZGVmIHBhcnNlKHM6IFN5bWJvbCk6IFN0cmluZyA9IHsKCQl2YWwgU3ltYm9sKHN0cikgPSBzCgkJdmFsIGNvbG9yID0gc3RyKDEpIG1hdGNoIHsKCQkJY2FzZSAnUCcgPT4gIlBpbmsiCgkJCWNhc2UgJ0cnID0+ICJHcmVlbiIKCQkJY2FzZSAnQicgPT4gIkJsdWUiCgkJCWNhc2UgJ1knID0+ICJZZWxsb3ciCgkJCWNhc2UgXyA9PiAibnVsbCIKCQl9CgkJc3RyKDApICsgIiAiICsgY29sb3IKCX0KCQoJZGVmIGdldEJlc3QoY2hhcnQ6IENNYXBbU3ltYm9sLCBDTWFwW1N5bWJvbCwgRG91YmxlXV0sIGNoYXIxOiBDaGFyLCBjaGFyMjogQ2hhcik6IENTZXFbU3ltYm9sXSA9IHsKCQl2YWwgcGF0aHMgPSBmb3IgewoJCQlzeW0xIDwtIGNoYXJ0LmtleXMuZmlsdGVyKF8ubmFtZSgwKSA9PSBjaGFyMSkKCQkJc3ltMiA8LSBjaGFydC5rZXlzLmZpbHRlcihfLm5hbWUoMCkgPT0gY2hhcjIpCgkJfSB5aWVsZCBnZXRQYXRoKGNoYXJ0LCBzeW0xLCBzeW0yKQoJCXBhdGhzLnRvU2VxLnNvcnRCeShnZXREaXN0YW5jZShjaGFydCwgXykpLmhlYWQKCX0KCVNlcSgoJ00nLCAnWicpLCAoJ1onLCAnQicpKS5mb3JlYWNoKHAgPT4gcHJpbnRsbihzIlBhdGg6ICR7Z2V0QmVzdChjaGFydCwgcC5fMSwgcC5fMikubWFwKHBhcnNlKS5ta1N0cmluZygiLCAiKX0sIHRpbWU6ICR7Z2V0RGlzdGFuY2UoY2hhcnQsIGdldEJlc3QoY2hhcnQsIHAuXzEsIHAuXzIpKX0gbWludXRlcyIpKQp9