Izgarayı üçgenlere bölme


18

Hedef

Bu zorluğun amacı, üçgenin tüm köşe noktalarının ızgara noktalarında olduğu ızgarayı üçgenlere nbölmenin yol sayısını hesaplayan bir işlev üretmektir n X 1.

Misal

Örneğin, 2 x 1 ızgarasını bölmenin 14 yolu vardır, bu nedenle f(2) = 14bölümlerin 2 x 1 bölmeler sırasıyla 2, 2, 2, 2, 4 ve 2 farklı yönlendirmeye sahip olduğu aşağıdaki bölümler aracılığıyla .

puanlama

Bu , bu yüzden en kısa kod kazanır.


10
Bazı ek test senaryoları faydalı olabilir, bu nedenle gönderimlerimizin doğru olduğunu doğrulayabiliriz.
AdmBorkBork

8
Dejenere olmayan üçgenler belirtmek isteyebilirsiniz .
Arnauld

1
Bu yorumu yansıtacak şekilde OEIS A051708 dizisinde düzenlemeler yaptım .
Peter Kagey

Yanıtlar:


2

05AB1E , 13 bayt

·LÉœÙεÅγo;P}O

Port @Bubbler 'in Jelly cevap .

Yerleşik permütasyonlar nedeniyle çok yavaş.

Çevrimiçi deneyin veya ilk dört girişi doğrulayın .

Açıklama:

·                # Double the (implicit) input
 L               # Create a list in the range [1, doubled_input]
  É              # Check for each if they're odd (1 if truthy, 0 is falsey)
                 # We now have a list of n 0s and n 1s (n being the input)
   œ             # Get all permutations of that list
    Ù            # Only leave the unique permutations
     ε     }     # Map each permutation to:
      Åγ         #  Run-length encode the current value (short for `γ€g`)
        o        #  Take 2 to the power for each
         ;       #  Halve each
          P      #  Take the product of the mapped permutation
            O    # Sum all mapped values together (and output implicitly)

19

Haskell , 60 55 54 52 bayt

Bir çizim ve programlamanın bir çok örneğinden sonra, bunun kalelerin problemiyle aynı olduğu bana geldi:

On bir (n+1)x(n+1) satranç tahtası, bir kale gitmek için kaç yolu vardır (0,0) için (n,n) sadece sağ hareket ettirerek +(1,0) veya yukarı +(0,1) ?

Temel olarak 1xn ızgarasının üst ve alt satırına sahipsiniz . Şimdi yatay olmayan çizgiyi doldurmalısınız. Her üçgenin yatay olmayan iki çizgisi olmalıdır. Kenarlarından birinin üst veya alt çizginin bir parçası olup olmadığı, kale sorununda gideceğiniz yöne ve uzunluğa karşılık gelir. Bu OEIS A051708 . Bu yazışmanın bir örneği olarak aşağıdaki örnekleri göz önünde bulundurun. Burada üst çizgi yukarı hareketlere karşılık gelirken, alt çizgi sağ hareketlere karşılık gelir.

-6 bayt için @PeterTaylor ve -2 bayt için @PostLeftGarfHunter teşekkürler!

b 0=1
b 1=2
b n=div((10*n-6)*b(n-1)-9*(n-2)*b(n-2))n

Çevrimiçi deneyin!


İlk birkaç değerle arayarak OEIS dizisini buldum. Neden eşleştiğine dair güzel bir açıklama. Bu alternatif kombinatoryal yorum hakkında yorum eklemek için bunu düzenlemek ister misiniz? Değilse, yapabilirim.
Peter Taylor

BTW indekslemeyi ayarlamanız gerekiyor, çünkü burada doğru cevap A051708(n+1). Bu yüzden ilk doğru cevabı gönderdim :-P
Peter Taylor

Üst ve alt kenarları olan üçgenler yukarı veya sağ hareketlere karşılık gelecek şekilde kale hareketlerini üçgenlere götürürüm?
Neil

@PeterTaylor Lanet, hatamı gösterdiğin için teşekkürler :)
flawr

5
@Neil Grafiksel bir açıklama ekledim.
flawr

8

Haskell , 42 bayt

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

Çevrimiçi deneyin!

2'den fazla değişkeni geri alan oldukça doğrudan bir uygulama.

Bu çözümü nasıl elde edebileceğimiz aşağıda açıklanmıştır. Doğrudan özyinelemeli formül uygulayan kodla başlayın:

54 bayt

0%0=1
a%b=sum$map(a%)[0..b-1]++map(b%)[0..a-1]
f n=n%n

Çevrimiçi deneyin!

Kullanılması flawr en kale hareket yorumunu , a%bgelen kalesini almak yolların sayısıdır (a,b)için (0,0)kullanarak, sadece bir koordinat azalma taşır. İlk hareket azalır aveya azalır b, diğeri aynı kalır, böylece özyinelemeli formül.

49 bayt

a?b=sum$map(a%)[0..b-1]
0%0=1
a%b=a?b+b?a
f n=n%n

Çevrimiçi deneyin!

map(a%)[0..b-1]++map(b%)[0..a-1]İki yarının aynı olduğunu ave bdeğiştirildiğini belirterek tekrardan kaçınabiliriz . Yardımcı çağrı a?bilk hareketin azaldığı yolları sayar ave böylece ilk hareketin azaldığı yolları b?asayar b. Bunlar genel olarak farklıdır ve eklerler a%b.

Özetleme, a?bliste kavrayışı olarak da yazılabilir a?b=sum[a%i|i<-[0..b-1]].

42 bayt

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

Çevrimiçi deneyin!

Son olarak, biz kurtulmak %ve sadece açısından özyinelemeye yazma ?değiştirerek a%iile a?i+i?aözyinelemeli arama.

Yeni temel durum , bunun 49 baytlık versiyonun ?iki katı çıkış vermesine neden oluyor ?, çünkü sahip 0?0=1olacağız 0%0=0?0+0?0=2. Bu, tanımlamayı f n=n?nbaşka yapmamız gereken yarıya olmadan kullanalım .


49 baytlık çözümünüz yanıtımla aynı özyinelemeyi kullanıyor, ancak 42 baytlık çözümü henüz bulamadım. Bir açıklama iyi olurdu.
Peter Taylor

Önceki programlardan birinde de aynı yaklaşımı kullandığımı düşünüyorum: Fikir, sağdan sola yatay olmayan çizgiler oluşturarak tüm bölümleri oluşturmak (veya saymak). Dikey çizgiyle başlıyorsunuz. Sonra tekrar okuyabilirsiniz: Önceki satırın uç düğümlerinden birini alın ve bu satırdaki önceki tüm düğümlerin solundan daha uzak olan zıt yatay çizgideki bir düğüme bağlayın.
flawr

Operatör , üst satırdaki a%bdüğümleri ve alt satırdaki düğümleri kullanarak bölüm sayısını sayar . Alt düğüm zaten kullanımdaysa, operatör üst düğümden yeni bir satır eklemenin yollarını sayar . ( Tüm düğümlere bağlanabilirsiniz , ancak her biri için tekrarlamak zorundasınız.)0,1,...,a0,1,..,ba?baba[0,1,...,b-1]
Kusur

@flawr, anladığım 49 baytlık bu. O var ?bilmiyorum 42 bayt birinin ve ne özellikle merak ediyor o simetrik değil olmasıdır.
Peter Taylor

@PeterTaylor Karışıklık için üzgünüm, bir şekilde iki çözümü karıştırdım. İki çözümü birbirinden kolayca dönüştürebileceğimizi düşünüyorum: İlk adımda map...bir liste kavrayışı ile yer değiştirebiliriz , ikinci adımda şu tanımı ekliyoruz %:a?b=sum$map(a%)[0..b-1], a%b=a?b+b?a a?b=sum[a%i|i<-[0..b-1]], a%b=a?b+b?a a?b=sum[a?i+i?a|i<-[0..b-1]]
flawr

7

CJam (24 bayt)

{2,*e!{e`0f=:(1b2\#}%1b}

Çevrimiçi demo

Bu Bubbler'inn 0 ve n1'lerin permütasyonlarını toplama yaklaşımını kullanır .

teşrih

{         e# Define a block
  2,*     e#   Given input n, create an array of n 0s and n 1s
  e!      e#   Generate all permutations of that array
  {       e#   Map:
    e`    e#     Run-length encode
    0f=:( e#     Extract just the lengths and decrement them
    1b    e#     Sum
    2\#   e#     Raise 2 to the power of that sum
  }%
  1b      e#  Sum the mapped values
}

Alternatif yaklaşım (28 bayt)

{_1aa{_2$,f{j}@@,f{j}+1b}2j}

Çevrimiçi demo

teşrih

Üçgenlerin hepsinde bir yatay kenar ve yatay çizgileri bağlayan iki kenar vardır. Yatay olmayan kenarları iki x-kordunun bir demetiyle etiketleyin ve sözlükbilimsel olarak sıralayın. Daha sonra ilk kenar, (0,0)son kenardır (n,n)ve iki ardışık kenar, iki konumdan birinde tam olarak farklılık gösterir. Bu, memoised özyineleme işleci kullanarak uyguladığım basit bir özyineleme yapar j:

{            e# Define a block
  _          e#   Duplicate the argument to get n n
  1aa        e#   Base case for recursion: 0 0 => 1
  {          e#   Recursive body taking args a b
    _2$,f{j} e#     Recurse on 0 b up to a-1 b
    @@,f{j}  e#     Recurse on a 0 up to a b-1
    +1b      e#     Combine and sum
  }2j        e#   Memoised recursion with 2 args
}

Not

fjCJam'de ilk kez desteklenmek istemedim. Burada da skoru 24 bayta indirir. Belki bir yama yazmaya çalışmalıyım ...


Yay, seni 10 saniye geçirdim, hiç bu kadar yakın olduğumu düşünmüyorum :)
flawr

@flawr, bir diseksiyon yazmadan önce yayınlamayı düşündüm, ama hızlı bir şekilde nakavt etmek için zamanım olduğunu düşündüm. Sonra "Yeni cevap" gördüm, bu yüzden kısmi yazılı diseksiyonumu sildim, yayınladım ve düzenledim.
Peter Taylor

1
-5 bytes btw için teşekkürler: D
flawr

4

Jöle , 15 14 bayt

Ø.xŒ!QŒɠ€’§2*S

Çevrimiçi deneyin!

Peter Taylor'ın yorumuna göre -1 byte.

Sonuçta elde edilen formül yerine kusurun çizimini doğrudan kullanır .

Nasıl çalışır

Ø.xŒ!QŒɠ€’§2*S    Main link (monad). Input: positive integer N.
Ø.x               Make an array containing N zeros and ones
   Œ!Q            All unique permutations
      Œɠ€         Run-length encode on each permutation
         ’§       Decrement and sum each
           2*S    Raise to power of 2 and sum

Kare bir ızgarada mümkün olan her rotayı takip edin. L birimlerini kale olarak bir yönde hareket ettirmenin yolu sayısıdır 2**(L-1). Bunu her rotaya uygulayın ve her rotadan geçmenin yollarını toplayın.


Güzel yaklaşım. CJam'a taşıdığımda, uzunlukları, toplamı azaltmak ve sonra 2'yi toplamına yükseltmek daha kısaydı; 2'yi uzunluğa yükseltmek, yarıya indirmek ve daha sonra çoğaltmak yerine. Size bir bayt tasarruf edip etmeyeceğini bilmiyorum.
Peter Taylor

3

Kömür , 44 31 bayt

çarpı 44 hala düzenli 44

F⊕θ«≔⟦⟧ηF⊕θ⊞ηΣ∨⁺ηEυ§λκ¹⊞υη»I⊟⊟υ

Çevrimiçi deneyin! Açıklama: Zıt taraf uzunluklarındaki bir yamuğun m,n, tamsayı ofsetleri üzerinde bulunan üçgenlere bölünme yollarının sayısını hesaplayarak çalışır . Bu sadece nsorudaki boyut dikdörtgeninin genel bir durumudur . Bölmeler sayısı tüm taraf için bölümlerin sayıların toplamları olarak yinelemeli verilir m,0..n-1ve n,0..m-1. Bu, kayaların genel sorununa ( OEIS A035002) eşdeğerdir . Kod basitçe , daha önce hesaplanan değerleri kullanmaya devam ederken 0,0kadar çalışan bölüm sayısını n,nhesaplar.

F⊕θ«

Satırların üzerinden geçin 0..n.

≔⟦⟧η

Boş bir satırla başlayın.

F⊕θ

Satırdaki sütunların üzerinden geçin 0..n.

⊞ηΣ∨⁺ηEυ§λκ¹

Şimdiye kadar olan satırı ve geçerli sütundaki önceki satırlardaki değerleri alın ve toplam toplamı geçerli satıra ekleyin. Ancak, hiç değer yoksa 1toplamın yerine ikame edin.

⊞υη»

Bitmiş satırı şimdiye kadar satır listesine ekleyin.

I⊟⊟υ

Hesaplanan son değeri çıktılar.




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.