Обчисліть плату за тролі, щоб безпечно пройти


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 інтервалом повернення торта (відмінно повернути зображення). Ви можете бачити, що повернення не може перевищувати 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. Я буду робити це завтра

Ба, ось чому в # не може бути приємних речей

Правило 2, здається, виключає можливість троля отримати лише частину торта, що повинно зробити припущення 4 надмірним. Однак у прикладі 2 ви кажете, що третій троль отримав би лише 0,8 торта.
Денніс

У специфікації є конфлікти. У випадку з 25 211 тортами ви даєте тролеві 2,75 пирогів і отримуєте назад 2, щоб троль тримався .75 (+. 25), і ви виживаєте. У випадку з 90 12 пирогами ви даєте тролі 1,8 і отримуєте назад 1, щоб троль тримався .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 виправлено, дякую!
Мартін Ендер

@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
Оптимізатор

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.

EDIT: Це працює. Гольф:

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


Я думаю, що важливою частиною специфікації є те, що рішення повертає нуль, якщо на початку вам потрібно більше 100 тортів.
Мартін Ендер


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зателефонуйте функції "пройти міст" 6 разів:
⌈⍵×xкількість тортів, кількість ставок податку, округлення (сума, яку ви платите)
⍵-Віднімайте від кількості тортів, які ви отримали
y+Додати відшкодування

Тоді ви отримуєте 100-елементний масив, що показує кількість тортів, які вам залишилися після перетину 6 мостів, якщо ви почнете з 1 ~ 100 тортів. Щоб побачити, чи можете ви перетнути останній міст, перевірте, чи не виходите ви за поріг y÷x. Як варіант:
помножте масив, x
y<перевіривши, чи більший заy

Нарешті,
1⍳⍨знайдіть індекс першого появи 1(true), повертає, 101якщо його не знайдено
101|mod 101


1

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

Безумовно

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

який компілятор ви використовуєте?
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.