Bu Gerçek Bir Ağaç mı?


20

Girdi bir ASCII ağacı ise, girdi olarak çıktı ve çıktı ya da geri dönen bir program veya işlev yazmalısınız.

  _
\/  /
 \_/
  |
  |

ASCII ağaçları karakterlerden oluşmaktadır / \ | _ spacesve newlines.

Boşluk olmayan karakterler hücrelerinin iki kenar noktasını bir çizgi parçasına bağlar:

  • / sol alt ve sağ üst köşeleri birleştirir
  • \ sağ alt ve sol üst köşeleri birleştirir
  • | alt kenar ve üst kenarın orta noktalarını birleştirir
  • _ sol alt ve sağ alt köşeleri ve alt kenarın orta noktasını birleştirir

(Not bu araçlar |, sadece ile bağlanabilir |ya da _değil ile /ya \.)

Aşağıdaki kurallar geçerliyse ASCII resmine ağaç denir:

  • Tam olarak bir karakterin tam olarak bir noktası (kök) son satırın alt kenarına temas eder.
  • Herhangi bir çizgi segmentinin herhangi bir noktasına aşağıdaki yollarla ulaşabilirsiniz:

    • kökten başlayarak
    • yalnızca çizgi segmentlerini kullanarak
    • asla aşağıya doğru gitmez (yana doğru bile değil)

Giriş

  • Karakterlerden oluşan / \ | _ spaceve newlineen az bir boşluk olmayan karakter içeren bir dize .
  • İki giriş biçimi arasından seçim yapabilirsiniz:

    • Ağacın etrafında gereksiz boşluk yoktur (örneklerde görüldüğü gibi).
    • Tüm satırları aynı uzunlukta yapmak için satırların sağ tarafındaki boşluklar hariç, ağacın etrafında (örneklerde görüldüğü gibi) gereksiz boşluk yoktur.
  • Sondaki satır başı isteğe bağlıdır.

Çıktı

  • Giriş bir ascii ağacı ise tutarlı bir doğruluk değeri.
  • Giriş bir ascii ağacı değilse tutarlı bir falsy değeri.

Örnekler

Geçerli ağaçlar:

|
  _
\/  /
 \_/
  |
  |
/ /    \/
\ \____/
 \/
 /
/
 \___/
 /   \
 \___/
   |
   |
   __/
 _/
/
____
  \  ___
 \ \/
  \/\_____/
 \/  \/
  \__/
    |
    |

Geçersiz ağaçlar (girdilerin parçası olmayan ekstra açıklamalar ile):

\/
 \_______/
  \__   /
   | \_/    <- reachable only on with downward route
   |
_           <- multiple roots
\/          <- multiple root characters
/\          <- multiple roots
|           <- unreachable part

|
 __/
/           <- unreachable parts
|
\____/
 |  |       <- multiple roots
_\__/       <- unreachable parts (_ and \ don't connect to each other)
|

Bu kod golf bu yüzden en kısa giriş kazanır.

Yanıtlar:


7

PMA / Salyangoz , 99 93

"Ağaç" tanımını karşılıyorsa 1 veya basarsa 0 yazdırır. Düzensiz dolgulu girdi biçimi tercih edilir, ancak Fdüzensiz sürümü test için yararlı olan boşlukla dolu bir dikdörtgene dönüştürmek için yalnızca bir bayta ( seçeneği kullanarak ) mal olur.

&
\ |{(\_|\|)d=\||(\\a7|\/d|\_da7)=\\|(\\d|\/a5|\_da5)=\/|(\_lr|\|d|\/l|\\r)=\_},^_!(r.,^ )d~

Ungolfed, eski sürüm (kişisel görüntüleme zevkim için):

F&
\ |
{
  \_ (lr=\_|da5=\/|da7=\\|d=\|) | \/ (l=\_|a5=\/|d=\\) | 
    \\ (r=\_|a7=\\|d=\/) | \|d=(\_|\|)    
}, 
^_ !(r.,^ ) d~

Bu, mevcut dil özellikleri için oldukça uygun. Ne yazık ki, işe yaramadan önce referans sayım hatasını takip etmek için birkaç saat harcamak zorunda kaldım.

&Opsiyon maçı her karakter başarılı gerektiği anlamına gelir. Her boşluk olmayan başlangıç ​​noktasından aşağıya doğru aşağı bir yol olup olmadığını kontrol eder. Regex ile sonlu durum makinesi yapmak, burada iddialar kullanılarak şans eseri çok daha kısadır =. En alt satırda, sağda boşluk olmayan karakterler olup olmadığını kontrol eder.


10

Mathematica, 345300 bayt

Hala oldukça uzun, ama sanırım bir başlangıç ​​...

(s=StringSplit;v=Reverse;#=="|"||#=="\\"||#=="/"&[""<>s@#]&&(g={};i=0;(c={i,++j};d={i,j+1/2};e=2d-c;g=Join[g,Switch[#,"|",{d->{1,0}+d},"/",{c->c+1},"\\",{e->{i+1,j}},"_",{c->d,d->e,e->c},_,{}]])&/@Characters[++i;j=0;#]&/@{##};Sort@VertexOutComponent[Graph@g,g[[1,1]]]==Union@@List@@@g)&@@v@s[#,"
"])&

İşte biraz ungolfed versiyonu:

(
  s = StringSplit;
  v = Reverse;
  # == "|" || # == "\\" || # == "/" &[
      "" <> s@#
      ] && (
      g = {};
      i = 0;
      (
           c = {i, ++j};
           d = {i, j + 1/2};
           e = 2 d - c;
           g = Join[g, Switch[#,
              "|", {d -> {1, 0} + d},
              "/", {c -> c + 1},
              "\\", {e -> {i + 1, j}},
              "_", {c -> d, d -> e, e -> c},
              _, {}
              ]]
           ) & /@ Characters[
          ++i;
          j = 0;
          #
          ] & /@ {##};
      Sort@VertexOutComponent[Graph@g, g[[1, 1]]] == 
       Union @@ List @@@ g
      ) & @@ v@s[#, "\n"]
) &

Bu giriş ve döner gibi dizisini alır isimsiz işlevi tanımlar Trueya da False.

Temel fikir önce tek bir kök olup olmadığını kontrol etmek ve daha sonra kökten Graphtüm köşelere ulaşılıp ulaşılamayacağını kontrol etmek için gerçek (yönlendirilmiş) bir nesne oluşturmaktır. Grafiği şu şekilde oluşturuyoruz:

Tam sayı koordinatlarının karakter hücrelerinin köşelerine karşılık geldiği ASCII sanatı üzerine yerleştirilmiş bir tam sayı ızgarası düşünün. Daha sonra hücrelerin her birinde bağlanabilecek altı ilgili nokta vardır. İşte ben de puan etiketlediğinize bir örnek vardır aiçin f:

     |                 |
     |                 |
---(2,3)---(2.5,3)---(3,2)---
     | d      e      f |
     |                 |
     |                 |
     |                 |
     |                 |
     |                 |
     |                 |
     | a      b      c |
---(2,2)---(2.5,2)---(3,2)---
     |                 |
     |                 |

Böylece, köşeleri bu yarı tamsayı koordinatları olan ve kenarları girişteki boşluk olmayan karakterler tarafından belirlenen bir grafik oluşturabiliriz. |bağlandığı biçin e, /bağlanır aetmek fve \bağlandığı ciçin d. Grafiği daha sonra gezerken asla aşağı doğru hareket etmememiz için bunların kenarları yönlendirilmesi gerektiğini unutmayın. İçin _biz ya bir yol olabilir, bu nedenle teoride dört kenarları ihtiyacımız a -> b, b -> a, b -> c, c -> b. Ancak, önemli olan üç kenarlarına bu kısaltmak böylece her üç köşeleri içeren bir döngü var olduğunu olduğunu fark edebilirsiniz: a -> b, b -> c, c -> a.

Çünkü bu grafiği Bina Mathematica'da oldukça basit bir aslında olan noktaların bir grafik oluşturmak, böylece bir amacı, bir tepe olarak hareket edebilir olan koordinat çiftleri.

Son olarak, her tepe noktasına kökten ulaşılabildiğini kontrol ediyoruz. Kökün koordinatı, grafiğe eklediğimiz ilk tepe noktası olarak kolayca bulunur. Sonra tüm köşelere ulaşılıp ulaşılamayacağını kontrol etmenin en kısa yolu VertexOutComponent, kökün (yani kökten erişilebilen tüm köşe kümelerinin) grafikteki tüm köşe kümeleriyle aynı olup olmadığını kontrol etmektir.


1
300 bayt uzun olabilir, ancak tam olarak 300 çok tatmin edicidir!
Alex A.

2

Yakut 226227228

->i{w=i.index(?\n)+1
t=[i.index(/[^ _] *\n\z/)]
a=->x,c{(i[x]==c||i[x]==?_)&&t<<x}
((x=t.pop)&&(s=x-w;c=i[x])<?0?(a[s+1,?/];a[s,?\\]):c<?]?(a[s-1,?\\];a[s,?/]):c<?`?(a[x-1,?\\];a[x+1,?/]):a[s,?|]
i[x]=' ')while t!=[]
!i[/\S/]}

Çevrimiçi test: http://ideone.com/Z7TLTt

Program aşağıdakileri yapar:

  • Bir kökü arar (a \, /ya |son satırda)
  • o kökten başlayarak, kuralları kullanarak ağaca tırmanın ve ziyaret edilen her karakterin yerine bir boşluk koyun
  • Sonunda, dizemizin tamamen boşluktan (geçerli bir ağaç anlamına gelir) oluşup oluşmadığına bakın (geçersiz ağaç; tüm parçalar "ziyaret edilmedi")

İşte çözülmemiş:

F =-> input {
  row_size = input.index(?\n)+1

  root_coord = input.index /[^ _] *\n\z/

  # coordinates to process
  todo = [root_coord]

  add_todo = -> coord, char{
    if input[coord] == char || input[coord] == ?_
      todo << coord
    end
  }

  while todo.any?
    x = todo.pop

    next unless x # exit quickly if no root present

    case input[x]
    when ?|
      add_todo[x - row_size, ?|]
    when ?_
      add_todo[x - 1, ?\\]
      add_todo[x + 1, ?/]
    when ?/
      add_todo[x - row_size + 1, ?/]
      add_todo[x - row_size, ?\\]
    when ?\\
      add_todo[x - row_size - 1, ?\\]
      add_todo[x - row_size, ?/]
    end
    input[x]=' '
  end
  input.strip < ?*
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.