Engel kursum ne kadar çeşitli?


21

Arka fon

Dikdörtgen bir odaya kutular yerleştirerek basit bir engel kursu kurdum. Şimdi, çözülebileceği esasen farklı yolların sayısını saymak istiyorum. Bana bunun için bir program yazmanı istiyorum.

Giriş

Girişiniz, karakterlerin boş olmayan dikdörtgen bir dizisidir .#. Noktalar .boş alan ve #engeller.

Engel rotasından geçen bir yol sol üst köşede başlar ve sağ alt köşede sona erer ve yalnızca sağa veya aşağı doğru gider. Ayrıca, geçerli bir yol bir engelden geçemez. +Karakterlerle çizilen bazı örnekler :

Valid path  Invalid path  Invalid path  Invalid path
++........   ++........    +++++.....    ..+.......
.++++++#..   .+.....#..    ....+++#++    ..++...#..
......+#..   .+.++++#..    .......#.+    ...+++.#..
....#.++++   .+++#.++++    ....#....+    ....#+....

İki yollardır esas olarak benzer 1 tek tek hareket ettirerek başka transforme edilebilir, eğer +her seferinde. Ara yollar da geçerli olmalıdır, bu nedenle bir engelin üzerinden bir yolu bükemezsiniz. Örneğin, buradaki ilk iki yol esasen birbirine benziyor, ancak üçüncüsü, esasen onlardan farklı, çünkü iki engelin üzerinden geçirilemiyor:

++........   +.........   +++++++++.
.+++++.#..   ++.....#..   .......#+.
.....+.#..   .++++++#..   .......#++
....#+++++   ....#.++++   ....#....+

Çıktı

Çıktınız, engel kursu boyunca esasen farklı yolların sayısıdır. Başka bir deyişle, tüm geçerli yollar temelde benzer yolların sınıflarına ayrılırsa, çıktı sınıfların sayısıdır. Geçerli bir yol yoksa, bu sayının 0 olabileceğini unutmayın.

Kurallar ve puanlama

Tam bir program veya bir fonksiyon yazabilirsiniz. En düşük bayt sayısı kazanır ve standart boşluklar izin verilmez. Programınızı göndermeden önce her sınav durumunda değerlendirmeniz gereken durumlar dışında hiçbir zaman sınırı yoktur.

Test durumları

....
....
.... => 1

...#
....
...# => 0

#..#
..#.
.... => 0

......
......
..##..
......
...... => 2

......
...#..
......
..#...
#..... => 3

......
..#...
......
....#.
#..... => 4

.......
##.....
....###
...#...
..##.#.
#....#.
..#.... => 0

......#.
..##....
...#....
.......#
....#...
.##...#.
....#...
##...... => 7

.........
.#.#.#.#.
.........
#.#...#.#
.........
.#.#.#.#.
......... => 17

..........
.#........
..........
.....#....
#.........
........#.
......#...
.......... => 10

.........
.#.......
.........
...#.....
.........
.....#...
.........
.......#.
......... => 16

1 Doğru teknik terim "homotopik" dir .


1
"Her seferinde bir tane taşıyarak+ " derken ne demek istiyorsunuz ? Bu, esasen benzer yolların aynı uzunlukta olması gerektiği anlamına mı geliyor?
Peter Taylor

3
@PeterTaylor Tüm yollar aynı uzunluktadır, çünkü yalnızca aşağı ve sağa gidebilirler. "Birini hareket ettirerek +" ile, esasen yolun bir köşesinin ters yönün bir köşesine ters çevrildiği anlamına gelir.
Zgarb

1
@Peter: Yalnızca sağa veya aşağıya gidebileceğiniz için, tüm yollar aynı uzunluktadır.
Deusovi

Yanıtlar:


8

Salyangoz , 53 49 bayt

A^
\.+d!{.l\.+a3(.|~c!~}\.+r!(.u\.+e(.|~},\.,=~d~

Bir kere tdehşet verici ışınlanma talimatını kullanmak zorunda değildim . Sonuç olarak, test durumları bir kez almak yerine anında sona erer.

Ungolfed:

A^
r\.+
{
    d\.+
    !{ r\.u \.+ a3 (.|~)}
    r\.+
    !{ d\.l \.+ a3 (.|~)}
},
d\.,
!(dr .)

Seçenekler A^sol üst köşeden başlamak ve eşleşen tüm yolları saymak anlamına gelir. Ana fikir, yollar için bir kanonellik durumunu kontrol etmektir. Dürüst olmak gerekirse, çalışmasını beklemiyordum, ama test davalarını çiviledi, yani .... Kontrol etmeye çalıştığı şey şu anki yol içinde, en çirkin yolun seçildiği, yani mümkün olduğunca çok doğru gittiği. engelleri aşmadan, mümkün olduğunca çok sayıda, vb. Bu, sağa 1 veya daha fazla kez hareket ettikten ve daha sonra 1 ya da daha fazla kez aşağıya indikten sonra, bir sonraki kareye (sağa doğru olması gereken) bir önceki sağa doğru bir kez daha sağa gidildiğinde ulaşılamayacağını kontrol ederek yapılır. Benzer durum sağa ve aşağıya hareket ettikten sonra da kontrol edilir.


iş için doğru dil hakkında konuşun!
Charles

10

Python 2, 170 131 112 bayt

def f(C,t=1):i="#".join(C).find("#")+1;return([]<C)*(i<1or(i<t
and f([r[i:]for r in C],t-i))+(i>1)*f(C[1:],i-1))

fEngel kursunu satır listesi olarak alan ve temelde farklı yolların sayısını döndüren bir işlev .

açıklama

Temel kavram şudur: O ve sol üst köşede sınırlama yapan başka bir engel bulunmayacak şekilde belirli bir engel seçeriz, o .

+--+....
|..|....  
+--#<==== o
.....#..
.#......
........

Sonra doğuya ve güneyindeki iki alt kursları düşünün o . Yoksa size ya bu alt kurslarının düşünün o aslında batıdan doğuya almak için kuzeyden geçti ve geçildiği onlara yönlendireceğini güneye almak için o bir yönden geçilebilmektedir. Problemi seçilen alt kursların her biri için çözüyoruz ve sonuçların toplamını döndürüyoruz. Bu sayılar , sırasıyla soldan ve sağdan o geçiş yaparken esasen farklı yolların sayısına karşılık gelir , bu nedenle sonuçta ortaya çıkan iki yol grubu esasen farklıdır. Başlangıç ​​noktası ve o arasında hiçbir engel olmadığından, başlangıç ​​noktası ile bu bölgelerin her birine girilen herhangi bir giriş noktası arasında bir yol vardır ve aynı noktaya giden tüm bu yollar esas olarak benzerdir, bu nedenle yukarıdaki toplam, tüm kurstaki temelde farklı yolların tam sayısıdır.

                               A
_
........       ...|////      |....
........       ...|////      |....
...#....  -->  ...#////  -->  ....
.#....#.       .#..//#/       ..#.
........       ....////       ....

   |                           |
   v                           v
                  B
........       ___
........       .#....#.
___#....  -->  ........  -->   +
/#////#/       
////////       

İşler, yalnızca engel kursunun ihtiyaç duyulan tüm bilgileri iletmemesi gerçeğiyle biraz karışıktır. Örneğin, yukarıdaki şekildeki B dersini düşünün . Kendi başına ele alındığında, engellerin her birinin kuzeyden geçip geçemeyeceğini belirleyemiyoruz. Eğer B giriş rotası olsaydı , o zaman tüm yollar sol üst köşeden başladığından beri, hiçbir engel kuzeyden geçemezdi, fakat, o , doğudan o çizgiyi geçerken sol engelin her iki tarafından B'ye ulaşabildiğimiz için Bu sorunu, rotayı çözerken kuzeyden geçilebileceğini düşünmeliyiz; aynı şey, bu yönden geçilemeyen doğru engel için geçerli değildir.

Bu ekstra bilgiyi, engel kursu ile birlikte, soldan başlayarak, yolun başlayabildiği ilk satırdaki karakter sayısını belirleyerek düzenleriz. Yukarıdaki şemada, bu, her bir kursun yanındaki kesintisiz çizgi olarak gösterilmiştir. Teknik olarak, A dersinde olduğu gibi, yolun başlayabileceği ilk sütun boyunca karşılık gelen karakter sayısını da belirtmemiz gerekirken, A dersinde olduğu gibi, pratikte her zaman en yüksek engeli seçtik, bu yüzden bu bilgi gerekli değil .

Fiili o seçimi şu şekildedir: Her satırın, sonuncusu hariç, onu takip eden bir engel (örneğin #buna eklenmiş) olduğunu ve sonuçtaki derste ilk sırayı okuma sırasını seçtiğini iddia ediyoruz. Başlangıçta hiçbir engeli olmayan satırlar (sonuncusu hariç) için, bu etkili bir şekilde onları atlayacağımız anlamına gelir (aşağıdaki yolun üst sıradaki herhangi bir karakterden başlayabildiğine dikkat ederek). Sonunda, sadece tek bir olası yolu olan, engelleri olmayan tek bir sıraya sahip olan bir kursla son buluruz.


Bu hemen hemen düşündüğüm bir çözüm. Bir şansım olmadan birinin göndereceğini biliyordum.
quintopia

6

CJam, 85 84 82 81 80 79 bayt

qN/:Q,(Qz,(:R_T]2/e~e!{'#Qs@{\(\@>}%s-},{_}{(a\L{@+_@\-_{2$\f.=0fe=2&},}h;}w;],

Çevrimiçi deneyin. Veya test takımının tamamını çalıştırın.

Bu çözümün verimliliği muhtemelen oldukça korkunçtur ancak her test durumunu birkaç saniye içinde çözer.

açıklama

Kodun tamamını daha sonra ekleyeceğim, ancak algoritmik fikir şudur:

  • Izgara genişliğini ve yüksekliğini sırasıyla Wve Hbırakın.
  • Olası tüm yolları, W-1kopyalarının 0ve H-1kopyalarının farklı izinleri olarak oluştururuz W-1(burada 0yatay bir adım ve W-1dikey bir adım temsil eder ). Kılavuzun ilk elemanını tekrar tekrar alarak ve ardından stepokuma sırasına göre hücreleri atlayarak ( stepbu 0veya nerede W-1) tüm bu yolları izleriz . A içeren tüm yolları atıyoruz #.
  • Ardından, benzer yollardan bir grubunu tekrar tekrar kaldırırız (bu, kalan yolların ilki ile aynı olan tüm yollar olacaktır). Benzer yolları kontrol etmek biraz daha kolay hale getirerek durumu biraz daha kolaylaştırıyor: birinin xhareket edip etmediğini kontrol etmek yerine , yolların tam olarak iki yerde farklılık gösterip göstermediğini kontrol ediyoruz. Bu durumda, bu iki yer dikey ve yatay bir hareketi değiştirilmiş olacak. Bu, bu hareketler arasındaki tüm segmentin bir hücre tarafından çapraz olarak kaydırılmasına neden olur. Ancak, bu iki yol da geçerliyse, yolun herhangi bir bölümünü bir hücre tarafından çapraz olarak kaydırmak bir engeli geçemez, bu yüzden benzerdirler. Geçişli kapatmayı bulmamız gerekiyor, bu yüzden bir sonraki gruba geçmeden önce benzer yollar bulana kadar bunu yapmaya devam ediyoruz.
  • Sonunda, bulduğumuz grupları, yığının altında bıraktığımız sayımı yaparız.
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.