Chroń moje ściany przed tymi nieznośnymi drzwiami

20

Klamki są świetne, ale kiedy otworzysz drzwi, zawsze wgniatają ściany wokół nich. Potrzebuję, abyś wziął udział w sztuce ASCII pokoju, tak jak to:

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

I wyślij pokój ze stoperami, tak jak to:

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

Specyfikacja:

  • Pomieszczenie ASCII (wejście) składa się z +, -i |. Te postacie są czysto kosmetyczne; wszyscy mogliby być +s, ale to wyglądałoby okropnie. Będzie także zawierać zawiasy ( X) i drzwi ( /lub \).
  • Drzwi składają się z /lub \. Zaczynając od znaku „zawiasu”, czyli Xidą bezpośrednio po przekątnej (zmiana 1 w xi 1 w y) dla 2 lub więcej jednostek (postaci).
  • Aby dowiedzieć się, gdzie umieścić odbojnik do drzwi (zawsze jest tylko jeden odbojnik na drzwi), znajdź drzwi do drzwi. Drzwi zawsze zaczynają się od jednego zawiasu i stamtąd przechodzą taką samą liczbę miejsc, jak długość drzwi w górę, w dół, w lewo lub w prawo. Następnym miejscem po tym będzie zawsze ściana. Na przykład w tych drzwiach drzwi są oznaczone przez Ds:

       \
        \
    ---DDX-----
    

    Gdy znajdziesz drzwi, dowiedz się, czy musisz dotrzeć do drzwi w prawo, czy w lewo. Na przykład w powyższych przykładowych drzwiach musisz iść w kierunku zgodnym z ruchem wskazówek zegara, aw tym przypadku musisz iść w kierunku przeciwnym do ruchu wskazówek zegara:

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

    Kiedy już wiesz, którą drogą iść, idź tą drogą (ignorując drzwi), aż dojdziesz do ściany.

    Oto wizualizacja tego dla przykładowych drzwi powyżej:

    wyobrażanie sobie

    Niebieski jest bramą, pomarańczowy stwierdza, że ​​musisz iść w prawo, a czerwony kontynuuje w prawo, aż do ściany.

    Po dotarciu do ściany przejdź (na długości drzwi) odstępy od zawiasu ( X) na tej ścianie, odsuń jedno miejsce od ściany w kierunku drzwi (aby nie umieścić odbojnika bezpośrednio na ścianie) i włóż .tam. Oto te same przykładowe drzwi pokazujące sposób ustawienia blokady drzwi:

       \
        \  .
    ---DDX12---
    

    Powtórz dla wszystkich drzwi i wyślij wynik! Użyj przykładowego wejścia u góry tego postu jako przypadku testowego, aby sprawdzić, czy Twój program jest prawidłowy.

    Pamiętaj, że nie musisz obsługiwać drzwi, które nie pasują do ich ścian, takich jak:

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

    Lub:

         /
        /
       /
    +-X   --
    |
    |
    
  • To jest , więc wygra najkrótszy kod w bajtach.
Klamka
źródło
Jakie są zasady dotyczące drzwi? Muszą być ortogonalne, tej samej długości co drzwi i otoczone ścianą z jednej strony, a zawiasem (z prawej strony) z drugiej strony?
John Dvorak
@JanDvorak Ok, zredagowane w celu wyjaśnienia
Klamka
3
Czy możemy założyć, że ściana zaczynająca się od zawiasu ma co najmniej taką samą długość jak drzwi i że żadne inne ściany (nie zaczynające się od zawiasu) nie kolidują z konkretnymi drzwiami?
Howard
@ Howard Nie jestem pewien, o czym mówisz. Czy pytasz, czy możesz założyć, że przeciwległa ściana od drzwi ma taką samą długość jak drzwi? Jeśli tak, to nie, ponieważ drzwi mogą wychylać się tylko o 90 stopni, tak jak drugi w przypadku testowym (licząc od umieszczenia zawiasu, zaczynając od lewego górnego rogu).
Klamka
1
Co? Drzwi są ukośne. Wszystkie te ciągi mają szerokość 6 znaków, więc nie ma środkowej kolumny.
Peter Taylor

Odpowiedzi:

4

Scala, 860 bajtów

Gra w golfa :

    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)}

Bez golfa :

    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)
    }

Z perspektywy czasu używanie OOP było zdecydowanie niewłaściwym podejściem. Gdybym mógł to zrobić jeszcze raz, zdecydowanie wybrałbym kilka zakodowanych tabel prawdy.

Mój drugi samochód to cadr
źródło