package knightsmetric
fun main(args: Array<String>) {
println("(0,0) -> (0,0) in ${getMoves(0, 0)} moves")
println("(0,0) -> (3,7) in ${getMoves(3, 7)} moves")
println("(0,0) -> (0,1) in ${getMoves(0, 1)} moves")
println("(0,0) -> (5,3) in ${getMoves(5, 3)} moves")
println("(0,0) -> (7,4) in ${getMoves(7, 4)} moves")
println("(0,0) -> (9,9) in ${getMoves(9, 9)} moves")
}
data class Node(val id: Int, val parent: Node?, val value: IntArray)
fun getMoves(x: Int, y: Int) : Int {
val root = Node(0, null, intArrayOf(0,0))
val goal
= initGoal
(abs(x
), abs(y
))
return getMovesFromNode(root, goal)
}
fun initGoal(x: Int, y: Int) : IntArray = if(x >= y) intArrayOf(x, y) else intArrayOf(y, x)
fun getMovesFromNode(source: Node, destination: IntArray) : Int {
val moves = getMovesList()
var queue = mutableListOf(source)
var visited = mutableSetOf<Int>()
var dist = mutableMapOf<Pair<Int, Int>, Int>()
var cur = source
var i = 0
dist.put(Pair(source.id, source.id), 0)
while(!queue.isEmpty()) {
cur = queue.removeAt(0)
if(coordinateCompare(cur.value, destination)) {
break
}
if(!visited.contains(cur.id)) {
visited.add(cur.id)
for(move: IntArray in moves) {
var nextCoord = coordinateAdd(cur.value, move)
var d = (dist.get(Pair(source.id, cur.id)))!!
var next = Node(++i, cur, nextCoord)
if((next.value[0] < -1 || next.value[1] < -1)) {
continue
}
queue.add(next)
dist.put(Pair(source.id, next.id), ++d)
}
}
}
return dist.get(Pair(source.id, cur.id))!!
}
fun getMovesList() : Array<IntArray> = arrayOf(
intArrayOf(1, 2), intArrayOf(2, 1), intArrayOf(-1, 2),
intArrayOf(-2, 1), intArrayOf(1, -2), intArrayOf(2, -1)
)
fun
abs(a
: Int
) : Int
= if(a
< 0) a
* -1 else a
fun coordinateCompare(a: IntArray, b: IntArray) : Boolean = a[0] == b[0] && a[1] == b[1]
fun coordinateAdd(a: IntArray, b: IntArray) : IntArray = intArrayOf(a[0] + b[0], a[1] + b[1])
cGFja2FnZSBrbmlnaHRzbWV0cmljCgpmdW4gbWFpbihhcmdzOiBBcnJheTxTdHJpbmc+KSB7CiAgICBwcmludGxuKCIoMCwwKSAtPiAoMCwwKSBpbiAke2dldE1vdmVzKDAsIDApfSBtb3ZlcyIpCiAgICBwcmludGxuKCIoMCwwKSAtPiAoMyw3KSBpbiAke2dldE1vdmVzKDMsIDcpfSBtb3ZlcyIpCiAgICBwcmludGxuKCIoMCwwKSAtPiAoMCwxKSBpbiAke2dldE1vdmVzKDAsIDEpfSBtb3ZlcyIpCiAgICBwcmludGxuKCIoMCwwKSAtPiAoNSwzKSBpbiAke2dldE1vdmVzKDUsIDMpfSBtb3ZlcyIpCiAgICBwcmludGxuKCIoMCwwKSAtPiAoNyw0KSBpbiAke2dldE1vdmVzKDcsIDQpfSBtb3ZlcyIpCiAgICBwcmludGxuKCIoMCwwKSAtPiAoOSw5KSBpbiAke2dldE1vdmVzKDksIDkpfSBtb3ZlcyIpCn0KCmRhdGEgY2xhc3MgTm9kZSh2YWwgaWQ6IEludCwgdmFsIHBhcmVudDogTm9kZT8sIHZhbCB2YWx1ZTogSW50QXJyYXkpCgpmdW4gZ2V0TW92ZXMoeDogSW50LCB5OiBJbnQpIDogSW50IHsKICAgIHZhbCByb290ID0gTm9kZSgwLCBudWxsLCBpbnRBcnJheU9mKDAsMCkpCiAgICB2YWwgZ29hbCA9IGluaXRHb2FsKGFicyh4KSwgYWJzKHkpKQoKICAgIHJldHVybiBnZXRNb3Zlc0Zyb21Ob2RlKHJvb3QsIGdvYWwpCn0KCmZ1biBpbml0R29hbCh4OiBJbnQsIHk6IEludCkgOiBJbnRBcnJheSA9IGlmKHggPj0geSkgaW50QXJyYXlPZih4LCB5KSBlbHNlIGludEFycmF5T2YoeSwgeCkKCmZ1biBnZXRNb3Zlc0Zyb21Ob2RlKHNvdXJjZTogTm9kZSwgZGVzdGluYXRpb246IEludEFycmF5KSA6IEludCB7CiAgICB2YWwgbW92ZXMgPSBnZXRNb3Zlc0xpc3QoKQogICAgdmFyIHF1ZXVlID0gbXV0YWJsZUxpc3RPZihzb3VyY2UpCiAgICB2YXIgdmlzaXRlZCA9IG11dGFibGVTZXRPZjxJbnQ+KCkKICAgIHZhciBkaXN0ID0gbXV0YWJsZU1hcE9mPFBhaXI8SW50LCBJbnQ+LCBJbnQ+KCkKICAgIHZhciBjdXIgPSBzb3VyY2UKICAgIHZhciBpID0gMAoKICAgIGRpc3QucHV0KFBhaXIoc291cmNlLmlkLCBzb3VyY2UuaWQpLCAwKQoKICAgIHdoaWxlKCFxdWV1ZS5pc0VtcHR5KCkpIHsKICAgICAgICBjdXIgPSBxdWV1ZS5yZW1vdmVBdCgwKQoKICAgICAgICBpZihjb29yZGluYXRlQ29tcGFyZShjdXIudmFsdWUsIGRlc3RpbmF0aW9uKSkgewogICAgICAgICAgICBicmVhawogICAgICAgIH0KCiAgICAgICAgaWYoIXZpc2l0ZWQuY29udGFpbnMoY3VyLmlkKSkgIHsKICAgICAgICAgICAgdmlzaXRlZC5hZGQoY3VyLmlkKQogICAgICAgICAgICBmb3IobW92ZTogSW50QXJyYXkgaW4gbW92ZXMpIHsKICAgICAgICAgICAgICAgIHZhciBuZXh0Q29vcmQgPSBjb29yZGluYXRlQWRkKGN1ci52YWx1ZSwgbW92ZSkKICAgICAgICAgICAgICAgIHZhciBkID0gKGRpc3QuZ2V0KFBhaXIoc291cmNlLmlkLCBjdXIuaWQpKSkhIQogICAgICAgICAgICAgICAgdmFyIG5leHQgPSBOb2RlKCsraSwgY3VyLCBuZXh0Q29vcmQpCgogICAgICAgICAgICAgICAgaWYoKG5leHQudmFsdWVbMF0gPCAtMSB8fCBuZXh0LnZhbHVlWzFdIDwgLTEpKSB7CiAgICAgICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBxdWV1ZS5hZGQobmV4dCkKICAgICAgICAgICAgICAgIGRpc3QucHV0KFBhaXIoc291cmNlLmlkLCBuZXh0LmlkKSwgKytkKQogICAgICAgICAgICB9ICAgCiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIGRpc3QuZ2V0KFBhaXIoc291cmNlLmlkLCBjdXIuaWQpKSEhCn0KCmZ1biBnZXRNb3Zlc0xpc3QoKSA6IEFycmF5PEludEFycmF5PiA9IGFycmF5T2YoCiAgICBpbnRBcnJheU9mKDEsIDIpLCBpbnRBcnJheU9mKDIsIDEpLCBpbnRBcnJheU9mKC0xLCAyKSwgCiAgICBpbnRBcnJheU9mKC0yLCAxKSwgaW50QXJyYXlPZigxLCAtMiksIGludEFycmF5T2YoMiwgLTEpCikKCmZ1biBhYnMoYTogSW50KSA6IEludCA9IGlmKGEgPCAwKSBhICogLTEgZWxzZSBhCmZ1biBjb29yZGluYXRlQ29tcGFyZShhOiBJbnRBcnJheSwgYjogSW50QXJyYXkpIDogQm9vbGVhbiA9IGFbMF0gPT0gYlswXSAmJiBhWzFdID09IGJbMV0KZnVuIGNvb3JkaW5hdGVBZGQoYTogSW50QXJyYXksIGI6IEludEFycmF5KSA6IEludEFycmF5ID0gaW50QXJyYXlPZihhWzBdICsgYlswXSwgYVsxXSArIGJbMV0p