Скільки пирогів з трьох фруктів можна зробити?


32

Трижирний пиріг виготовляється з трьох різних фруктів. Що таке три фруктові пироги, які ви можете зробити з кількості 5 фруктів?

Наприклад, с

1 apple
1 banana
4 mangoes 
2 nectarines
0 peaches

ви можете зробити 2 пироги:

apple, mango, nectarine
banana, mango, nectarine

Введення: П’ять невід’ємних цілих чисел або їх список.

Вихід: Максимальна кількість пирогів з трьома фруктами, які ви можете зробити з цих кількостей фруктів. Виграє найменше байт.

Тестові приклади:

1 1 4 2 0
2
2 2 2 2 2
3
0 6 0 6 0
0
12 5 3 2 1
5
1 14 14 3 2
6
0 0 1 0 50
0

Табло:


Я вважаю, що у вашому прикладі відсутні два додаткові варіанти: Apple, Banana, Mango і Apple, Banana, Nectarine. Таким чином, 1 1 4 2 0тестовий випадок повинен отримати результат: 4.
кобальтдук

@cobaltduck Але якщо ви використовуєте яблуко та банан у своєму першому пирозі (яблуко / банан / манго), у вас немає яблук чи банану для використання у вашому другому пирозі (яблуко / банан / нектарин).
AdmBorkBork

2
@Timmy D: Ах, зрозуміло. Не було зрозуміло, що пиріжки роблять одночасно.
кобальтдук

@cobaltduck Я вважаю, що їх не потрібно робити одночасно, але ви не можете обдурити, використовуючи плоди, які ви використовували для першого.
Містер Лістер

@Містер. Лістер: Семантика. Досить, що існувало правило, яке було неоднозначним (принаймні для одного читача) і з тих пір було з'ясовано.
кобальтдук

Відповіді:


34

Піт, 19 18 14 байт

-1 байт від @FryAmTheEggman

14-байтна програма від @isaacg

Я стверджую, що кількість пиріжків, які можна сформувати із висхідного списку, [x1,x2,x3,x4,x5]становить:

floor(min((x1+x2+x3+x4+x5)/3,(x1+x2+x3+x4)/2,x1+x2+x3))

Або в коді:

JSQhS/Ls~PJ_S3

[Див. Історію версій програм TI-BASIC та APL]

Доказ правильності

Дозволяє

s3 = x1+x2+x3
s4 = x1+x2+x3+x4
s5 = x1+x2+x3+x4+x5

Ми хочемо показати, що P(X)=floor(min(s5/3,s4/2,s3))завжди найбільша кількість пирогів для списку x1≤x2≤x3≤x4≤x5чисел фруктів 1 ~ 5.

Спочатку ми показуємо, що всі три числа є верхніми межами.

  • Оскільки є s5всього фрукти, і кожен пиріг має три фрукти, ⌊s5/3⌋це верхня межа.

  • Оскільки є s4фрукти, які не є фруктами 5, а в кожному пирозі потрібно щонайменше два не-5 фруктів, ⌊s4/2⌋це верхня межа.

  • Оскільки є s3фрукти, які не є ні фруктами 4, ні фруктами 5, і хоча б один такий фрукт потрібен в кожному пирозі, s3є верхньою межею.

По-друге, ми покажемо, що метод збору фруктів з трьох найбільших паль завжди задовольняє зв'язаним. Робимо це за допомогою індукції.

Базовий випадок: 0 пирогів очевидно можуть бути сформовані з будь-якого дійсного списку P(X)>=0.

Індуктивний крок: При будь-який список , Xде P(X) > 0ми можемо спекти один пиріг, залишаючи за собою список X'з P(X') >= P(X)-1. Ми робимо це, беручи фрукти з найбільших трьох паль 3,4,5, потім вдаючись, якщо потрібно. Ведміть зі мною; є деякі справи.

  • Якщо x2<x3, тоді нам не потрібно сортувати список після видалення фруктів. У нас вже є дійсна X'. Ми знаємо, що P(X') = P(X)-1тому що s5'на 3 менше (тому що було видалено три плоди типу 1 ~ 5), s4'на 2 менше, а s3'на 1 менше. Так що P(X')рівно на один менше Р (Х).
  • Якщо x3<x4, тоді ми робимо аналогічно.
  • Тепер ми беремо випадок, де x2=x3=x4. Цього разу нам потрібно буде переставити список.

    • Якщо x5>x4, тоді ми переставляємо список, перемикаючи палі 4 і 2. s5'і s4'все ще є зменшенням на 3 і 2 відповідно, але s3'=s3-2. Це не проблема, тому що якщо x2=x3=x4- тоді 2*x4<=s3-> 2*x4+s3 <= 2*s3-> (x4 + s4)/2 <= s3. У нас є два підкази:
    • Рівність, тобто (x4,x3,x2,x1)=(1,1,1,0)в такому випадку P(X)= 1і ми можемо чітко зробити пиріг з паль 5,4,3, або:

    • (s4+1)/2 <= s3, в цьому випадку зменшення s4на додаткове 1не означає додаткове зниження до P (X).

  • Тепер ми залишаємося з випадком, де x1<x2=x3=x4=x5. Тепер s3також зменшиться на 1, тому нам потрібно (s5/3+1)бути <=s4/2; тобто 8x5+2x1+2<=9x5+3x1, або x5+x1>=2. Усі випадки менші, ніж це, можна перевірити вручну.

  • Якщо кожне число дорівнює, то зрозуміло, що ми можемо досягти межі ⌊s5/3⌋, яка завжди менша, ніж два інших - ми просто проходимо числа в послідовності.

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


Я думаю, що ваша претензія відповідає ітеративному рішенню @ fryamtheeggman.
Спарр

@Sparr Я намагаюся довести, що моя зв'язок є доступною за допомогою методу fryamtheeggman.
lirtosiast

2
Це можна пограти в 4 байти, перетворивши його в петлю:JSQhS/Ls~PJ_S3
isaacg

3
Я вважаю, що я знайшов доказ щодо nінгредієнтів та kінгредієнтів на пиріг, але це поле для коментарів занадто довго . Будь ласка, вкажіть будь-які помилки, які ви можете виявити, щоб ми могли це підтвердити.
Mego

7

CJam, 34

q~L{J2be!\f{\.-_W#){j)7}|;}0+:e>}j

Спробуйте в Інтернеті

Пояснення:

q~          read and evaluate the input array
L{…}j       calculate with memoized recursion and no initial values
             using the input array as the argument
  J2b       convert 19 to base 2 (J=19), obtaining [1 0 0 1 1]
  e!        get permutations without duplicates
             these are all the combinations of three 1's and two 0's
             which represent the choices of fruit for one pie
  \         swap with the argument array
  f{…}      for each combination and the argument
    \       swap to bring the combination to the top
    .-      subtract from the argument array, item by item
    _       duplicate the resulting array
    W#)     does it contain the value -1? (calculate (index of W=-1) + 1)
    {…}|    if not
      j     recursively solve the problem for this array
      )7    increment the result, then push a dummy value
    ;       pop the last value (array containing -1 or dummy value)
  0+        add a 0 in case the resulting array is empty
             (if we couldn't make any pie from the argument)
  :e>       get the maximum value (best number of pies)

Чи запам'ятовування рекурсії коштує в байтах? Не існує обмеження часу виконання.
xnor

2
@xnor Я думаю, що насправді тут економиться 1 байт :)
aditsu

7

Хаскелл, 62 байти

f x=maximum$0:[1+f y|y<-mapM(\a->a:[a-1|a>0])x,sum y==sum x-3]

Це визначає функцію, fяка бере в списку фрукти xі повертає максимальну кількість пирогів.

Пояснення

Ми обчислюємо кількість пиріжків рекурсивно. Частина mapM(\a->a:[a-1|a>0])xоцінюється до списку всіх списків, отриманих xза допомогою декрементування будь-яких позитивних записів. Якщо x = [0,1,2], це призводить до

[[0,1,2],[0,1,1],[0,0,2],[0,0,1]]

Частина між зовнішньою []є розумінням списку: ми повторюємо все yу наведеному вище списку і відфільтровуємо ті, сума яких не дорівнює sum(x)-3, тому ми отримуємо всі списки, де 3 різних фрукти були перетворені в пиріг. Тоді ми рекурсивно оцінюємо fза цими списками, додаємо 1до кожного і беремо максимум їх і 0(базовий випадок, якщо ми не можемо скласти пиріжки).


7

C #, 67

Рекурсивно робіть один пиріг на ітерацію з фруктами, яких у вас найбільше, доки ви не закінчитеся.

int f(List<int>p){p.Sort();p[3]--;p[4]--;return p[2]-->0?1+f(p):0;}

Тестові приклади тут


Не знайомий з C #, але ви можете, можливо, зробити p[2]--це одночасно з перевіркою p[2]>-1?
xnor

хороший момент, я оновлю відповідь через секунду.
AXMIM

6

Піта, 29

Wtt=QS-Q0=Q+tPPQtM>3.<Q1=hZ;Z

Тестовий набір

Сортує список введення та видаляє нулі. Потім, доки у вас є три плоди, декрементуйте перший та два останні елементи та додайте решту елементів до списку, перш ніж сортувати його та знову видаляти нулі. Потім збільшують лічильник на 1.

Це насправді досить швидко, тому що всього 5 фруктів, це може вирішити дуже великі бункери з фруктами, тобто 1000,1000,1000,1000,1000за секунду.


Чи можете ви довести, що це правильно?
aditsu

@aditsu я цього не довів, але я перевірив його щодо вашого на кілька додаткових значень. Я раніше не писав доказів на щось подібне, але спробую. Поки що я скажу, що має сенс, що це має працювати, тому що ви завжди берете лише з найбільших грудок фруктів, поки не вичерпаєте менші. Хоча жадібні стратегії, очевидно, не завжди властиві правильним, я не можу придумати, чому це не працює тут.
FryAmTheEggman

@FryAmTheEggman Чи правильно я розумію, що ви берете два найпоширеніші фрукти та найрідкісніші фрукти?
xnor

@xnor Так, це правильно. Це не працює?
FryAmTheEggman

1
@TimmyD Ні, я не думаю (думаю, що) не повинен, однак це не коштує жодних байтів для видалення цієї функціональності (це фактично коштує дорожче). Зважаючи на це , я очікую , що рішення Рето Кораді у більшості мов коротше, і очевидно, що Томас набагато стисліший. Я думаю, що причина, коли вам не доведеться переробляти, пов’язана з нею, незалежно від того, з яких 3-х менших паль ви берете.
FryAmTheEggman

6

Пітон, загальне рішення, 128 92 байт

-36 байт від @xnor, ви справжній mvp

g=lambda l,k:0if k>sum(l)else-(-1in l)or-~g(map(sum,zip(sorted(l),[0]*(len(l)-k)+[-1]*k)),k))

def g(a,k):b=[i for i in a if i];return 0if len(b)<k;c=sorted(b,reverse=True);return 1+g([c[i]-(k-1>i)for i in range(len(c))],k)

Це працює до тих пір, поки моє доказ правильне. Якщо це не так, дайте мені знати, чому я можу спробувати це виправити. Якщо це незрозуміло, дайте мені знати, і я атакую ​​його після кількох чашок кави.


Зараз мені все здається тісним.
lirtosiast

@Mego Дякую за роботу над цим! Чи можете ви включити докази в посаду SE? Існує загальне занепокоєння, що хтось, читаючи ці роки пізніше, може знайти мертві посилання. Форматування LaTeX в основному має працювати лише в MathJax.
xnor

@Mego На жаль, я забув, що MathJax тут не ввімкнено. Хм, я запитаю, що робити.
xnor

Я нагороджую винагородою за цей доказ. Вітаю!
xnor

@Mego Nope, я думаю, що ваше посилання на MathCloud - це найкраще, що ми маємо.
xnor

5

Python 2, 78 байт

Введення 5 цифр як вхідних даних: 91 89 88 байт

s=sorted([input()for x in[0]*5])
while s[2]:s[2]-=1;s[3]-=1;s[4]-=1;s.sort();x+=1
print x

Edit : Зміна s=sorted([input()for x in[0]*5])по s=sorted(map(input,['']*5));x=0зберігає 1 байт.

Бере 5 чисел як вхідних даних і друкує кількість можливих пирогів, які можна зробити. Він застосовує той самий підхід, що і відповідь Рето Кораді - без поліпшення кількості байтів - але здавалося, що на це питання не було відповіді в Python.

Дякую @ThomasKwa та @xsot за вашу пропозицію.

Як це працює

 s=sorted([input()for x in[0]*5]) takes 5 numbers as input, puts them in a list 
                                  and sorts it in ascending order. The result
                                  is then stored in s 

 while s[2]:                      While there are more than 3 types of fruit 
                                  we can still make pies. As the list is                     
                                  sorted this will not be true when s[2] is 0. 
                                  This takes advantage of 0 being equivalent to False.

 s[2]-=1;s[3]-=1;s[4]-=1          Decrement in one unit the types of fruit 
                                  that we have the most

 s.sort()                         Sort the resulting list

 x+=1                             Add one to the pie counter

 print x                          Print the result

Зауважте, що змінна xніколи не визначається, але програма займає випередження деякого пітону витоку 2.7. При визначенні списку sз розумінням списку останнє значення в ітерабельному ( [0]*5в даному випадку) зберігається в змінній, яка використовується для ітерації.

Щоб зробити речі зрозумілішими:

>>>[x for x in range(10)]
>>>x
9

Введення списку як вхідного даних: 78 байт

Дякую @xnor @xsot та @ThomasKwa, що запропонували змінити вхід до списку.

s=sorted(input());x=0
while s[2]:s[2]-=1;s[3]-=1;s[4]-=1;s.sort();x+=1
print x

Як це працює

Він працює так само, як і вищезгаданий код, але в цьому випадку введення вже є списком, тому немає необхідності його створювати, і змінну xпотрібно визначати.

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


1
Ви можете мати дані вже у списку; s[2]>0-> s[2], оскільки число в купі завжди невід’ємне.
ліртосіаст

Томас Ква зауважив, що ви можете припустити, що введення вже подано як список, так що ви можете просто зробити s=sorted(input()). Також ваш поточний кількість байтів дорівнює 89; Нові рядки вважаються єдиним знаком.
xnor

@ThomasKwa вже вказував, що ви могли б прийняти введення у вигляді списку, але якщо ви наполягаєте на прийнятті введення декількох рядків, замінити перший рядок з наступним зберегти байт: s=sorted(map(input,['']*5));x=0.
xsot

4

CJam, 23 байти

0l~{\)\$2/~+:(+_2=)}g;(

Спробуйте в Інтернеті

Це бере плоди з 3 найбільших паль у кожній ітерації та підраховує кількість повторень.

У мене немає математичного підтвердження того, що це завжди дає правильний результат. Це робиться для наведених тестових прикладів, і я вважаю, що він працює для всіх випадків, поки хтось не подасть мені зустрічний приклад.

Інтуїтивне пояснення, яке я використовував, щоб переконати себе: Щоб максимально збільшити кількість пиріжків, вам потрібно зберегти стільки паль, скільки не порожніх. Це тому, що ви втрачаєте можливість робити більше пиріжків, як тільки у вас є 3 або більше порожніх паль.

Це досягається, завжди беручи фрукти з найбільших паль. Я не можу придумати випадок, коли вживання фруктів з меншої купки призвело б до кращої ситуації, ніж брати фрукти з більшої купки.

У мене в голові трохи більше формальних міркувань. Я спробую придумати спосіб укласти його в слова / формули.


Я намагався використовувати індукцію; можливо, ми можемо поєднати наші ідеї, щоб знайти офіційний доказ.
ліртосіаст

@ThomasKwa Я не придумав нічого достатньо чіткого, що могло б виглядати переконливо, якщо я його запишу. Все зводиться до того, що я не бачу абсолютно жодної причини, чому б коли-небудь було краще взяти з меншої стопки більше великої. Хоча явно існують ситуації, коли брати з меншої стеки було б гірше. Я також ввів кілька випадкових помірно великих чисел у рішення моїх та адицу, і вони дали однаковий результат. Моє рішення також відповідає вашій формулі для прикладів, які я спробував.
Ретро Коради

3

> <>, 76 байт

0&4\/~}&?!/
@:@<\!?:}$-1@@$!?&+&:)@:@
,:&:@(?$n;/++:&+::2%-2,:&:@(?$&~+:3%-3

Виходить сортування в <<> не просто! Ця програма спирається на докази, висунуті Томасом Ква, що є правдивим, що, безумовно, має місце в тестових випадках.

Очікується, що 5 вхідних номерів будуть присутні у стеці на початку програми.

Перші два рядки сортують числа на стеку, а третій виконує обчислення floor(min((x1+x2+x3+x4+x5)/3,(x1+x2+x3+x4)/2,x1+x2+x3)), взяті з відповіді Томаса.


Чи буде коротше, якби обчислити всі суми з трьох / чотирьох елементів, а мінус цих?
lirtosiast

@ThomasKwa Я виглядає так, що це передбачає пошук перестановок вхідного набору, підсумовуючи найвищі 3 та 4 елементи кожного та беручи найменший з них? Я не думаю, що пошук перестановок був би коротшим, ніж підхід сортування / обчислення, який я використовував, особливо на мові, що базується на стеці. Якщо ви знаєте якісь зручні алгоритми для генерації перестановок мовою на основі стека, мені було б цікаво подивитися: o)
Sok

2

Python 2, 59 байт

h=lambda l,k=3:k*'_'and min(h(sorted(l)[:-1],k-1),sum(l)/k)

Загальний метод, який працює для будь-яких nі k. Значення k=3плодів на пиріг за замовчуванням до 3, але ви можете передати інше значення. Рекурсія використовує той факт, що рядки більше, ніж числа в Python 2, дозволяючи порожній рядку представляти базовий випадок нескінченності.

Цей метод використовує той факт, що завжди вживання найбільш звичайних плодів є оптимальним, тому ми розглядаємо кожен можливий сорт фруктів як обмежуючий фактор. Я спростував цей факт нижче.


Доказ Мего змусив мене задуматися над цим прямим доказом того, що багаторазовий прийом найпоширеніших плодів є оптимальним. Про це говорять пироги з kфруктами.

Теорема: Неодноразовий прийом kнайпоширеніших фруктів дає оптимальну кількість пиріжків.

Доказ: Ми покажемо, що якщо Nпиріжки можливі, то найпоширеніша фруктова стратегія дає принаймні Nпиріжки. Ми робимо це, перемикаючи фрукти серед Nпиріжків, щоб вони відповідали тим, які виробляються цією стратегією, зберігаючи пиріжки дійсними.

Давайте зробимо так, щоб перший пиріг (назвіть його p) містив найпоширеніші фрукти. Якщо цього ще немає, він повинен містити плід i, але не більш звичайний плід j. Тоді в решті пиріжків строго більше фруктів, jніж фруктів i, і тому якийсь інший пиріг qповинен містити, jале ні i. Потім ми можемо поміняти фрукти iз пирога pна фрукти jз пирога q, в якому Nпироги мають чіткі фрукти.

Повторюйте цей процес до pтих пір, поки не kз’являться найпоширеніші плоди.

Потім pвідкладіть пиріг і повторіть цей процес для наступного пирога, щоб він мав найпоширеніші плоди. Продовжуйте робити це, поки пиріжки не стануть послідовністю, що створюється найпоширенішими фруктами.


1

PowerShell, 92 байт

$a=($args|sort)-ne0;while($a.count-ge3){$a[0]--;$a[-1]--;$a[-2]--;$a=($a-ne0;$c++}($c,0)[!$c]

Використовує такий же жадібний алгоритм, що і відповідь FryAmTheEggman ... просто набагато складніше в PowerShell ....

$a=($args|sort)-ne0  # Take input arguments, sort them, remove any 0's
while($a.count-ge3){ # So long as we have 3 or more fruit piles
  $a[0]--            # Remove one from the first element...
  $a[-1]--           # ... the last element ...
  $a[-2]--           # ... and the second-to-last.
  $a=$a-ne0          # Remove any 0's from our piles
  $c++               # Increment how many pies we've made
}                    #
($c,0)[!$c]          # Equivalent to if($c){$c}else{0}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.