Doğrusallaştırılmış Bir Ağaç mı? (Genişlik Birinci Baskı)


11

Arka fon

Etiketsiz bir ağaç şöyle görünebilir:

   o
 / | \
o  o  o
|    / \
o   o   o

Bu ağacı doğrusallaştırmak için önce her düğümü oalt düğüm sayısı ile etiketliyoruz :

   3
 / | \
1  0  2
|    / \
0   0   0

ve sonra sayıları bir satırda ve soldan sağa olacak şekilde, önce nefes nefese bir şekilde yazın:

[3, 1, 0, 2, 0, 0, 0]

Bu, yukarıdaki ağacın benzersiz ve açık bir temsilidir, yani iki farklı saf ağacın aynı doğrusallaştırmaya sahip olmayacağı ve orijinal ağacı listeden yeniden oluşturabileceğimiz anlamına gelir.

Her ağaç belirli bir tamsayı listesine karşılık gelse de, her tamsayı listesi geçerli bir doğrusal ağacı [2, 0, 0, 0]temsil etmez : Örneğin geçerli bir ağacı temsil etmez, eğer doğrusallaştırmaya çalışırsak bu ağaçla sonuçlanırız

[2,0,0,0] -> 2 [0,0,0] -> 2 [0,0] -> 2 [0]
            / \          / \        / \
                        0          0   0

ama hala 0listede bir sol var ve koyacak hiçbir yer yok. Benzer şekilde [2, 0], doğrusal olmayan ağaç boş bir alt noktaya sahip olduğundan, geçerli bir ağaç doğrusallaştırma da değildir:

  2
 / \
0

Görev

Bir tamsayı listesi verildiğinde, olabildiğince az bayt kullanarak bir ağacın geçerli bir doğrusallaştırması olup olmadığına karar verin. Tam bir program veya işlev yazabilirsiniz.

Girdi: Negatif olmayan tam sayıların boş olmayan bir listesi.

Çıktı: Liste bir ağacın doğrusallaştırılmasıysa doğruluk değeri, aksi halde bir yanlış değer.

testcases

Doğru
[0]
[2, 0, 0]
[1, 1, 1, 1, 1, 0]
[3, 1, 0, 2, 0, 0, 0]
[2, 0, 2, 2, 0, 0, 2, 0, 0]
[3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0]
[1, 5, 3, 0, 2, 1, 4, 0, 1, 0, 0, 2, 1, 0, 0, 1, 1, 0, 0, 0, 0, 2, 1, 0, 0, 1, 0]
Falsy
[0, 1]
[2, 0]
[2, 0, 0, 0]
[1, 0, 1]
[3, 2, 1, 0]
[2, 0, 0, 2, 0, 0]
[4, 1, 0, 3, 0, 0, 0, 0]
[4, 2, 0, 3, 1, 0, 0, 0, 0, 0]

Yanıtlar:


4

Haskell, 44 bayt

f[n:k]=iterate f[k]!!n
f _=[]
g x=f[x]==[[]]

gListe alan ve bir boole döndüren bir işlevi tanımlar . Tüm test senaryolarını geçtiğini görün .

açıklama

Bu, önce derinlik ve ilk genişlik doğrusallıklarının aynı dizileri ürettiğine dayanır. Ayrıntılar için Martin'in cevaplarına bakın; temel olarak ikisi de dizide aynı aritmetik koşulu verir.

Bu işleve f, tek bir listede sarılmış giriş listesi verilir. nListeden bir sayı çıkar , sonra nda atlanan düğümün alt öğelerini (önce derinlik) işlemek için kalan listeye kendini çağırır . []Hata listesi olarak kullandığım boş listeyi açtığımda ortaya çıkıyor. İşlev g, son sonucun, [[]]işlenmemiş düğüm içermeyen benzersiz hatalı olmayan durum olduğunu kontrol eder . Haskell zayıf yazıldıysa, sadece 0hata durumu olarak kullanabilirim ve girişi başka bir listeye sarmak zorunda kalmazdım.


3

Mathematica, 38 bayt

Last@#<0<=Min@Most@#&@Accumulate[#-1]&

Temel fikir, doldurulacak birkaç düğümü takip etmemizdir. Listedeki her öğe bir düğümü kullanır ve alt öğesi ekler. Böylece her eleman itoplam sayıyı değiştirir i-1. Bu sayı birer birer kapalıdır, çünkü 1(kökten) başlamalı , değil 0.

Ağacın geçerli olması için a) 0liste boyunca asla aşağıya inemeyiz, çünkü mevcut düğümü yerleştirmek için hiçbir yere sahip olmazdık ve b) sonunda -1bitirmeliyiz, aksi takdirde kullanılmayan düğümler kaldı.

Kalan düğümlerin bu çalışan toplamını elde ederiz Accumulate[#-1](giriş listesinin önek toplamlarını eksi bir hesaplar). Ve sonra son elemanın ve sadece son elemanın -1:

Last@#<0<=Min@Most@#

Son öğenin negatif olup olmadığını kontrol etmenin yeterli olduğuna dikkat edin, çünkü asla daha fazla azaltamazız 1, bu nedenle son değerler -2veya daha düşükse, minimum değer için diğerlerinin negatif olmaması imkansız olacaktır.


2

Retina , 29 bayt

\d+
$*
^(?<-1>(1)*,)*$(?(1)!)

Çevrimiçi deneyin! (İlk satır, satır besleme ile ayrılmış bir test paketini etkinleştirir.)

açıklama

Temel fikir, Mathematica cevabımla aynıdır : kalan toplam düğümleri takip ediyoruz, asla sıfırın altına düşmediğinden emin olun, ancak sıfırla bitiyor. Bununla birlikte, bunun regex ile uygulama şekli çok farklıdır.

\d+
$*

Bu, girişi tekli nhaline getirir ve her tamsayıyı n1 saniyeye dönüştürür .

^(?<-1>(1)*,)*$(?(1)!)

Gerçek sihir burada gerçekleşir. Sadece geçerli ağaçlarla eşleşen oldukça kısa bir regex, ancak mekanik oldukça ince.

Regex içindeki yığınlarla çalışmanın bir yolu olan düğüm sayısını takip etmek için dengeleme grupları kullanıyorum .

İlk olarak, elbette böyle bir yığın asla negatif derinliğe sahip olamaz, bu yüzden -1Mathematica çözümünde yaptığımız gibi sonunda bir temsil ile sonuçlanamayız . Ancak, giriş nihai eleman olduğuna dikkat edebilirsiniz sahip geçerli bir yığın üzerinde sıfır olması (aksi takdirde biz ile bitirmek could not -1). Hem sıfırda hem de sıfır düğümle sonlandığımızı kontrol etmek için aslında bayt tasarrufu sağladığı ortaya çıkıyor .

İşte normal ifadenin dökümü:

^        e# Anchor the match to the beginning of the string.
(?<-1>   e# Each repetition of this group will match one number. 
         e# We can ignore the <-1> for now.
  (1)*   e#   Match each unary digit of the current number, pushing
         e#   a capture onto stack 1. This increments our total of
         e#   remaining nodes by 1 for each child.
  ,      e#   Match a comma. Note that this requires that there is at
         e#   least one more number in the list.
)*       e# At the end of the repetition the <-1> pops one capture from
         e# the stack. This is the node that the current number itself
         e# takes up.
$        e# Match the end of the string. This requires the input to end
         e# in a zero, because the last thing we matched was a comma.
(?(1)!)  e# Make sure that stack 1 is empty, so that we don't have any
         e# unused nodes.

1

CJam (20 bayt)

{X0@{+\(_0>{\}*}/|!}

Çevrimiçi test paketi . Bu, yığında bir dizi alan ve yığında 0 veya 1 bırakan anonim bir bloktur.

teşrih

Sahte kodda bu:

p = 1
q = 0
foreach (i in input):
  q += i
  if (--p <= 0):      # in practice, if (--p == 0):
      p, q = q, p
return (p | q) == 0   # i.e. p == 0 && q == 0

qağaçtaki geçerli seviyede düğümlerin etiketlerinin toplamını biriktirir; pgeçerli seviyede kalan düğümleri geri sayar.


{X0@{+\(_{\}&}/|!}Bence?
Martin Ender

Ayrıca önlemek için tam bir program kullanarak bir bayt kaydetmek gerekir gibi görünüyor @.
Martin Ender

1

Labirent , 17 bayt

(
+?
;-)
,_"
@@,!

Çevrimiçi deneyin!

Gerçek çıktı -1ve yanlış çıktı boş. Labirent'te doğruluk ve sahtelik tanımlamak biraz zordur, çünkü Labirent'in dalları esasen üçlüdir. Ancak, güvenilir bir şekilde iki dalı olan bir koşul oluşturmanın tek yolu, sadece bunu yapabilirsiniz:

>"F
 T

Bu durumda, düz bir falsiye geçmeyi (çünkü hareketin yönü etkilenmediğinden) ve gerçeğe dönüştüğünü düşünürdüm. Bunlar sırasıyla sıfıra ve sıfıra karşılık gelmez. Sıfırı temsil etmek için boş bir çıktı kullanmamın nedeni, çıktıyı başka bir Labirent programına geri bağlayacak olmanız ?durumunda, giriş boşsa giriş operatörünün aslında bir sıfıra basmasıdır, bu nedenle boş dizeyi geçerli sayıyorum sıfır gösterimi.

açıklama

Algoritma hala Mathematica ve Retina cevaplarımdakiyle aynı, ancak Labirent'in kontrol akışı nedeniyle, bu sefer biraz farklı çalışıyor:

  • Burada toplam sayaçla tek tek çalışmıyoruz. Bunun yerine a) negatif bir sayaçla çalışıyoruz ve b) başlangıçta -11başlangıç olarak ayarlıyoruz, böylece sayacın liste boyunca negatif olmasını ve son girişte sıfıra ulaşmasını istiyoruz. Bu aslında buradaki kontrol akışını basitleştirir.
  • Tam listeyi oluşturmak ve yanlış değeri içerip içermediğini kontrol etmek yerine, üç olası sonlandırma koşulu vardır:

    1. Toplam sıfıra ulaşmadan önce EOF'a ulaştık. Bu durumda kullanılmayan düğümler kalır ve hiçbir şey yazdırmayız.
    2. Sıfıra ulaşıyoruz ve EOF'dayız. Bu durumda, geçerli bir ağacımız var.
    3. Sıfıra ulaştık ve henüz EOF'da değiliz. Bu durumda, tüm öğeleri örtmeden önce düğümlerimiz bitti ve hiçbir şey yazdırmıyoruz.

Gerçek koda gelince, sol üst köşeden başlıyoruz. (Bir içine yığının tepesinde kapalı sıfır döner -1çalışan toplamı olacaktır. Daha sonra programın çok sıkı ana döngüsüne giriyoruz +?-)"_,;+:

+   Add the top two values. This does nothing on the first iteration,
    but gets rid of a helper-zero on subsequent iterations.
?   Read and push integer.
-   Subtract it from running total.
)   Increment.
"   No-op. There is a branch at this point. If the running total is zero,
    we move straight ahead onto the , (see below). Otherwise, the loop continues.
_   Push a zero. This is necessary to prevent the IP from turning south.
,   Read a character. This will either be the next separator (some positive
    number) or EOF (-1). If it's EOF, the IP turns south and the program
    terminates. Otherwise, the loop continues.
;   Discard the separator.

Bu sadece bir noktada toplamı sıfıra indirdiğimiz durumları bırakır. IP sağ alt tarafa doğru hareket eder ,ve EOF'a ulaşıp ulaşmadığımızı kontrol etmek için başka bir karakter okur. Değilse, değer pozitif olur ve IP batıya doğru döner @ve program sona erer. Biz ulaşmak EOF yaptıysak, IP doğuya yönelerek, yazdırır -1ile !. IP daha sonra @programı sonlandırmak için biraz garip bir yolla sol alt tarafa doğru yol alacak .


0

Python, 82 bayt

lambda l:len(l)==sum(l)+1 and not any(list(l[x]>=len(l)-x for x in range(len(l))))

Daha fazla test vakasına ihtiyacınız var.


Bu listen azından Python 2 ise döküm yapmanıza gerek yoktur ve ikinci koşulu yeniden düzenleyerek ve ters çevirerek 70 bayta alabilirsiniz:lambda l:all(l[x]<len(l)-x for x in range(len(l)))and len(l)==sum(l)+1
Kade

^ Buna bağlı olarak, vücudun değiştirebilir allolmak x<len(l)-y for y,x in enumerate(l)68'e almak için başka 2 bayt kaydetmek için
Kade

Bunu daha fazla golf oynamıyorum çünkü bunun doğru bir çözüm olduğunu düşünmüyorum. İpuçları için teşekkürler.
Sparr

0

Pyth, 13 bayt

qxsM._tMQ_1tl

Giriş gösterimindeki tüm noktalarda ağacın mevcut dolgunluğunu hesaplayarak başlıyoruz. Fikrin bu kısmı büyük ölçüde Martin Ender'den ödünç alındı, bu yüzden onun sayesinde.sM._tMQ

Bu listeye sahip olduktan sonra, -1( x..._1) içeren ilk dizinin giriş eksi bir ( q...tl(Q)) uzunluğunu kontrol ediyoruz .

Çalıştığına inanmıyor musunuz? Kendin dene!

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.