Prédire le glissement de terrain

22

Glissements de terrain

Dans ce défi, votre travail consiste à prévoir l'étendue des dommages causés par un glissement de terrain massif. Nous utilisons pour cela le modèle bidimensionnel simplifié, paramétré par une hauteur initiale h >= 0 et un coefficient critique c > 0 . Vous commencez par une falaise de hauteur h, et on suppose que le terrain est complètement plat infiniment à gauche et à droite de celui-ci. Pour h = 6, la situation ressemble à ceci:

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

Le -substratum rocheux est inamovible et le #sol est instable. Si la différence de hauteur entre deux colonnes voisines est supérieure à c, un glissement de terrain se produit: les cunités supérieures du sol de la colonne de gauche tombent dans les ccolonnes suivantes à droite, une à chacune. La colonne non vide la plus à droite de la figure est instable c = 2, donc un glissement de terrain est déclenché:

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

La colonne est toujours instable, ce qui provoque un deuxième glissement de terrain:

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

Maintenant, la colonne de gauche est devenue instable, donc un nouveau glissement de terrain y est déclenché:

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

Après cela, la falaise est de nouveau stable. La bonne chose à propos de ce modèle est que l'ordre dans lequel les glissements de terrain sont traités n'a pas d'importance: le résultat final est le même.

La tâche

Votre programme reçoit les paramètres entiers het cen entrée (l'ordre n'a pas d'importance, mais vous devez le spécifier dans votre réponse), et il doit afficher le nombre total de colonnes affectées par le glissement de terrain. Cela signifie le nombre de colonnes dans la falaise stable résultante dont la hauteur est strictement comprise entre 0et h. Dans l'exemple ci-dessus, la sortie correcte est 4.

Vous pouvez écrire un programme complet ou une fonction. Le nombre d'octets le plus bas l'emporte et les failles standard sont interdites.

Cas de test

Ceux-ci sont donnés dans le format 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
Zgarb
la source

Réponses:

5

CJam, 62 57 octets

Pour autant que je puisse voir, c'est une approche complètement différente pour implémenter la solution de la réponse d'Aditsu.

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

L'entrée prend la forme de h c

Exemple:

80 5

Sortie:

28

Comment ça marche

La logique est assez simple ici avec quelques astuces utilisées pour réduire la taille du code.

  • Récupère h + 1( + 1pour la h = 0casse) un tableau de longueurs, chaque élément hreprésentant la falaise
  • Commencez à itérer à partir de l'index le plus à droite de ce tableau
    • Si les deux éléments de l'index actuel ont plus de c
      • Supprimer cde l'élément d'index actuel
      • Ajouter 1aux céléments suivants du tableau à partir de l'index en cours
      • Rendre l'index actuel égal à la longueur de ce nouveau tableau
      • Cela garantit que nous stabilisons les pierres à droite de l'index actuel en premier
    • sinon, réduisez l'indice actuel
  • Lorsque nous avons atteint l'indice le plus à gauche, nous faisons en sorte que tous les index adjacents ont inférieur ou égal à la cdifférence
  • Supprimez tout 0ou hvaleur du tableau et obtenez la longueur.

Expansion du code

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";

Essayez-le en ligne ici

Optimiseur
la source
Foiled again: p Bien joué :)
aditsu
@aditsu à nouveau?
Optimizer
Ce n'est pas la première fois que quelqu'un me bat à CJam. Et ce n'est pas la première fois que vous le faites non plus, bien que vous ne sachiez pas si vous l'avez déjà fait en compétition directe auparavant.
aditsu
Heh :) C'est tout sur l'algorithme :)
Optimizer
4

CJam - 70

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

Essayez-le sur http://cjam.aditsu.net/

Explication:

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

L' hopérateur vérifie la dernière valeur de la pile sans la supprimer. Si un glissement de terrain s'est produit, la valeur est le tableau de falaises, qui prend la valeur true car il n'est pas vide. Sinon, la dernière valeur est 0 (faux).
Donc, en cas de glissement de terrain, la boucle continue avec le tableau sur la pile, sinon elle se termine par un 0 poussé après le tableau. Ce 0 est ensuite supprimé du tableau par l' -opérateur suivant .

aditsu
la source
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)

Version étendue:

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)

Edit: Après quelques optimisations, j'ai éliminé la terminaison de boucle maladroite via break (enregistre 1 octet). La diapositive a également été modifiée de base en tranche à base en boucle.

Philipp
la source
Agréable! Vous pouvez supprimer les crochets à l'intérieur sumpendant 2 octets. De plus, il est généralement préférable de définir un programme complet en Python, en prenant l'entrée avec h,c=input()et en imprimant le résultat à la fin.
Zgarb
Je n'ai pas remarqué cette solution et j'ai posté une solution légèrement pire D: Oh bien, la concurrence est agréable. Je vais peut-être voir si je peux raser certains octets du mien. Soit dit en passant, en feuilletant vos comparaisons dans votre sumPourrez - vous sauver un: sum(h>i>0for i in q).
undergroundmonorail
@undergroundmonorail J'ai essayé dur, mais je crains que votre approche soit tout simplement supérieure :(. c=0enregistre un octet (je ne peux pas commenter votre réponse).
Philipp
4

Python 2 - 194 158 octets

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)

(Notez que l'interpréteur de marquage de SE convertit les tabulations littérales en 4 espaces. Les lignes 7 et 8 de ce programme n'ont qu'une seule tabulation [c'est-à-dire un octet] d'indentation chacune.)

Prend d'abord une entrée sur stdin h. Par exemple:

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

Ce programme a connu de nombreuses améliorations. J'avais édité cette réponse pour expliquer certaines des modifications les plus importantes, mais cela devenait un peu long. Vous pouvez consulter l'historique des modifications si vous êtes curieux.

Explication

Tout d'abord, het csont lus depuis stdin. En Python 2, input()est équivalent à eval(raw_input()), c'est pourquoi je demande une virgule séparant les nombres. input()donne renvoie un tuple d'ints, aucune conversion requise.

Ensuite, une liste d'entiers est établie. C'est 2*hlong. La première moitié est h0 et la seconde moitié est 0. Je n'ai aucun raisonnement pour montrer que cela suffit pour simuler des hs infinis à gauche et des 0 à droite. Je suis juste tombé dessus et cela fonctionne pour tous les cas de test, donc si quelqu'un peut trouver une entrée, cela ne fonctionne pas, je le changerai avec plaisir. Quoi qu'il en soit, cette liste est appelée l, mais une autre copie de celle-ci est appelée b.

bLa valeur de 's n'a pas vraiment d'importance, tout ce qui compte, c'est que c'est vrai. Une liste non vide est véridique et la seule façon d' bêtre vide ici est si hest 0, auquel cas la réponse correcte est toujours imprimée. Dans tous les autres cas, bdoit être véridique pour s'assurer que nous entrons dans la while b:boucle. Cependant, la première chose qui se produit dans la boucle est la mise bà 0, une valeur de falsey. Au cours de chaque répétition de la boucle bdoit être spécifiquement remise à un vrai ou la boucle se terminera.

Le reste de la boucle est la simulation réelle. C'est très naïf, essentiellement juste une traduction de code de la description du problème. Si un élément de lest plus que csupérieur à celui qui le suit, il est soustrait par cet les céléments suivants ont 1 ajouté à eux. (La magie au niveau du bit utilisée ici est juste une façon plus courte d'écrire i+1+j, soit dit en passant.) Lors de ces transformations, best défini sur 1. La première fois qu'aucune transformation n'est effectuée, breste 0 et la boucle se termine.

Toute expression vraie est évaluée à True, et lorsque vous essayez de faire des calculs, Trueelle est évaluée à 1. Il en va de même pour Falseet 0. La dernière ligne du programme utilise chaque élément de las edans l'expression h>e>0et additionne le résultat. Cela obtient le nombre de colonnes supérieur à 0 mais inférieur à la hauteur de falaise d'origine, qui est la valeur demandée par la question. Il est imprimé et le programme se ferme.

métro monorail
la source
2
N'est-ce pas c-=céquivalent à c=0?
Zgarb
...sensationnel. merci d'avoir regardé mon dos, j'aurais dû attraper ça, haha
undergroundmonorail
1
i+1+jpeut être écrit commei-~j
Sp3000
@ Sp3000 J'ai totalement oublié la magie au niveau du bit! Merci: D
undergroundmonorail
3

Haskell, 163 156 151 octets

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)

Utilisation:, h#cpar exemple, 6#2quelles sorties 4.

Comment ça marche: la fonction d'aide sfait un seul glissement de terrain. Appliquer à plusieurs reprises sjusqu'à ce que la sortie ne change plus. Comptez les éléments affectés.

Trouvé la fonction "appliquer jusqu'à ce que la sortie ne change pas" (c'est until=<<((==)=<<)-à- dire ) à Stackoverflow .

nimi
la source
Vous pouvez enregistrer quelques octets en définissant fcomme infix ( h#c=...) et en déplaçant la whereclause sur la même ligne. De plus, il y a encore des parenthèses à utiliser $, même si je ne sais pas combien ...
Zgarb
@Zgarb: merci pour les indices. Remplacer ()par $est une piste et une erreur pour moi.
nimi
3

Mathematica, 108 104 100 100 97 95

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

Usage:

f[c, h]

Exemple:

f[5, 80]

28

alephalpha
la source
2

C # 303 295

Ça marche!

Mais c'est un ....

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;}

Je dois trouver une nouvelle langue;)

Je vais vérifier ce truc CJam ...

Amélioré:

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;}
mike m
la source
1
Vous pouvez toujours optimiser cela un peu. int z=i;int y=i-1;pourrait être int z=i,y=i-1;. Les forboucles ne font pas de choses compliquées avec leurs indices, par exemple cela for(int i=s.Count-1;i>0;i--)pourrait l'être for(int i=s.Count;--i>0;). 1<0est une façon d'écrire plus courte false. Je soupçonne que cela if(s[s.Count-1]>0)s.Add(0);pourrait perdre la condition sans affecter la justesse, juste la vitesse.
Peter Taylor
@Peter Taylor. Merci!
mike m