Рассчитайте плату за проезд тролля, чтобы безопасно пройти

12

Вдохновленный /puzzling//q/626


В своих приключениях вы попадете в серию из 7 мостов, которые вы должны пересечь. Под каждым мостом живет тролль. Чтобы пересечь мост, вы должны сначала дать троллю количество тортов в процентах от количества тортов, которые вы несете. Поскольку это добрые тролли, они вернут вам определенное количество тортов.

В начале каждого дня местный король троллей устанавливает процентный налог на торт, который должен платить каждый путешественник, и возврат тролля - количество тортов, которые каждый тролль должен вернуть путешественникам.

Ваша задача - рассчитать минимальное количество тортов, необходимое для прохождения всех 7 троллей-мостов для заданных условий в этот день.

Предполагать:

  1. Два входных параметра: процентный налог на торт (целое число от 0 до 100) и возврат тролля.
  2. Никто, даже тролли, не хочет торт, частично съеденный другим троллем. Если у вас останется кусок пирога, тролль получит его.
  3. Если тролль принимает налог с пирога, но затем должен вернуть вам все пироги (осталось столько же или меньше пирогов, чем раньше), он разозлится и съест вас и ваши пироги.
  4. У каждого тролля должен быть хотя бы один полный торт.
  5. Вы можете нести не более 100 тортов.
  6. Вам нужно закончить день, когда вы находитесь в данный момент или на другой стороне всех 7 мостов.

Вызов:

Напишите полную программу, чтобы вывести минимальное количество тортов для поездки на текущий день или ноль, если сегодня невозможно безопасно путешествовать - вы будете ждать, чтобы увидеть, какие цифры будут завтра.

Ввод должен быть передан как stdin, аргументы командной строки или файл.

Самый короткий код (число байтов) выигрывает.

Пример:

25% налог на торт, 2 тролля.

начать с 19 тортов
до тролля 1: (19 * 0,75) = 14,25
после тролля 1: (14 + 2) = 16

до тролля 2: (16 * 0,75) = 12
после тролля 2: (12 + 2) = 14

и т.п.

19 тортов -> 16 -> 14 -> 12 -> 11 -> 10 -> 9 -> 8
18 тортов -> 15 -> 13 -> 11 -> 10 -> 9 -> 8 -> 8 (правило 3)

За 18 тортов последний тролль не сможет оставить себе тортов. Следовательно, минимальное количество тортов на 25% / 2 дня составляет 19.

input: 25 2
output: 19

Пример 2:

90% налог на торт, 1 возврат тролля

100 тортов -> 11 -> 2 -> 1 (правило 4)

Третий тролль не смог сохранить торт. Поэтому невозможно путешествовать на 90% / 1 день, даже начиная с максимального количества тортов.

input: 90 1
output: 0

Данные

Составьте быстрый график входных и выходных значений. Я был удивлен, что это не было «гладко» (как кривая колокола или подобное); Есть несколько заметных островов.

диаграмма данных

Данные для заинтересованных. Столбцы разделены на 5% интервалы, строки - это единицы с интервалами возврата 1 пирога (Excel повернул изображение). Вы можете видеть, что не может быть возврата выше, чем 28 тортов.

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
Сообщество
источник
Хорошая точка зрения. Сделайте это полной программой для простоты. Ввод может быть указан, однако вы считаете нужным, если он не жестко запрограммирован (обновленный вызов).
Это хорошая загадка для грубой силы в CJam. Я сделаю это примерно завтра
Ба, вот почему у C # не может быть хороших вещей
Правило 2, по-видимому, исключает возможность получения троллем лишь доли пирога, что должно сделать предположение 4 излишним. Тем не менее, в примере 2 вы говорите, что третий тролль получит только 0,8 торта.
Деннис
Есть конфликты в спец. В случае с 25 211 пирогами вы даете троллю 2,75 пирога и получаете обратно 2, так что тролль держит 0,75 (+. 25), и вы выживаете. В случае с 90 1двумя пирогами вы даете троллю 1,8 и получаете обратно 1, так что тролль держит 0,8 (+ 2), но вы умираете.
TwiNight

Ответы:

6

CJam, 46 43 41 39 38 36 33 байта

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

Ввод через ARGV.

Есть онлайн-интерпретатор, но, к сожалению, он не поддерживает аргументы командной строки. Для тестирования вы можете имитировать его из STDIN с этой версией:

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

Объяснение версии на основе 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.";

Содержимое стека автоматически печатается в конце программы.

Мартин Эндер
источник
Ваш код дает неправильные результаты для 55 2( 0вместо 100) и 56 5( 98вместо 94). Это потому, что 100_0.55*-iи 25_0.56*-iстановятся жертвами неточностей с плавающей запятой. Насколько я могу судить, пары также 31 24, 31 25, 33 21, 33 22, 33 23, 35 10, 35 12, 35 15, 35 16, 35 27, 56 1, 57 4дают неверные результаты.
Деннис
1
@ Денис исправил, спасибо!
Мартин Эндер
@Dennis Это на самом деле спасло байт. Я хотел бы, чтобы у CJam были замыкания, тогда я мог бы просто определить блок в начале, который делает налоговый вычет, и использовать его вместо двух переменных. Может быть, я могу что-то сохранить, используя ARGV вместо STDIN, дай мне посмотреть.
Мартин Эндер
5

CJam, 44 40 38 37 35 байт

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

Или при использовании аргументов командной строки и {}#трюка, 33 байта :

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

Не ставить этот вопрос в качестве основного {}#подхода вдохновил ответ Мартина.

Пример выполнения:

Входные данные:

25 2

Выход:

19

Другой:

Входные данные:

15 14

Выход:

100

Как это устроено

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

Попробуйте онлайн здесь

оптимизатор
источник
А теперь осталось дождаться, когда Деннис придет и победит нас обоих. ;)
Мартин Эндер
Не в CJam;) (надеюсь)
Оптимизатор
Мне очень нравится этот ]W=трюк, но до сих пор, каждый раз, когда я пытаюсь его использовать, я получаю одинаковое количество символов.
Мартин Эндер
@ MartinBüttner - Да, я тоже.
Оптимизатор
1
@Dennis - должен работать сейчас, с дополнительным преимуществом на 2 байта более короткого кода: D
Optimizer
4

APL (39)

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

Объяснение:

  • T R←⎕: прочитайте две цифры с клавиатуры и сохраните их в T(налог) и R(возврат).
  • Z←⍳M←100: сохранить номер 100в M, и все числа от 1до 100в Z.
  • {... }⍣7¨: для каждого элемента в Z, запустите следующую функцию 7 раз:
    • R+⌊1-T÷M: подсчитайте, сколько тортов нужно заплатить,
    • ⍵(⊢×>): умножьте эту сумму на 1, если у тролля будет больше торта, чем он начал, или на 0, если нет.
  • ⊃Z/⍨: для каждого элемента в Z, скопируйте его по номеру, который дала эта функция. (Таким образом, все числа, для которых возвращена функция, 0исчезают.) Затем выберите первый элемент из этого списка. Если список оказался пустым, это дает 0.
Мэринус
источник
3

C 83 байта

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

Если это работает, это работает для всех возможных стартовых кексов, а не только от 1 до 100.

РЕДАКТИРОВАТЬ: Это работает. 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;}

С пределом «максимум 100 тортов»:

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 байт.

Gerwin
источник
Я думаю, что важной частью спецификации является то, что решение возвращает ноль, если вам нужно более 100 тортов в начале.
Мартин Эндер
2

CJam, 36 байт

q~:R100:H*\d:T/i){R-H*HT-/m]}6*_H)<*
Деннис
источник
1

C ++ - 202 символа

Как обычно, мой C ++ сделал худшее:

#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

объяснение

Обратите внимание, что существует «порог торта». Для получения налоговой ставки xи возмещения yвам потребуется строго больше, чем y÷xпирожные для прохождения следующего моста.

x y←⎕принять входные данные и присвоить x(налог) и y(возврат)
⍳x÷←100делить xна 100, а затем сгенерировать массив от 1 до 100

{y+⍵-⌈⍵×x}⍣6вызовите функцию «Pass Bridge» 6 раз:
⌈⍵×xколичество тортов, умноженное на налоговую ставку, округление (сумма, которую вы платите).
⍵-Вычтите из количества тортов, которое вы имеете.
y+Добавьте возврат

Затем вы получите массив из 100 элементов, показывающий количество тортов, с которыми вы останетесь после пересечения 6 мостов, если вы начнете с 1 ~ 100 тортов. Чтобы увидеть, можете ли вы пересечь последний мост, проверьте, находитесь ли вы выше порога y÷x. Альтернативно:
умножьте массив на x
y<проверку, если больше чемy

Наконец,
1⍳⍨найти индекс первого появления 1(true), возвращает, 101если не найден
101|мод 101

TwiNight
источник
1

С 128

Довольно похоже на другое решение C, но я думаю, что это неизбежно. Основной трюк - выход из внутреннего цикла с различными значениями в зависимости от того, идет ли он до завершения или нет. Это позволяет мне использовать?: Когда я не мог, если я использовал перерыв;

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);
}
Alchymist
источник
какой компилятор вы используете?