Захистіть мої стіни від цих примхливих дверей


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 Добре, відредаговано для уточнення
Doorknob

3
Чи можемо ми припустити, що стіна, що починається від петлі, принаймні такої ж довжини, як і двері, і що жодна інша стіна (не починаючи від шарніра) не заважає цій конкретній двері?
Говард

@Howard Я не впевнений, про що ти говориш. Ви запитуєте, чи можете ви припустити, що протилежна стіна від дверного отвору такої ж довжини, як і дверний проріз? Якщо так, то ні, оскільки дверцята могла розгорнутися лише на 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)
    }

Використання OOP, безумовно, був неправильним підходом тут, заднім числом. Якби я міг це зробити ще раз, я б неодмінно пішов із купою твердо кодованих таблиць правди.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.