Guest User

Mélységi bejárás kotlinba konvertálva ronda módon

a guest
Oct 24th, 2018
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 9.27 KB | None | 0 0
  1. import kotlin.experimental.and
  2. import kotlin.system.measureTimeMillis
  3.  
  4. data class Coordinate(val x: Int, val y: Int)
  5.  
  6. @SinceKotlin("1.1")
  7. data class Field(val x: Int, val y: Int, val value: Byte) {
  8.     fun northWall(): Boolean {
  9.         return value and 1 != 0.toByte()
  10.     }
  11.  
  12.     fun eastWall(): Boolean {
  13.         return value and 2 != 0.toByte()
  14.     }
  15.  
  16.     fun southWall(): Boolean {
  17.         return value and 4 != 0.toByte()
  18.     }
  19.  
  20.     fun westWall(): Boolean {
  21.         return value and 8 != 0.toByte()
  22.     }
  23.  
  24.     fun hasObject(): Boolean {
  25.         return value and 16 != 0.toByte()
  26.     }
  27. }
  28.  
  29. class Input(val labyrinth: Labyrinth, val nObjects: Int)
  30.  
  31. class Labyrinth(val width: Int, val height: Int, val fields: Array<Field>) {
  32.     fun getField(x: Int, y: Int): Field {
  33.         return fields[x + y * width]
  34.     }
  35. }
  36.  
  37. class Output(val steps: List<Coordinate?>)
  38.  
  39. class InputParser {
  40.     private val rows : MutableList<Array<Field>> = mutableListOf()
  41.     private var numObjects: Int = 0
  42.  
  43.     private val input: Input
  44.         get() {
  45.             val width = rows[0].size
  46.             val fields = arrayOfNulls<Field>(width * rows.size)
  47.  
  48.             for (y in rows.indices) {
  49.                 val row = rows[y]
  50.                 //System.arraycopy(rows[y], 0, fields, y * width, width)
  51.  
  52.                 for (p in y*width until y*width + width) {
  53.                     fields[p] = row[p-y*width]
  54.                 }
  55.             }
  56.  
  57.             val labyrinth = Labyrinth(width, rows.size, fields.requireNoNulls())
  58.  
  59.             return Input(labyrinth, numObjects)
  60.         }
  61.  
  62.     fun feedLine(line: String): Input? {
  63.         val items = line.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
  64.  
  65.         if (items.size == 1) {
  66.             numObjects = items[0].toInt()
  67.  
  68.             return input
  69.         } else if (items.size > 0) {
  70.             val rowNum = rows.size
  71.             val row = arrayOfNulls<Field>(items.size)
  72.  
  73.             for (col in items.indices) {
  74.                 row[col] = Field(rowNum, col, items[col].toByte())
  75.             }
  76.  
  77.             rows.add(row.requireNoNulls())
  78.         }
  79.  
  80.         return null
  81.     }
  82. }
  83.  
  84.  
  85. class Solver(private val input: Input) {
  86.     private val objects: List<Coordinate>
  87.  
  88.     private val width: Int
  89.     private val height: Int
  90.     private val maze_end: Coordinate
  91.  
  92.     private var counter: Long = 0
  93.  
  94.     init {
  95.  
  96.         objects = ArrayList()
  97.         for (f in input.labyrinth.fields) {
  98.             if (f.hasObject()) {
  99.                 objects.add(Coordinate(f.x, f.y))
  100.             }
  101.         }
  102.  
  103.         width = input.labyrinth.width
  104.         height = input.labyrinth.height
  105.         maze_end = Coordinate(width - 1, height - 1)
  106.     }
  107.  
  108.     fun solve(): Output {
  109.         val steps = ArrayList<Coordinate>()
  110.  
  111.         for (o in objects.indices) {
  112.             var limit = input.labyrinth.width + input.labyrinth.height - 2
  113.  
  114.             var ss: List<Coordinate>? = null
  115.             while (ss == null) {
  116.                 //println("o$o, limit: $limit")
  117.  
  118.                 if (o == 0) {
  119.                     ss = solveWithLimit(limit, MAZE_START) { it[it.size - 1] == objects[0] }
  120.                 } else {
  121.                     ss = solveWithLimit(limit, objects[o - 1]) { it[it.size - 1] == objects[o] }
  122.                 }
  123.  
  124.                 if (ss != null) {
  125.                     steps.addAll(ss)
  126.                 }
  127.  
  128.                 limit++
  129.             }
  130.         }
  131.  
  132.         var limit = input.labyrinth.width + input.labyrinth.height - 2
  133.  
  134.         var ss: List<Coordinate>? = null
  135.         while (ss == null) {
  136.             ss = solveWithLimit(limit, objects[objects.size - 1]) { it[it.size - 1] == maze_end }
  137.  
  138.             if (ss != null) {
  139.                 steps.addAll(ss)
  140.             }
  141.  
  142.             limit++
  143.         }
  144.  
  145.         return createOutput(steps)
  146.     }
  147.  
  148.     private fun createOutput(steps: List<Coordinate>): Output {
  149.         val objects : MutableList<Coordinate> = this.objects.toMutableList()
  150.         val outSteps : MutableList<Coordinate?> = mutableListOf()
  151.  
  152.         for (step in steps) {
  153.             outSteps.add(step)
  154.  
  155.             if (objects.contains(step)) {
  156.                 outSteps.add(null)
  157.                 objects.remove(step)
  158.             }
  159.         }
  160.  
  161.         return Output(outSteps)
  162.     }
  163.  
  164.     private fun isValid(steps: List<Coordinate>): Boolean {
  165.         counter++
  166.         val (x, y) = steps[steps.size - 1]
  167.         return if (!(x == input.labyrinth.width - 1 && y == input.labyrinth.height - 1)) { // Jobb also a cel
  168.             false
  169.         } else steps.containsAll(objects)
  170.  
  171.     }
  172.  
  173.     private fun getPossibleSteps(now: Coordinate, previous: Coordinate?): ArrayList<Coordinate> {
  174.         val field = input.labyrinth.getField(now.x, now.y)
  175.  
  176.         val possibleSteps = ArrayList<Coordinate>()
  177.  
  178.         if (now.x != width - 1 && !field.eastWall()) {
  179.             possibleSteps.add(Coordinate(now.x + 1, now.y))
  180.         }
  181.         if (now.x != 0 && !field.westWall()) {
  182.             possibleSteps.add(Coordinate(now.x - 1, now.y))
  183.         }
  184.         if (now.y != 0 && !field.northWall()) {
  185.             possibleSteps.add(Coordinate(now.x, now.y - 1))
  186.         }
  187.         if (now.y != height - 1 && !field.southWall()) {
  188.             possibleSteps.add(Coordinate(now.x, now.y + 1))
  189.         }
  190.  
  191.         if (!field.hasObject() && previous != null) {
  192.             possibleSteps.remove(previous)
  193.         }
  194.  
  195.         return possibleSteps
  196.     }
  197.  
  198.     private fun solveWithLimit(limit: Int, start: Coordinate, validFn: (List<Coordinate>) -> Boolean): List<Coordinate>? {
  199.         var steps: MutableList<Coordinate>? = findFirstLegitSteps(null, start, limit)
  200.  
  201.         while (steps != null && !validFn(steps)) {
  202.             steps = alter(start, null, steps)
  203.         }
  204.  
  205.         return steps
  206.     }
  207.  
  208.     private fun findFirstLegitSteps(startPrev: Coordinate?, start: Coordinate, num: Int): MutableList<Coordinate>? {
  209.         var steps: MutableList<Coordinate>? = ArrayList()
  210.  
  211.  
  212.         var i = 0
  213.         while (i < num) {
  214.             val prev: Coordinate?
  215.             val state: Coordinate
  216.  
  217.             if (i == 0) {
  218.                 state = start
  219.                 prev = startPrev
  220.             } else if (i == 1) {
  221.                 state = steps!![i - 1]
  222.                 prev = startPrev
  223.             } else {
  224.                 state = steps!![i - 1]
  225.                 prev = steps[i - 2]
  226.             }
  227.  
  228.             val possibleSteps = getPossibleSteps(state, prev)
  229.  
  230.             if (possibleSteps.size == 0) {
  231.                 if (steps!!.size == 0) {
  232.                     return null
  233.                 }
  234.  
  235.                 steps = alter(start, startPrev, steps)
  236.                 if (steps == null) {
  237.                     return null
  238.                 }
  239.  
  240.                 i--
  241.                 i++
  242.                 continue
  243.             }
  244.  
  245.             val newStep = possibleSteps[0]
  246.             steps!!.add(newStep)
  247.             i++
  248.         }
  249.  
  250.         return steps
  251.     }
  252.  
  253.     private fun alter(start: Coordinate, startPrev: Coordinate?, steps: MutableList<Coordinate>): MutableList<Coordinate>? {
  254.         val size = steps.size
  255.  
  256.         var i = size - 1
  257.         while (i >= 0) {
  258.             val current = steps[i]
  259.             val prev = if (i == 0) start else steps[i - 1]
  260.             val prevprev: Coordinate?
  261.             if (i > 1) {
  262.                 prevprev = steps[i - 2]
  263.             } else if (i == 1) {
  264.                 prevprev = start
  265.             } else {
  266.                 prevprev = startPrev
  267.             }
  268.  
  269.             val alternatives = getPossibleSteps(prev, prevprev)
  270.             val index = alternatives.indexOf(current)
  271.  
  272.             if (index != alternatives.size - 1) {
  273.                 val newItem = alternatives[index + 1]
  274.                 steps[i] = newItem
  275.  
  276.                 val remainder = findFirstLegitSteps(prev, newItem, size - i - 1)
  277.                 if (remainder == null) {
  278.                     i++
  279.                     i--
  280.                     continue
  281.                 }
  282.  
  283.                 removeAfterIndexExclusive(steps, i)
  284.                 steps.addAll(remainder)
  285.  
  286.                 return steps
  287.             } else {
  288.                 if (i == 0) {
  289.                     return null
  290.                 }
  291.             }
  292.             i--
  293.         }
  294.  
  295.         return steps
  296.     }
  297.  
  298.     companion object {
  299.         private val MAZE_START = Coordinate(0, 0)
  300.         private fun removeAfterIndexExclusive(list: MutableList<*>, index: Int) {
  301.             val rnum = list.size - 1 - index
  302.  
  303.             for (i in 0 until rnum) {
  304.                 list.removeAt(list.size - 1)
  305.             }
  306.         }
  307.     }
  308. }
  309.  
  310. private fun readTillParsed(): Input? {
  311.  
  312.     val parser = InputParser()
  313.  
  314.     while (true) {
  315.         val line = readLine() ?: return null
  316.  
  317.         val input = parser.feedLine(line)
  318.         if (input != null) {
  319.             return input
  320.         }
  321.     }
  322.  
  323.     return null
  324. }
  325.  
  326. fun main(args : Array<String>) {
  327.     val input = readTillParsed()
  328.  
  329.     val solver = Solver(input!!)
  330.     val time = measureTimeMillis {
  331.         val output = solver.solve()
  332.  
  333.         for (c in output.steps) {
  334.             if (c == null) {
  335.                 println("felvesz")
  336.             } else {
  337.                 println("${c.x} ${c.y}")
  338.             }
  339.         }
  340.     }
  341.  
  342.     println("time: $time")
  343.  
  344. }
Advertisement
Add Comment
Please, Sign In to add comment