Heyelanı Tahmin Et


22

Heyelanlar

Bu zorlukta, işiniz büyük bir heyelanın neden olduğu zararın derecesini tahmin etmektir. İlk yükseklik h >= 0 ve kritik bir katsayı ile parametrelenmiş, aşağıdaki basitleştirilmiş iki boyutlu modeli kullanıyoruz c > 0. Yükseklikten bir uçurum ile başlarsınız hve arazinin tamamen sola ve sağa doğru tamamen düz olduğu varsayılır. Çünkü h = 6durum şöyle gözüküyor:

##########
##########
##########
##########
##########
##########
-----------------------

-Taşınmaz kaya, ve #stabil olmayan topraktır. İki komşu sütun arasındaki yükseklik farkı daha fazlaysa c, bir heyelan meydana gelir: csol sütundan toprağın üst birimleri c, sağdaki bir sonraki sütuna doğru düşer , her biri. Şekildeki en boş olmayan sütun için kararsızdır c = 2, bu nedenle bir heyelan tetiklenir:

#########
#########
##########
##########
##########
############
-----------------------

Sütun hala kararsız, bu da ikinci bir toprak kaymasına neden oluyor:

#########
#########
#########
#########
############
############
-----------------------

Şimdi, solundaki sütun dengesiz hale geldi, bu yüzden orada yeni bir heyelan tetiklendi:

########
########
#########
###########
############
############
-----------------------

Bundan sonra, uçurum tekrar kararlıdır. Bu model hakkında güzel olan şey, toprak kaymalarının işlenme sırasının önemli olmamasıdır: sonuç aynıdır.

Görev

Programınıza tamsayı parametreleri hve cgirdiler (sipariş önemli değil, ancak cevabınızı belirtmelisiniz) verilir ve heyelanın etkilediği toplam sütun sayısını vermelidir . Bu, yüksekliği kesin olarak 0ve arasında olan ortaya çıkan sabit uçurumdaki sütun sayısı anlamına gelir h. Yukarıdaki örnekte, doğru çıktı 4.

Tam bir program veya bir fonksiyon yazabilirsiniz. En düşük bayt sayısı kazanır ve standart boşluklar izin verilmez.

Test Kılıfları

Bunlar formatta verilmiştir h c -> output.

0  2  -> 0
2  3  -> 0
6  2  -> 4
6  6  -> 0
10 1  -> 10
15 1  -> 14
15 2  -> 11
15 3  -> 6
40 5  -> 16
80 5  -> 28
80 10 -> 17

Yanıtlar:


5

CJam, 62 57 bayt

Görebildiğim kadarıyla, bu çözümü Aditsu'nun cevabından uygulamak için tamamen farklı bir yaklaşım.

q~:C;:HaH)*H){(:I\_@>2<:-C>{I0a*C~)+C1a*+]z1fb_,}I?}h-H-,

Giriş şeklinde gider h c

Örnek:

80 5

Çıktı:

28

Nasıl çalışır

Mantık, kod boyutunu küçültmek için kullanılan birkaç püf noktası ile oldukça açıktır.

  • Yol h + 1( + 1için h = 0, her elemanı olan uzunluk dizisi durumda) htepeden temsil etmek için
  • Bu dizinin en sağındaki dizinden yinelemeye başla
    • Geçerli dizinden iki öğenin değerinden daha farklı olması durumunda c
      • cGeçerli dizin öğesinden kaldır
      • Dizinin 1sonraki cöğelerine geçerli dizinden ekle
      • Geçerli dizini bu yeni dizinin uzunluğuna eşit yapın
      • Bu, taşları ilk önce mevcut dizinin sağına sabitlediğimizden emin olmamızı sağlar
    • başka, geçerli dizini azalt
  • En endeksi sola bastığımızda, bitişik tüm indekslerin cfarklılıktan daha küçük veya eşit olmasına dikkat ediyoruz
  • Dizideki herhangi bir değeri 0veya hdeğeri kaldırın ve uzunluk kazanın.

Kod genişletme

q~:C;:HaH)*H){(:I\_@>2<:-C>{I0a*C~)+C1a*+]z1fb_,}I?}h-H-,
q~:C;:HaH)*H)
q~:C;:H                  "Read the input, evaluate it, store height in H and coeff. in C";
       aH)*              "Wrap the height number in an array and repeat it H + 1 times";
           H)            "Put H+1 on stack, representing the current index of iteration";
{(:I\_@>2<:-C>{I0a*C~)+C1a*+]z1fb_,}I?}h
(:I\_@>2<:-C>
(:I                      "Decrement the current index and store it in I";
   \_                    "Swap to put array on top and make 1 copy";
     @>2<                "Get the two elements starting from Ith index";
         :-              "Get the difference. The best part of this approach is that";
                         "For the right most index, where there is only element, it";
                         "returns the element itself, which is the expected difference";
           C>            "Check if difference is greater than C";
{I0a*C~)+C1a*+]z1fb_,}   "This block will be executed when the difference is more than C";
 I0a*                    "Get an array of I length and all elements 0";
     C~)+                "Get -C value and append it to the above array";
         C1a*+           "Get C length array of 1s and concat with the above array";
              ]          "Wrap the two arrays, the cliff and the above one in an array";
               z1fb      "Transpose to get number pairs and add those pairs. For example";
                         "If we are at the right most index with H = 80 and C = 5,";
                         "The right section of the cliff looks like:";
                         "[ ... 80 80 80 80 80] and the array created in above step";
                         "looks like [ ... 0 0 0 0 -5 1 1 1 1 1]. After z, we have:";
                         "[ ... [80 0] [80 0] [80 0] [80 0] [80 -5] [1] [1] [1] [1] [1]]";
                         "After 1fb we get [ ... 80 80 80 80 75 1 1 1 1 1]";
                   _,    "Take a copy of the above resultant array and take its length";
I?                       "If difference was not greater than C, put I on stack";
                         "Now we either have the decremented index or new array length";
                         "on stack."
{ ... }h                 "This is a do while loop which makes sure that we iterate to";
                         "the left of the array. This loops runs till the top stack";
                         "element is 0 while not popping the top element";
        -H-,             "After the loop, we have the final cliff array and 0 on stack";
                         "Remove any 0 elements from the array, then remove any H";
                         "elements from the array and then take length to get the";
                         "number of columns which were modified";

Burada çevrimiçi deneyin


Tekrar
foiled

Yine @aditsu?
Doktor

Biri beni CJam'da ilk defa dövmez. Ve bunu ilk yaptığınız zaman da değil, daha önce doğrudan rekabette yaptınız mı emin olmasanız da.
aditsu

Heh :) Her şey algoritma ile ilgili :)
Doktor

4

CJam - 70

q~:C;:H0]H*$W%{[__W<\1>]z{~-}%{C>}#):I{I(_2$=C-tC,{I+_2$=)t}/}0?}h-H-,

Http://cjam.aditsu.net/ adresinde deneyin

Açıklama:

q~                    read and evaluate the input
:C;                   store the 2nd number in C and remove
:H                    store the first number in H
0]H*                  make an array [H 0] and repeat it H times
$W%                   sort and reverse, obtaining [(H H's) (H 0's)] (initial cliff)
{                     loop...
    [__W<\1>]         make an array with the cliff without the first column
                      and the cliff without the last column
    z{~-}%            subtract the 2 arrays to get the height differences
    {C>}#             find the index of the first height diff. greater than C
    ):I               increment and store in I
    {                 if the value is non-zero (i.e. landslide occurring)
        I(_2$=C-t     subtract C from the corresponding column height
        C,            make an array [0 1 ... C-1]
        {             for each of those numbers
            I+        add I, obtaining a column index where some soil falls
            _2$=)t    increment the column height
        }/            end loop
    }0?               else break outer loop; end if
}h                    ...while the condition is true
-H-                   remove all 0 and H from the final stable cliff
,                     count the remaining columns

hOperatör çıkarmadan yığında son değerini kontrol eder. Bir heyelan oluştuysa, değer, boş olmadığı için true olarak değerlendirilen cliff dizisidir. Değilse, son değer 0'dır (yanlış).
Bu nedenle, heyelan durumunda, döngü yığındaki diziyle devam eder, aksi halde diziden sonra 0 basılarak biter. Bu 0 daha sonra bir sonraki -operatör tarafından diziden kaldırılır .


4

Python, 200 190 174

h,c=input();q=[h]*h+[0]*h
try:
 while 1:
    d=[b-a for a,b in zip(q[1:],q)];g=max(d);a=d.index(g)
    for i in range(c):q[a+1+i]+=1/(g>c);q[a]-=1
except:print sum(h>i>0for i in q)

Genişletilmiş sürüm:

h, c = input()
# Initialize the heights
q = [h]*h + [0]*h
try:
    while 1:
        # Difference between the heights
        d = [b-a for a,b in zip(q[1:],q)]
        # It may error here, when h == 0, but thats okay
        g = max(d)
        a = d.index(g)
        for i in range(c):
            # This is the termination condition, when g <= c
            q[a+1+i] += 1 / (g>c)
            # Save the newline; also move this line to after termination
            q[a] -= 1
except:
    # Count all heights that have changed
    print sum(h > i > 0 for i in q)

Düzenleme: Bazı optimizasyonlardan sonra, mola yoluyla zorlu döngü sonlandırmasını elimine ettim (1 bayt kazandırır). Ayrıca slaytı dilimden loop temelli olarak değiştirdik.


Güzel! Köşeli parantezleri sum2 bayt içine bırakabilirsiniz . Ayrıca Python'da tam bir program tanımlamak, girdi almak h,c=input()ve sonuçta baskı almak daha iyidir .
Zgarb

Bu çözümü farketmedim ve biraz daha kötüsünü gönderdim D: Ah, rekabet güzel. Belki bakalım bazı baytları tıraş edebilir miyim? Bu arada, senin içinde karşılaştırmalar saygısız sumkutu size bir tane kaydet: sum(h>i>0for i in q).
undergroundmonorail

@undergroundmonorail Çok çalıştım, ancak yaklaşımınızın sadece üstün olduğuna korkuyorum :(. c=0bir bayt kaydeder (cevabınız hakkında yorum yapamam).
Philipp

4

Python 2 - 194 158 bayt

h,c=input()
b=l=[h]*h+[0]*h
while b:
 b=0
 for i in range(len(l)-1):
  if l[i]-l[i+1]>c:
    for j in range(c):l[i-~j]+=1
    l[i]-=c;b=1
print sum(h>e>0for e in l)

(SE'nin etiketleme yorumlayıcısının hazır bilgi sekmelerini 4 boşluğa dönüştürdüğünü unutmayın. Bu programın 7. ve 8. satırlarının yalnızca her biri girinti için tek bir sekme [yani bir bayt] vardır.)

hÖnce stdin'in girişini yapar . Örneğin:

$ ./landslide.py <<< '6, 2'
4

Bu program pek çok gelişme kaydetti. Bu cevabı daha önemli düzenlemelerin bazılarını açıklamak için düzenliyordum, ancak biraz zaman alıyordu. Merak ediyorsanız düzenleme geçmişini kontrol edebilirsiniz.

açıklama

İlk önce hve cstdin'den okunur. Python 2'de input()eşdeğerdir eval(raw_input()), bu yüzden sayıları ayıran bir virgül istiyorum. input()dönüşüm gerektirmeyen, bir miktar demet verir.

Daha sonra bir tamsayı listesi yapılır. Öyle 2*huzun. İlk yarı hve ikinci yarı 0'dır. Bunun sonsuz hs sola ve 0 s sağa simüle etmek için yeterli olduğunu göstermek için hiçbir nedenim yok . Ben sadece bir tökezledi ve tüm test durumlarında işe yarıyor, bu yüzden eğer birisi girdi bulabilirse işe yaramazsa memnuniyetle değiştireceğim. Her neyse, bu liste denir l, ancak başka bir kopyası denir b.

b'nin değeri aslında önemli değil, tek önemli olan onun gerçek olmaması. Boş olmayan bir liste gerçeğe aykırı ve bburada boş bırakmanın tek yolu h0 ise, bu durumda doğru cevap hala basılıyor. Başka bir durumda, bdöngüye girdiğimizden emin olmak için acımasız olmak gerekir while b:. Bununla birlikte, döngüde gerçekleşen ilk şey b0'a, bir falsey değerine ayarlanır . Döngünün her tekrarı sırasında, bözel olarak bir gerçeğe geri ayarlanmalıdır, aksi takdirde döngü sona erer.

Döngünün geri kalanı gerçek simülasyondur. Çok saf, aslında sadece sorun tanımının kod çevirisi. Herhangi bir elementi l, takip edenden daha cbüyükse, çıkartılır cve bir sonraki celementler bunlara 1 eklenir. (Burada kullanılan bitsel sihir i+1+j, bu arada , sadece daha kısa bir yazı biçimidir.) Bu dönüşümleri yaparken, 1 bolarak ayarlanır. İlk kez hiçbir dönüşüm byapılmazsa, döngü 0 kalacaktır.

Herhangi bir gerçek ifade değerlendirilir Trueve üzerinde matematik yapmaya çalıştığınızda, 1 Trueolarak değerlendirilir. Aynı doğru Falseve 0'dır. Programın son satırı , ifadedeki lgibi her elemanı kullanır ve sonucu toplar. Bu, 0'dan büyük ancak orijinal uçurum yüksekliğinden daha düşük sütun sayısını alır; bu, sorunun istediği değerdir. Yazdırıldı ve program sona erdi.eh>e>0


2
c-=cEşdeğer değil c=0mi?
Zgarb

...vay. Arkamı izlediğin için teşekkürler, şunu haketmeliydim, haha
undergroundmonorail

1
i+1+jolarak yazılabiliri-~j
Sp3000

@ Sp3000 Tamamen bitwise sihri unuttum! Teşekkürler: D
undergroundmonorail

3

Haskell, 163 156 151 Bayt

h#c=sum[1|e<-(until=<<((==)=<<))s$r h++r 0,e`mod`h/=0]where r=replicate$h+1;s w@(x:y:z)|x==0=w|x>c+y=x-c:map(+1)(take c(y:z))++drop c(y:z)|1<2=x:s(y:z)

Kullanım: h#cörneğin 6#2hangi çıktılar 4.

Nasıl çalışır: yardımcı işlevi stek bir heyelan yapar. sÇıkış artık değişmeyene kadar tekrar tekrar uygulayın . Etkilenen öğeleri sayın.

Stackoverflow'ta "çıkış değişmeyene kadar uygula" işlevini (yani until=<<((==)=<<)) bulundu .


fİnfix ( h#c=...) olarak tanımlayarak ve wheremaddeyi aynı satıra taşıyarak birkaç bayttan tasarruf edebilirsiniz . Ayrıca, kaç tane parantez kullanıldığını hala $biliyorum, ancak ne kadar emin değilim ...
olmasam da

@ Zgarb: ipuçları için teşekkürler. Değiştirme() ile $benim için iz ve hatadır.
nimi

3

Mathematica, 108 104 100 97 95

f=Max@#-Min@#&[0Range@#2//.{x___,k:##..&[a_,{#}],a_,y___}:>Sort@{x,##&@@({k}-1),a+#,y}/.{}->0]&

Kullanımı:

f[c, h]

Örnek:

f[5, 80]

28


2

C # 303 295

İşe yarıyor!

Ama bu bir ....

int q(int n,int c){var s=Enumerable.Repeat(n,n).ToList();s.Add(0);var d=new HashSet<int>();var g=true;while(g){g=false;for(int i=s.Count-1;i>0;i--){int z=i;int y=i-1;if((s[y]-s[z])>c){s[y]-=c;d.Add(y);g=true;for(int j=1;j<=c;j++){s[y+j]++;d.Add(y+j);if(s[s.Count-1]>0)s.Add(0);}break;}}}return d.Count;}

Yeni dil bulmalıyım;)

Bu CJam olayını kontrol edeceğim ...

Gelişmiş:

int q(int n,int c){var s=Enumerable.Repeat(n,n).ToList();s.Add(0);var d=new HashSet<int>();var g=1>0;while(g){g=1<0;for(int i=s.Count-1;i>0;i--){int z=i,y=i-1;if((s[y]-s[z])>c){s[y]-=c;d.Add(y);g=1>0;for(int j=1;j<=c;j++){s[y+j]++;d.Add(y+j);if(s[s.Count-1]>0)s.Add(0);}break;}}}return d.Count;}

1
Bunu hala biraz optimize edebilirsiniz. int z=i;int y=i-1;olabilir int z=i,y=i-1;. forÖrneğin bu yüzden döngüler, onların endeksleri ile zorlaştırdı mı yok for(int i=s.Count-1;i>0;i--)olabilir for(int i=s.Count;--i>0;). 1<0daha kısa bir yazı biçimidir false. if(s[s.Count-1]>0)s.Add(0);Doğruluk etkilemeden durumu kaybedebileceğinden şüpheleniyorum , sadece hız.
Peter Taylor

@Peter Taylor. Teşekkürler!
mike m
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.