Защити мои стены от этих надоедливых дверей

20

Ручки великие и все такое, но когда вы открываете дверь, она всегда вдавливает стены вокруг нее. Мне нужно, чтобы вы взяли вход ASCII искусства комнаты, как это:

+---------+--X  --X    --+-----+
|       \     \   |\     |   \ |
|        \     \  | \    |    \|
|         X       |  \   |     X
|      /  |       |   \  X      
|     /   |     \       /       
|    /    |      \     /       |
+---X   --+-------X------+-----+

И выведите комнату с дверными проемами, вот так:

+---------+--X  --X    --+-----+
|       \  .  \   |\     |   \.|
|        \     \  | \   .|    \|
|         X       |  \   |     X
|      /  |       |.  \  X      
|     /  .|     \       /       
|.   /    |     .\     /       |
+---X   --+-------X------+-----+

Спецификация:

  • ASCII - зал (вход) будет состоять из +, -, и |. Эти персонажи чисто косметические; они все могут быть +с, но это будет выглядеть ужасно. Он также будет содержать петли ( X) и двери ( /или \).
  • Двери состоят из /или \. Начиная с символа «шарнир», то есть Xони будут идти прямо по диагонали (изменение 1 в xи 1 в y) для 2 или более единиц (символов).
  • Чтобы найти, где разместить дверную дверцу (всегда есть только одна дверная дверь), найдите дверной проем для двери. Дверной проем всегда будет начинаться с одной петли и будет занимать то же количество пробелов, что и длина двери, вверх, вниз, влево или вправо оттуда. Следующим пространством после этого всегда будет стена. Например, в этой двери дверной проем помечен Ds:

       \
        \
    ---DDX-----
    

    Когда найден дверной проем, выясните, нужно ли идти по часовой стрелке или против часовой стрелки, чтобы добраться до двери. Например, в приведенном выше примере двери вы должны идти по часовой стрелке, а в этом - против часовой стрелки:

       \ <-
        \  )
    -----X  ---
    

    Как только вы знаете, в какую сторону идти, продолжайте идти по ней (игнорируя дверь), пока не дойдете до стены.

    Вот визуализация этого для примера двери выше:

    визуализация

    Синий - это дверной проем, оранжевый - что вы должны идти по часовой стрелке, а красный продолжает идти по часовой стрелке, пока не будет достигнута стена.

    Как только вы достигнете стены, пройдите (длина двери) пробелы от петли ( X) на этой стене, отодвиньте одно пространство от стены к двери (чтобы вы не поместили дверную стопорку прямо на стену) и вставьте .там. Вот тот же пример двери, показывающий, как расположена дверная остановка:

       \
        \  .
    ---DDX12---
    

    Повторите для каждой двери, и выведите результат! Используйте пример ввода в верхней части этого поста в качестве контрольного примера для проверки правильности вашей программы.

    Обратите внимание, что вам не нужно обрабатывать двери, которые не подходят к их стенам, такие как:

    |     /
    |    /
    |   /
    |  /
    +-X    --
    

    Или:

         /
        /
       /
    +-X   --
    |
    |
    
  • Это , поэтому выиграет самый короткий код в байтах.
Дверная ручка
источник
Каковы правила для дверных проемов? Они должны быть ортогональными, такой же длины, что и их двери, и окружены стеной с одной стороны и шарниром (для правой двери) с другой стороны?
Джон Дворжак
@JanDvorak Хорошо, отредактировано для уточнения
Ручка двери
3
Можем ли мы предположить, что стена, начинающаяся с петли, имеет по меньшей мере ту же длину, что и дверь, и что никакие другие стены (не начинающиеся с петли) не мешают этой конкретной двери?
Говард
@ Говард, я не знаю, о чем ты. Вы спрашиваете, можете ли вы предположить, что длина противоположной стены от дверного проема равна длине дверного проема? Если это так, то нет, поскольку дверь могла поворачиваться только на 90 градусов, как вторая в тестовом случае (считая путем расположения петель, начиная с верхнего левого угла).
Дверная ручка
1
А? Дверь по диагонали. Все эти строки имеют ширину 6 символов, поэтому среднего столбца нет.
Питер Тейлор

Ответы:

4

Scala, 860 байт

Гольф :

    object D extends App{val s=args(0)split("\n")
    val r=Seq(P(1,0),P(1,-1),P(0,-1),P(-1,-1),P(-1,0),P(-1,1),P(0,1),P(1,1))
    var m=r(0)
    val e=s.map(_.toCharArray)
    case class P(x:Int,y:Int){def u=x==0||h
    def h=y==0
    def p(o:P)=P(x+o.x,y+o.y)
    def o="\\/".contains(c)
    def w="-|+".contains(c)
    def c=try s(y)(x) catch {case _=>'E'}
    def n=r.filter(!_.u).map(d => d.j(p(d))).sum
    def j(t:P):Int=if(t.o)1+j(p(t))else 0
    def q=if(c=='X'){m=this
    r.filter(_.u).map{d=>if(p(d).c==' '&&p(P(d.x*(n+1),d.y*(n+1))).w)d.i}}
    def i:Unit=Seq(r++r,(r++r).reverse).map(l=>l.drop(l.indexOf(this)+1)).map(_.take(4)).filter(_.exists(a=>a.p(m)o))(0).grouped(2).foreach{p=>if(p(1)p(m)w){p(0)add;return}}
    def add=if(r.filter(_.h).map(p(_)p(m)).exists(_.w))e(y*m.n+m.y)(x+m.x)='.'else e(y+m.y)(x*m.n+m.x)='.'}
    val f=args(0).size
    Array.tabulate(f,f){(i,j)=>P(i,j)q} 
    e.map(_.mkString).map(println)}

Без гольфа :

    object DoorknobCleanVersion extends App {
            val s = args(0) split ("\n")

            val r = Seq(P(1, 0), P(1, -1), P(0, -1), P(-1, -1), P(-1, 0), P(-1, 1), P(0, 1), P(1, 1))
            val HorizontalDirections = r.filter(_.isHorizontal)

            var hinge = r(0)
            val result = s.map(_.toCharArray)

            type I = Int
            case class P(x: Int, y: Int) {
                    def isCardinal = x == 0 || isHorizontal
                    def isHorizontal = y == 0

                    override def toString = x + "," + y

                    def p(o: P) = P(x + o.x, y + o.y)

                    def isDoor = Seq('\\', '/').contains(charAt)
                    def isWall = Seq('-', '|', '+').contains(charAt)

                    def charAt = try s(y)(x) catch { case _ => 'E' }

                    def doorLength = r.filter(!_.isCardinal).map(d => d.recursion2(p(d))).sum

                    def recursion2(currentPosition: P): Int =
                            if (currentPosition.isDoor)
                                    1 + recursion2(p(currentPosition))
                            else
                                    0

                    def findDoorway =
                            if (charAt == 'X') {
                                    hinge = this
                                    r.filter(_.isCardinal).map { d =>
                                            if (p(d).charAt == ' ' && p(P(d.x * (doorLength + 1), d.y * (doorLength + 1))).isWall)
                                                    d.getCorrectRotation2
                                    }
                            }

                    def getCorrectRotation2: Unit = Seq(r ++ r, (r ++ r).reverse).map(l => l.drop(l.indexOf(this) + 1))
                            .map(_.take(4))
                            .filter(_.exists(a => a.p(hinge)isDoor))(0)
                            .grouped(2)
                            .foreach {
                                    p =>
                                            if (p(1) p (hinge)isWall) {
                                                    p(0)add;
                                                    return
                                            }
                            }

                    def add =
                            if (HorizontalDirections.map(p(_) p (hinge)).exists(_.isWall))
                                    result(y * hinge.doorLength + hinge.y)(x + hinge.x) = '.'
                            else
                                    result(y + hinge.y)(x * hinge.doorLength + hinge.x) = '.'

            }

            val size = args(0).size
            Array.tabulate(size, size) { (i, j) => P(i, j).findDoorway }

            result.map(_.mkString).map(println)
    }

Оглядываясь назад, использование ООП было определенно неправильным подходом. Если бы я мог сделать это снова, я бы определенно пошел с кучей жестко закодированных таблиц правды.

Моя другая машина - кадр
источник