Vous pagayez en canoë sur une rivière d'eau vive assez rapide. Soudain, vos pagaies explosent et vous vous retrouvez dans une situation dangereuse dévalant une rivière rapide sans pagaies. Heureusement, vous avez toujours vos compétences en programmation, vous décidez donc de vous tailler un programme sur le côté de votre canoë pour vous aider à survivre aux rapides. Cependant, il n'y a pas beaucoup de surface sur le côté du canoë pour écrire votre programme, vous devez donc le rendre aussi court que possible.
La rivière peut être représentée par une grille de 8 sur 16. Nous allons étiqueter les colonnes avec les nombres 0
à 7
et les lignes avec les nombres 0
à 15
.
y
--------15
--------14
--------13
--------12
--------11
--------10
--------9
--------8
--------7
--------6
--------5
--------4
--------3
--------2
--------1
--------0
01234567
x
Ci-dessus: une rivière ordinaire, complètement calme et sans obstruction. Naturellement, ce n'est pas la rivière sur laquelle vous vous trouvez.
Vous commencez aux coordonnées (4, 0) et à partir de là, vous remontez de façon incontrôlable la rivière (c'est-à-dire le vecteur (0,1)
) jusqu'à ce que vous heurtiez un rocher (représenté par un o
dans ces exemples). Lorsque vous frappez un rocher, vous aurez 55% de chances de passer devant le rocher vers la gauche (ie le vecteur (-1,1)
) et 45% de chances de passer devant le rocher vers la droite (ie le vecteur (1,1)
). Si le canoë est sur les colonnes à l'extrême gauche ou à droite, il se déplacera toujours vers le centre. S'il n'y a pas de roches, il se déplacera tout droit vers le haut.
y
----x---15
----xo--14
-o--x---13
----x---12
---ox---11
---x----10
---xo---9
---ox---8
----xo--7
-----x--6
----ox--5
-o--x---4
----x---3
----xo--2
----x---1
----x---0
01234567
Ci-dessus: un itinéraire possible que le canoë pourrait emprunter, représenté à l'aide du caractère x
Étant donné la carte de la rivière, écrivez un programme qui affichera la probabilité que le canoë se termine à une colonne donnée.
Acceptez la saisie selon la méthode qui convient à votre programme (par exemple, STDIN, argument de ligne de commande raw_input()
, lecture à partir d'un fichier, etc.). La première partie de l'entrée est un entier unique de 0 à 7, représentant la colonne pour laquelle le programme trouvera la probabilité. Ensuite, une liste de tuples sous la forme x,y
représentant la position des pierres.
Un exemple:
Contribution:
4 4,1 5,5 3,5
Cela indiquerait une rivière avec des rochers aux positions (4,1), (5,5) et (3,5), et demande la probabilité que le canoë se termine à la 4e colonne.
Sortie:
0.495
Notez que dans cet exemple, les positions des roches étaient symétriques, permettant de résoudre le problème avec une distribution binomiale. Ce ne sera pas toujours le cas!
De plus, la rivière sera toujours traversable. Autrement dit, il n'y aura jamais deux roches placées côte à côte horizontalement. Voir le commentaire de Glenn pour un exemple d'un cas impossible.
C'est le golf de code, donc le plus petit nombre de personnages gagne. N'hésitez pas à poser des questions dans les commentaires si la spécification n'est pas claire.
la source
Réponses:
GolfScript, 105 caractères
Une version GolfScript qui est devenue beaucoup plus longue que prévu - mais chaque tentative avec une approche différente était encore plus longue. L'entrée doit être donnée sur STDIN.
Exemple:
Code annoté:
la source
Rubis,
204191172 caractèresIl simule récursivement tous les résultats possibles tout en gardant une trace de la probabilité de chaque résultat individuel, puis il ajoute cette probabilité à un compteur cumulatif quand
y == 15
.Astuces de fantaisie:
c,*r=gets.split
- l'opérateur "splat" (*
) prend tous les éléments restants degets.split
et les colle dans ler
tableaunext {something} if {condition}
: essentiellement équivalent à« Découvert » en évoluantif condition; something; return; end
versreturn something if condition
àbreak something if condition
, puis je me suis dit que je voudrais essayer un « opérateur de boucle » plus courte pour voir si elle fonctionnerait (ce qu'elle a fait, bien sûr).Merci à @ MartinBüttner d'avoir suggéré d'utiliser des opérateurs ternaires chaînés (qui ont fini par devenir l'énorme troisième ligne du code golfé ci-dessus) et d'éliminer le point ci-dessus (qui a sauvé 19 (!) Caractères).
J'ai cependant utilisé une astuce quelque peu sophistiquée: j'ai réalisé que
s[foo],s[bar]
cela ne fonctionne pas dans Ruby pour deux appels de méthode dans une seule instruction. Donc au début je l' ai changé(_=s[foo],s[bar])
(une variable factice), mais je me suis aperçu que je pouvais ajouter et jeter les valeurs de retour:s[foo]+s[bar]
. Cela ne fonctionne que parce que les appels às
ne "renverront" jamais d'autres appels às
ou un numéro (o[x]+=p
), donc je n'ai pas à me soucier de vérifiernil
.Autres optimisations diverses:
p
au lieu deputs
pour imprimer les nombres,<1
au lieu de==0
(puisque le canoë ne quitte jamais la rivière) et des comparaisons similaires ailleurs,[0]*8
pour les probabilités initiales car les nombres de Ruby sont toujours "pass by value"Non golfé:
la source
next X if Y
dans des opérateurs ternaires imbriqués? Belle trouvaille cependant, vous voudrez peut-être l'ajouter aux conseils Ruby!C #
418 364octetsProgramme C # complet attendant l'entrée de STDIN. Fonctionne en lisant les roches dans un tableau de tous les emplacements de la rivière, créant efficacement une carte, puis il effectue simplement 16 itérations de probabilités de déplacement autour d'un tableau décimal de 8 largeurs avant de produire le résultat.
Code formaté:
la source
for(;j-->0;)
). Vous pouvez vous débarrasser de quelques caractères en remplaçant le dernierC.WriteLine
parC.Write
. De plus, si vous utilisezfloat
au lieu de,decimal
vous pouvez enregistrer quelques octets supplémentaires.decimal
parce quefloat
ce ne sera pas précis, mais la décimale devrait suffire pour ces problèmes, mais pourrait probablement s'en tirer comme vous le dites. Je mettraiC.Write
si je parviens à jouer au golf plus loin car il est probablement plus proche de la spécification queC.WriteLine
je ne pense pas que 4 octets justifient une modification pour ce programme de taille;)Haskell, 256 octets
Voici une version très non golfée avec quelques astuces qui ont été utilisées:
La dernière astuce que j'ai utilisée était de noter que vous pouvez agir comme si les roches d'une même rangée étaient réellement séparées par une quantité infinitésimale. En d'autres termes, vous pouvez appliquer le transformateur de distribution de probabilité pour chaque roche de la même ligne de manière séquentielle et dans l'ordre que vous souhaitez, plutôt que de les appliquer tous simultanément. Cela ne fonctionne que parce que le problème interdit deux roches adjacentes horizontalement.
Ainsi, le programme transforme l'emplacement de chaque roche en un transformateur de distribution de probabilité, ordonné par la coordonnée y de la roche. Les transformateurs sont ensuite simplement enchaînés dans l'ordre et appliqués à la distribution de probabilité initiale. Et c'est ça!
la source
Perl 169 octets
Lit à partir de STDIN.
Assez simple, utilise implicitement les colonnes -1 et 8 pour lisser les cas de bordure. Les probabilités peuvent être propagées en toute sécurité à chaque niveau suivant car il n'y a pas de pierres adjacentes, donc une seule passe suffit.
la source
PHP, 358
Utiliser le cerveau pour déterminer les chemins possibles et leurs probabilités est difficile et nécessiterait probablement plus de code que de simuler simplement 1 000 000 d'accidents de canoë. Oh l'humanité!
Exemple:
Golfé:
Cette version ne fait pas de jolie impression et affiche la probabilité de flottement de l'atterrissage du canoë à la position spécifiée.
la source
PHP, 274
Je ne peux pas lire / écrire GolfScript pour me sauver la vie, mais en jetant un œil à la soumission de @ Howard, je me suis dirigé dans une meilleure direction que de simuler simplement 1 million d'accidents de canoë.
En commençant par un tableau de probabilités pour les positions de départ, nous pouvons simplement diviser ces nombres chaque fois qu'une pierre est rencontrée.
Exemple de sortie:
Golfé:
Exemple d'exécution:
la source
Haskell, 237
J'espère juste que le canoë est livré avec ghc installé ...
L'astuce avec la liste infinie est volée à Matt Noonan, bravo à lui!
J'espère avoir bien compris la logique, mais l'exemple de Matt
"5 4,4 1,5 5,3 3,6 2,9 4,12 3,13"
donne0.5613750000000001
et l'exemple de OP"4 4,1 5,5 3,5"
donne0.49500000000000005
, ce qui semble être correct à part quelques erreurs en virgule flottante.Le voici en action:
la source