Calculer le péage des trolls pour passer en toute sécurité

12

Inspiré par /puzzling//q/626


Dans vos aventures, vous arrivez à une série de 7 ponts que vous devez traverser. Sous chaque pont vit un troll. Pour traverser le pont, vous devez d'abord donner au troll un certain nombre de gâteaux en pourcentage du nombre de gâteaux que vous portez. Parce que ce sont de gentils trolls, ils vous rendront un certain nombre de gâteaux.

Au début de chaque journée, le roi des trolls local fixe le pourcentage de taxe sur les gâteaux que chaque voyageur doit payer et le remboursement des gâteaux de trolls - le nombre de gâteaux que chaque troll doit rendre aux voyageurs.

Votre travail consiste à calculer le nombre minimum de gâteaux nécessaires pour passer les 7 ponts de pêche à la traîne pour les conditions données ce jour-là.

Présumer:

  1. Deux paramètres d'entrée: taxe sur le gâteau en pourcentage (entier de 0 à 100) et remboursement du gâteau troll.
  2. Personne, pas même les trolls, ne veut un gâteau partiellement mangé par un autre troll. Si vous vous retrouvez avec une fraction de gâteau, le troll l'obtient.
  3. Si un troll accepte une taxe sur les gâteaux, mais doit ensuite vous rendre tous les gâteaux (avec les mêmes gâteaux ou moins qu'auparavant), il se mettra en colère et vous dévorera, vous et vos gâteaux.
  4. Chaque troll doit garder au moins un gâteau complet.
  5. Vous ne pouvez transporter qu'un maximum de 100 gâteaux.
  6. Vous devez terminer la journée où vous vous trouvez actuellement ou de l'autre côté des 7 ponts.

Défi:

Écrivez un programme complet pour sortir le nombre minimum de gâteaux à voyager pour la journée en cours ou zéro s'il n'est pas possible de voyager en toute sécurité aujourd'hui - vous attendez de voir quels sont les nombres demain.

L'entrée doit être passée en tant que stdin, arguments de ligne de commande ou entrée de fichier.

Le code le plus court (nombre d'octets) gagne.

Exemple:

25% de taxe sur les gâteaux, 2 remboursements de gâteau troll.

commencer avec 19 gâteaux
avant le troll 1: (19 * 0,75) = 14,25
après le troll 1: (14 + 2) = 16

avant le troll 2: (16 * 0,75) = 12
après le troll 2: (12 + 2) = 14

etc.

19 gâteaux -> 16 -> 14 -> 12 -> 11 -> 10 -> 9 -> 8
18 gâteaux -> 15 -> 13 -> 11 -> 10 -> 9 -> 8 -> 8 (règle 3)

Pour 18 gâteaux, le dernier troll n'aurait pas pu garder de gâteaux. Par conséquent, le nombre minimum de gâteaux pour 25% / 2 jours est de 19.

input: 25 2
output: 19

Exemple 2:

90% de taxe sur les gâteaux, 1 remboursement de gâteau troll

100 gâteaux -> 11 -> 2 -> 1 (règle 4)

Le troisième troll n'a pu garder aucun gâteau. Il n'est donc pas possible de voyager sur 90% / 1 jour même à partir du nombre maximum de gâteaux.

input: 90 1
output: 0

Les données

Créez un graphique rapide des valeurs d'entrée et de sortie. J'ai été surpris que ce ne soit pas "lisse" (comme une courbe en cloche ou similaire); il y a plusieurs îles visibles.

tableau de données

Données pour les personnes intéressées. Les colonnes sont divisées en intervalles de 5%, les rangées sont des unités de 1 intervalle de remboursement de gâteau (Excel a fait pivoter l'image). Vous pouvez voir qu'il ne peut y avoir de remboursement supérieur à 28 gâteaux.

27, 17, 13, 14, 15, 18, 20, 24, 53, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
47, 27, 20, 19, 19, 19, 24, 39, 48, 68, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0
67, 37, 28, 24, 23, 28, 27, 29, 50, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
87, 47, 33, 29, 27, 28, 31, 44, 37, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 57, 40, 34, 31, 29, 34, 34, 62, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 67, 48, 39, 35, 38, 37, 49, 57, 76, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 77, 53, 44, 39, 38, 47, 39, 59, 78, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 87, 60, 49, 43, 39, 40, 54, 46, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 97, 68, 54, 47, 48, 44, 44, 71, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 73, 59, 51, 48, 47, 59, 73, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 80, 64, 55, 49, 51, 49, 68, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 88, 69, 59, 58, 54, 64, 70, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 93, 74, 63, 58, 57, 54, 57, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 100, 79, 67, 59, 67, 69, 82, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 84, 71, 68, 60, 59, 77, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 89, 75, 68, 64, 74, 79, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 94, 79, 69, 67, 64, 66, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 99, 83, 78, 71, 79, 91, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 87, 78, 74, 69, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 91, 79, 77, 84, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 95, 88, 87, 74, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 99, 88, 80, 89, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 89, 84, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 98, 87, 94, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 98, 91, 84, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 99, 94, 99, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 97, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Communauté
la source
Bon point. Faites-en un programme complet pour plus de simplicité. L'entrée peut être spécifiée comme bon vous semble tant qu'elle n'est pas codée en dur (défi mis à jour).
C'est un bon casse-tête pour la force brute dans CJam. Je le ferai demain
bah, c'est pourquoi c # ne peut pas avoir de belles choses
La règle 2 semble exclure la possibilité qu'un troll ne reçoive qu'une fraction d'un gâteau, ce qui devrait rendre l'hypothèse 4 redondante. Pourtant, vous dites dans l'exemple 2 que le troisième troll n'obtiendrait que 0,8 gâteaux.
Dennis
Il y a des conflits dans la spécification. Dans le 25 2cas de 11 gâteaux, vous donnez au troll 2,75 gâteaux et récupérez 2 pour que le troll garde 0,75 (+ 0,25) et que vous survivez. Dans le 90 1cas des 2 gâteaux, vous donnez le troll 1,8 et récupérez 1 pour que le troll garde 0,8 (+. 2) mais vous mourrez.
TwiNight

Réponses:

6

CJam, 46 43 41 39 38 36 33 octets

100:H,{)_7{ea:i~H@m2$*H/+@;}*>}#)

Entrée via ARGV.

Il existe un interpréteur en ligne, mais malheureusement, il ne prend pas en charge les arguments de ligne de commande. Pour les tests, vous pouvez l'imiter depuis STDIN avec cette version:

rr]:A;
100:H,{)_7{A:i~H@m2$*H/+@;}*>}#)

Explication de la version basée sur ARGV:

100:H                                  "Push a 100 and save it in H.";
     ,                                 "Create a range (as an array) from 0 to 99.";
      {                       }#       "Find the first index in [0,1,2,...,99] for which the
                                        block produces a truthy (non-zero) value.";
       )_                              "Increment and duplicate the current array element.";
         7{                }*          "Execute the block seven times.";
           ea:i                        "Push the command-line arguments as an array of strings
                                        and convert each element to an integer";
               ~                       "Unwrap the array.";
                H@                     "Push a 100 and rotate the stack to pull up
                                        the first command line argument.";
                  m                    "Subtract (from 100).";
                   2$                  "Copy the last iterations result.";
                     *H/               "Multiply and divide by 100, deducting tax.";
                        +              "Add the refund.";
                         @;            "Rotate top three stack elements, and discard the one that 
                                        has been pulled to the top. This always leaves the last 
                                        two results on the stack.";

                             >         "Make sure that the last result was less than the second 
                                        to last. Yields 0 or 1.";
                                )      "After the # search completes, we'll get -1 if no such 
                                        index exists, or one less than the desired number if it 
                                        does, so we can just increment.";

Le contenu de la pile est automatiquement imprimé à la fin du programme.

Martin Ender
la source
Votre code produit des résultats incorrects pour 55 2( 0au lieu de 100) et 56 5( 98au lieu de 94). En effet, 100_0.55*-iet 25_0.56*-iêtre victime d'une imprécision en virgule flottante. Autant que je sache, les paires 31 24, 31 25, 33 21, 33 22, 33 23, 35 10, 35 12, 35 15, 35 16, 35 27, 56 1, 57 4donnent également des résultats incorrects.
Dennis
1
@Dennis corrigé, merci!
Martin Ender
@Dennis Cela a en fait sauvé un octet. Je souhaite que CJam ait des fermetures, alors je pourrais simplement définir un bloc au début qui fait la déduction fiscale, et l'utiliser, au lieu d'utiliser deux variables. Peut-être que je peux enregistrer quelque chose en utilisant ARGV au lieu de STDIN, laissez-moi voir.
Martin Ender
5

CJam, 44 40 38 37 35 octets

l~U100:M),{{_M5$-*M/3$+_@<*}7*}=]W=

Ou lorsque vous utilisez des arguments de ligne de commande et une {}#astuce, 33 octets :

100:M,{){_ea:i~M@-@*M/+_@<*}7*}#)

Ne pas mettre celui-ci comme mon {}#approche principale est inspiré de la réponse de Martin.

Exemple d'exécution:

Contribution:

25 2

Production:

19

Un autre:

Contribution:

15 14

Production:

100

Comment ça fonctionne

l~                       "Read the two numbers, swap and convert tax to double";
  U100:M),               "Push 0 and [0, 1, ... 100] to stack, storing 100 in M";
          {  ...  }=     "Run this code for each element until top stack element is 1";
           {...}7*       "Run this code block 7 times";
_                        "Copy the array element";
  M5$                    "Push 100 and a copy tax % to stack";
     -*                  "Number = (100 - tax %) * Number";
       M/                "Integer divide the number by 100";          
         3$+             "Add refund";
            _@<*         "Convert to 0 if refunded number > before tax one";
                    ]W=  "Take the last element of the stack";

Essayez-le en ligne ici

Optimiseur
la source
Et maintenant, il ne reste plus qu'à attendre que Dennis vienne nous battre. ;)
Martin Ender
Pas dans CJam;) (avec un peu de chance)
Optimizer
J'aime vraiment l' ]W=astuce, mais jusqu'à présent, chaque fois que j'essaie de l'utiliser, je me retrouve avec le même nombre de caractères.
Martin Ender
@ MartinBüttner - Ouais, moi aussi.
Optimizer
1
@Dennis - Devrait fonctionner maintenant, avec un avantage supplémentaire de 2 octets de code plus court: D
Optimizer
4

APL (39)

T R←⎕⋄⊃Z/⍨{⍵(⊢×>)R+⌊⍵×1-T÷M}⍣7¨Z←⍳M←100

Explication:

  • T R←⎕: lisez deux chiffres sur le clavier et enregistrez-les dans T(taxe) et R(retour).
  • Z←⍳M←100: enregistrer le numéro 100dans Met tous les numéros de 1à 100dans Z.
  • {... }⍣7¨: pour chaque élément dans Z, exécutez la fonction suivante 7 fois:
    • R+⌊1-T÷M: calculer combien de gâteaux doivent être payés,
    • ⍵(⊢×>): multipliez ce montant par 1 si le troll se retrouve avec plus de gâteau qu'il n'en a commencé, ou par 0 sinon.
  • ⊃Z/⍨: pour chaque élément dans Z, répliquez-le par le nombre que cette fonction a donné. (Ainsi, tous les nombres pour lesquels la fonction renvoyée 0disparaît.) Sélectionnez ensuite le premier élément de cette liste. Si la liste s'est retrouvée vide, cela donne 0.
marinus
la source
3

C, 83 octets

int cake(int perc_taken, int given_back)
{
    int startcake = floor(100.f/perc_taken*given_back+1);
    for(int i = 0; i < 6; i++)
    {
        startcake = ceil((startcake-given_back) * 100.f/(100 - perc_taken));
    }
    return startcake;
}

Si cela fonctionne, il fonctionne pour tous les startcakes possibles, pas seulement de 1 à 100.

EDIT: Cela fonctionne. Golfé:

n(int p,int g) {int s=100./p*g+1,i=0;for(;i++<6;){s=ceil((s-g)*100./(100-p));}return s;}

Avec la limite «maximum 100 gâteaux»:

n(int p,int g) {int s=100./p*g+1,i=0;for(;i++<6;){s=ceil((s-g)*100./(100-p));}return s>100?0:s;}

91 octets.

Gerwin
la source
Je pense que c'est une partie importante de la spécification que la solution renvoie zéro si vous avez besoin de plus de 100 gâteaux au début.
Martin Ender
2

CJam, 36 octets

q~:R100:H*\d:T/i){R-H*HT-/m]}6*_H)<*
Dennis
la source
1

C ++ - 202 caractères

Comme d'habitude, mon C ++ a fait le pire:

#include<iostream>
int main(){double p,g,c=1,i,r,t;std::cin>>p>>g;for(;c<101;c++){r=c;for(i=0;i<7;i++){t=(int)(r*(1-(p/100))+g);if(t>=r){r=-1;break;}r=t;}if(r!=-1)break;}r!=-1?std::cout<<c:std::cout<<0;}

la source
1

APL, 36

x y←⎕⋄101|1⍳⍨y<x×{y+⍵-⌈⍵×x}⍣6⍳x÷←100

Explication

Notez qu'il existe un "seuil de gâteau". Pour le taux de taxe xet le remboursement y, vous aurez besoin de bien plus que de y÷xgâteaux pour passer le pont suivant.

x y←⎕prendre une entrée et affecter à x(taxe) et y(retour)
⍳x÷←100diviser xpar 100, puis générer un tableau de 1 à 100

{y+⍵-⌈⍵×x}⍣6appelez la fonction "pass bridge" 6 fois:
⌈⍵×xle nombre de gâteaux que vous avez, le taux de taxe, arrondissez (le montant que vous payez)
⍵-soustrayez du nombre de gâteaux que vous avez
y+Ajoutez le remboursement

Ensuite, vous obtenez un tableau de 100 éléments indiquant le nombre de gâteaux qui vous restent après avoir traversé 6 ponts si vous commencez avec 1 à 100 gâteaux. Pour voir si vous pouvez traverser le dernier pont, vérifiez si vous êtes au-dessus du seuil y÷x. Alternativement:
multipliez le tableau en x
y<vérifiant s'il est supérieur ày

Enfin,
1⍳⍨trouvez l'indice de première occurrence de 1(vrai), retourne 101s'il n'est pas trouvé
101|mod 101

TwiNight
la source
1

C 128

Assez similaire à l'autre solution C mais je pense que c'est inévitable. L'astuce principale consiste à sortir de la boucle interne avec des valeurs différentes selon qu'elle se termine ou non. Cela me permet d'utiliser?: Quand je ne pourrais pas si j'utilisais break;

t,r,j,k,l,p;main(i){for(scanf("%d%d",&t,&r),i=101;k=--i;){for(j=8;--j>0;)(p=r+k*(100-t)/100)<k?k=p:j=0;j?0:l=i;}printf("%d",l);} 

Non golfé

int t,r,j,k,l,p;
main(int i)
{
    for(scanf("%d%d",&t,&r),i=101;k=--i;)
    {
        for(j=8;--j>0;)
        {
            if((p=r+k*(100-t)/100)<k)
                k=p;
            else
                j=0;
        }
        j?0:l=i;
    }
    printf("%d",l);
}
Alchymiste
la source
Quel compilateur utilisez-vous?