Calcola il pedaggio da troll per passare in sicurezza


12

Ispirato da /puzzling//q/626


Nelle tue avventure arrivi a una serie di 7 ponti che devi attraversare. Sotto ogni ponte vive un troll. Per attraversare il ponte, devi prima dare al troll un numero di torte come percentuale del numero di torte che stai trasportando. Poiché questi sono troll gentili, ti restituiranno un certo numero di torte.

All'inizio di ogni giorno, il re del troll locale imposta la tassa sulla torta percentuale che ogni viaggiatore deve pagare e il rimborso della torta del troll - il numero di torte che ciascun troll deve restituire ai viaggiatori.

Il tuo compito è calcolare il numero minimo di torte necessarie per passare tutti e 7 i ponti dei troll per le condizioni indicate in quel giorno.

Assumere:

  1. Due parametri di input: imposta sulla torta percentuale (numero intero compreso tra 0 e 100) e rimborso della torta troll.
  2. Nessuno, nemmeno i troll, vuole una torta parzialmente mangiata da un altro troll. Se ti rimane una frazione di torta, il troll lo ottiene.
  3. Se un troll accetta una tassa sulle torte, ma deve restituirti tutte le torte (viene lasciato con le stesse o meno torte di prima), si arrabbierà e mangerà te e le tue torte.
  4. Ogni troll deve conservare almeno una torta completa.
  5. Puoi trasportare solo un massimo di 100 torte.
  6. Devi terminare la giornata in cui ti trovi attualmente o dall'altra parte di tutti e 7 i ponti.

Sfida:

Scrivi un programma completo per ottenere il numero minimo di torte da percorrere per il giorno corrente o zero se non è possibile viaggiare in sicurezza oggi - aspetterai di vedere quali sono i numeri domani.

L'input deve essere passato come stdin, argomenti della riga di comando o input di file.

Vince il codice più breve (conteggio byte).

Esempio:

25% di tasse sulla torta, rimborso di 2 troll cake.

inizia con 19 torte
prima del troll 1: (19 * 0,75) = 14,25
dopo il troll 1: (14 + 2) = 16

prima del troll 2: (16 * 0.75) = 12
dopo il troll 2: (12 + 2) = 14

eccetera.

19 torte -> 16 -> 14 -> 12 -> 11 -> 10 -> 9 -> 8
18 torte -> 15 -> 13 -> 11 -> 10 -> 9 -> 8 -> 8 (regola 3)

Per 18 torte, l'ultimo troll non è riuscito a conservare nessuna torta. Pertanto, il numero minimo di torte per un 25% / 2 giorni è 19.

input: 25 2
output: 19

Esempio 2:

90% di tasse sulle torte, 1 rimborso di troll

100 torte -> 11 -> 2 -> 1 (regola 4)

Il terzo troll non è riuscito a conservare nessuna torta. Pertanto non è possibile viaggiare con un 90% / 1 giorno anche a partire dal numero massimo di torte.

input: 90 1
output: 0

Dati

Metti insieme un rapido grafico dei valori di input e output. Sono stato sorpreso che questo non fosse "liscio" (come una curva a campana o simile); ci sono diverse isole notevoli.

tabella dei dati

Dati per gli interessati. Le colonne sono divise in intervalli del 5%, le righe sono unità di 1 intervalli di rimborso della torta (Excel ha ruotato l'immagine). Puoi vedere che non può esserci un rimborso superiore a 28 torte.

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

Buon punto. Rendilo un programma completo per semplicità. L'input può essere specificato come meglio credi, purché non sia codificato (sfida aggiornata).

Questo è un buon enigma per la forza bruta in CJam. Lo farò domani

bah, ecco perché c # non può avere cose

La Regola 2 sembra escludere la possibilità che un troll riceva solo una frazione di una torta, il che dovrebbe rendere ridondante il presupposto 4. Eppure dici nell'esempio 2 che il terzo troll otterrebbe solo 0,8 torte.
Dennis,

Ci sono conflitti nelle specifiche. Nel 25 2caso di 11 torte, dai al troll 2,75 torte e torni 2 in modo che il troll mantenga .75 (+. 25) e sopravvivi. Nel 90 1caso di 2 torte, dai al troll 1.8 e torni indietro 1 in modo che il troll mantenga .8 (+. 2) ma muori.
TwiNight,

Risposte:


6

CJam, 46 43 41 39 38 36 33 byte

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

Ingresso tramite ARGV.

C'è un interprete online, ma sfortunatamente non supporta gli argomenti della riga di comando. Per i test, puoi imitarlo da STDIN con questa versione:

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

Spiegazione della versione basata su 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.";

Il contenuto della pila viene stampato automaticamente alla fine del programma.


Il tuo codice produce risultati errati per 55 2( 0anziché 100) e 56 5( 98invece di 94). Questo perché 100_0.55*-ie 25_0.56*-icadere vittima di imprecisione in virgola mobile. Per quanto ne so, anche le coppie 31 24, 31 25, 33 21, 33 22, 33 23, 35 10, 35 12, 35 15, 35 16, 35 27, 56 1, 57 4danno risultati errati.
Dennis,

1
@Dennis risolto, grazie!
Martin Ender,

@Dennis Che effettivamente ha salvato un byte. Vorrei che CJam avesse delle chiusure, quindi all'inizio potevo solo definire un blocco che fa la detrazione fiscale e usarlo, invece di usare due variabili. Forse posso salvare qualcosa usando ARGV invece di STDIN, fammi vedere.
Martin Ender,

5

CJam, 44 40 38 37 35 byte

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

O quando si usano gli argomenti e il {}#trucco della riga di comando , 33 byte :

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

Non mettere questo come il mio principale come {}#approccio è ispirato dalla risposta di Martin.

Esempio di esecuzione:

Ingresso:

25 2

Produzione:

19

Un altro:

Ingresso:

15 14

Produzione:

100

Come funziona

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

Provalo online qui


E ora non ci resta che aspettare che Dennis arrivi e ci batti entrambi. ;)
Martin Ender,

Non in CJam;) (si spera)
Ottimizzatore

Mi piace molto il ]W=trucco, ma finora, ogni modo in cui provo ad usarlo finisco con lo stesso numero di personaggi.
Martin Ender,

@ MartinBüttner - Sì, anch'io.
Ottimizzatore

1
@Dennis - Dovrebbe funzionare ora, con un vantaggio aggiuntivo di 2 byte codice più breve: D
Ottimizzatore

4

APL (39)

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

Spiegazione:

  • T R←⎕: leggi due numeri dalla tastiera e li memorizza in T(imposta) e R(ritorno).
  • Z←⍳M←100: memorizza il numero 100in Me tutti i numeri da 1a 100in Z.
  • {... }⍣7¨: per ogni elemento in Z, eseguire la seguente funzione 7 volte:
    • R+⌊1-T÷M: calcola quante torte devono essere pagate,
    • ⍵(⊢×>): moltiplica quell'importo per 1 se il troll finisce con più torta di quella che ha iniziato, o per 0 se no.
  • ⊃Z/⍨: per ogni elemento in Z, replicalo per il numero fornito da quella funzione. (Quindi 0scompaiono tutti i numeri per i quali è stata restituita la funzione .) Quindi selezionare il primo elemento dall'elenco. Se l'elenco è finito vuoto, questo dà 0.

3

C, 83 byte

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

Se funziona, funziona per tutti i possibili startcakes, non solo da 1 a 100.

EDIT: funziona. golfed:

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

Con il limite di "massimo 100 torte":

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 byte.


Penso che sia una parte importante delle specifiche che la soluzione restituisca zero se avessi bisogno di più di 100 torte all'inizio.
Martin Ender,

2

CJam, 36 byte

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

1

C ++ - 202 caratteri

Come al solito, il mio C ++ ha fatto il peggio:

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

1

APL, 36

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

Spiegazione

Si noti che esiste una "soglia della torta". Per l'aliquota fiscale xe il rimborso y, avrai bisogno di molto più delle y÷xtorte per passare il ponte successivo.

x y←⎕accetta input e assegna a x(tax) e y(return)
⍳x÷←100dividere xper 100, quindi genera un array da 1 a 100

{y+⍵-⌈⍵×x}⍣6chiama la funzione "pass bridge" 6 volte:
⌈⍵×xil numero di torte che hai, volte l'aliquota fiscale, arrotondare per eccesso (l'importo che paghi)
⍵-Sottrai dal numero di torte che hai
y+Aggiungi il rimborso

Quindi ottieni una matrice di 100 elementi che mostra il numero di torte che ti rimangono dopo aver attraversato 6 ponti se inizi con 1 ~ 100 torte. Per vedere se riesci ad attraversare l'ultimo ponte, controlla se sei sopra la soglia y÷x. In alternativa:
moltiplicare l'array per x
y<verificare se maggiore diy

Infine,
1⍳⍨trova l'indice della prima occorrenza di 1(true), restituisce 101se non trovato
101|mod 101


1

C 128

Abbastanza simile all'altra soluzione C ma penso che sia inevitabile. Il trucco principale è uscire dal circuito interno con valori diversi a seconda che vada al completamento o meno. Questo mi permette di usare?: Quando non potevo se usassi 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);} 

Ungolfed

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

Che compilatore stai usando?
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.