Самородки коду


18

Самородки коду

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

Зараз улюблена закуска кожного - курячі нагетси, але є проблема: не існує жодної упаковки, яка б відповідала всім потребам. Отже, оскільки ви вже в настрої для гольфу, ви вирішили створити програму, яка точно визначає, які пакети ви повинні придбати, щоб мати змогу покрити всі потреби Нуггета.

Розміри пачок для курячих самородків є всюди, і залежно від того, де ви живете в світі, змінюються і стандартні розміри. Однак найближче [місце, яке обслуговує самородки] зберігає такі розміри пакетів самородків:

4, 6, 9, 10, 20, 40

Тепер ви можете помітити, що ви не можете замовити певні комбінації самородків. Наприклад, 11самородки неможливі, оскільки немає комбінації, яка б 11точно дорівнювала . Однак ви можете зробити 43, отримавши 1 пачку 20, 1 пачку 10, 1 упаковку 9і 1 пачку 4,

20 + 10 + 9 + 4 = 43 (597)

де 597кожен термін складається в квадрат і додається разом (натяк: оптимальне рішення має це як найвище значення) . Звичайно, існують і інші способи виготовлення 43, але, як відомо, чим більше самородків в упаковці, тим дешевше вони отримують за саморобку. Отже, ви хочете в ідеалі придбати найменшу кількість пачок і в найбільшій кількості, щоб мінімізувати свої витрати.

Завдання

Ви повинні створити програму або функцію, яка містить список цілих чисел, що відповідають вимогам кожної людини. Потім слід обчислити та роздрукувати найвигідніший порядок α , щоб придбати курячі самородки. Найвигідніший порядок α - це комбінація, за якою сума квадратів кожної величини є найвищою. Якщо немає абсолютно ніякого способу , щоб купити самородки відмінно, ви повинні надрукувати на falsy значення , наприклад 0, False, Impossible!або все , що є на вашій мові.

Приклад вводу / виводу:

[2 7 12 4 15 3] => [20 10 9 4]
     1, 1, 2, 1 => False
  6 5 5 5 5 5 9 => 40
      [6, 4, 9] => 9 10
              1 => 0
            199 => 40, 40, 40, 40, 20, 10, 9
              2 => Impossible!

Ось перелік ідеальних рішень для перших 400. Зверніть увагу, вони не форматовані так, як я б очікував, що це буде ваше, кожне tupleу формі (N lots of M).

Правила

  1. Немає стандартних лазівки
  2. Немає використання вбудованих функцій, які виконують все або більшість завдань, наприклад, FrobeniusSolveу Mathematica.

α - Щоб уточнити це на прикладі, ви також можете зробити 43, зробивши це 4 + 6 + 6 + 9 + 9 + 9 = 43 (319), але це не було б оптимальним і, таким чином, невірним результатом, оскільки сума квадратів менша, ніж комбінація, яку я зазначив у вступі. По суті, більша сума квадратів = менша вартість = найбільш економічна.


Чи є обмеження часу / пам’яті?
Денніс

@Dennis Немає обмежень ні часу, ні пам’яті.
Кейд

4
Це насправді четвер.
mbomb007

4
@ mbomb007 Проникливі спостереження: P Я відрегулював вступ.
Кейд

2
Я ПОТРІБНО якось використовувати теорему про курячу макгггет ...
Stretch Maniac

Відповіді:


7

Pyth, 26 25 байт

e+Zo.aNf!-TCM"  
("./sQ

Зауважте, що є кілька недрукованих символів. Спробуйте в Інтернеті: Демонстрація . Це досить повільно (але не так повільно, як моє 26-байтне рішення).

Пояснення:

                          implicit: Q = input list
                     sQ   sum(Q)
                   ./     generate all integer partitions
       f                  filter for partitions T, which satisfy:
             "   ("          string containing chars with the ASCII-values of 4,6,9,10,20,40
           CM                convert each char to the ASCII-value
         -T                  remove this numbers from T
        !                    and check, if the resulting list is empty
    o                      order the remaining subsets N by:
     .aN                      the vector length of N (sqrt of sum of squares)
  +Z                       insert 0 at the beginning
 e                         print the last element

Pyth, 32 байти

e+Zo.aNfqsTsQysm*]d/sQdCM"  
(

Зауважте, що є кілька недрукованих символів. Спробуйте в Інтернеті: Демонстрація Ця версія набагато швидша. Він знайде рішення для входу [6,7,8]приблизно за одну секунду, а рішення для входу - [30]приблизно за 90 секунд.

Пояснення:

                                 implicit: Q = input list
                          "...(  the string containing chars with the ASCII-values of 4,6,9,10,20,40
                        CM       convert each char to the ASCII-value
                m                map each number d to:
                  ]d                create the list [d]
                 *  /sQd            and repeat it sum(Q)/d times
               s                 unfold
              y                  generate all subsets
        f                        filter for subsets T, which satisfy:
         qsTsQ                      sum(Q) == sum(T)
    o                            order the remaining subsets N by:
     .aN                            the vector length of N (sqrt of sum of squares)
  +Z                             insert 0 at the beginning
 e                               print the last element

Чому це відповідає квадрату суми квадратів, а не просто суми?
mbomb007

1
@ mbomb007 Тому що це не має значення. Якщо a> b, ніж sqrt (a)> sqrt (b) і навпаки. А використання .aметоду коротше, ніж квадратування та підсумовування s^R2.
Якубе

5

Perl, 175 153

sub f{my$n=$_[0];if(!$n){return 1;}foreach$o(40,20,9,10,6,4){if($n>=$o&&f($n-$o)){print"$o ";return 1;}}return 0;}$n+=$_ for@ARGV;if(!f($n)){print":(";}

Приймає це введення з аргументів програми. Друкує : ( якщо він не може знайти ідеального рішення.

Код без вогню:

sub f
{
    my $n = $_[0];
    if(!$n)
    {
        return 1;
    }
    foreach $o(40,20,9,10,6,4)
    {
        if($n>=$o&&f($n-$o))
        {
            print "$o ";
            return 1;
        }
    }
    return 0;
}

$n += $_ for @ARGV;
if(!f($n))
{
    print ":(";
}

PS: Це, мабуть, перший запис, який не потребує 10 хвилин 1 2;)

Перевірте це тут.


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

Ваш код може дати неправильний вихід. Вхід 18повинен друкувати 9 9, а не 4 4 10.
Денніс

Є й інші невірні виходи. Якщо я не помиляюся, ви можете їх виправити, змінивши порядок 9і 10.
Денніс

@Dennis Дякую, виправив!
Томас Олтманн

3

CJam, 45 29 28 байт

q~:+_[40K9A6Z)U]m*_::+@#=0-p

Зауважимо, що такий підхід дуже повільний і затягує пам'ять.

Спробуйте його в Інтернеті інтерпретаторі CJam .

Її можна значно прискорити за 5 байт:

q~:+_40/4+[40K9A6Z)U]m*_::+@#=0-p

Складність все ще є експоненціальною в сумі введених даних, але це має вирішувати тестові випадки до 159 за допомогою онлайн-перекладача та до 199 з інтерпретатором Java за пару секунд.

Спробуйте його в Інтернеті інтерпретаторі CJam .

Ідея

Оптимальна покупка (максимальна сума квадратів) - це дійсна покупка (правильна кількість самородків), яка має стільки 40 -х, скільки можливо 20-ти, потім стільки 20 -х, скільки можливо 9-ти (наприклад, 9 9є переважніше над 10 4 4) та ін. протягом 10 ', 6 ' і 4 's.

При такому підході ми генеруємо декартовий добуток з N копій масиву [40 20 9 10 6 4 0] , де N - бажана кількість самородків. N - погана верхня межа для кількості покупок, які ми маємо зробити. У прискореній версії коду ми використовуємо N / 40 + 4 замість цього .

Через те, як впорядковано масив, декартовий добуток розпочнеться з вектора [40 ... 40] і закінчиться вектором [0 ... 0] . Ми обчислюємо індекс першого вектора, який має правильну суму (який також матиме оптимальну суму квадратів), витягуємо відповідний елемент масиву, видаляємо нулі, які служили заповнювачами та друкуємо результат.

Якщо не вдалося знайти жодного вектора, індекс буде -1 , тому ми отримаємо [0 ... 0] , який замість нього надрукує порожній масив.

Код

q~                            e# Read from STDIN and evaluate the input.
  :+                          e# Push N, the sum of all elements of the resulting array.
     [40K9A6Z)U]              e# Push B := [40 20 9 10 6 4 0].
    _           m*            e# Push B**N, the array of all vectors of dimension N
                              e# and coordinates in B.
                  _::+        e# Copy and replace each vector by its sum.
                      @#      e# Get the first index of N.
                        =     e# Retrieve the corresponding element.
                         0-p  e# Remove 0's and print.

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

2

Джулія, 126 байт

r->(t=filter(i->all(j->j[4,6,9,10,20,40],i),partitions(sum(r)));show(!isempty(t)&&collect(t)[indmax(map(k->sum(k.^2),t))]))

Це створює неназвану функцію, яка приймає масив як вхідний і друкує масив або булеве значення STDOUT, залежно від того, чи існує рішення. Щоб зателефонувати, дайте ім’я, наприклад f=n->....

Недоліки + пояснення:

function f(r)
    # Nugget pack sizes
    packs = [4, 6, 9, 10, 20, 40]

    # Filter the set of arrays which sum to the required number of nuggets
    # to those for which each element is a nugget pack
    t = filter(i -> all(j -> jpacks, i), partitions(sum(r)))

    # Print the boolean false if t is empty, otherwise print the array of
    # necessary nugget packs for which the sum of squares is maximal
    show(!isempty(t) && collect(t)[indmax(map(k -> sum(k.^2), t))])
end

Приклади:

julia> f([1])
false

julia> f([2,7,12,4,15,3])
[20,10,9,4]

1

Python 3 - 265 символів

import itertools as i
n=list(map(int,input().split(',')));m=[]
for f in range(1,9):
 for j in range(6*f):
  for x in i.combinations((4,6,9,10,20,40,)*f,j+1):
   if sum(n)==sum(x):m.append(x)
if m!=[]:v=[sum(l**2for l in q)for q in m];print(m[v.index(max(v))])
else:print(0)

Показ інтервалу:

import itertools as i
n=list(map(int,input().split(',')));m=[]
for f in range(1,5):
 for j in range(6*f):
\tfor x in i.combinations((4,6,9,10,20,40,)*f,j+1):
\t if sum(n)==sum(x):m.append(x)
\t\tif m!=[]:v=[sum(l**2for l in q)for q in m];print(m[v.index(max(v))])
else:print(0)

Проходить усі тестові справи

Примітка. Я не знаю, чи це пройде всі справи, тому що це так повільно ... Але це повинно ...


Зараз з цим нічого не здається, я перевірю його і побачу. Як тільки я повернуся додому, я додам довідкову програму, яка не використовується для генерування, яку я використовував для генерування списку, який міститься в Gist. Хоча я не проводив часу, я вважаю, що це пройшло десь у 8-12 хвилинному діапазоні для всіх випадків.
Кейд

@ Vioz- Блискуче! : D
бета-розпад

Схоже, я можу помилятися, після тестування 36 він отримує близько 40 мільйонів комбінацій (точніше 40,007,602) перед тим, як потрапити в MemoryError. Це може бути обмеженням моєї робочої машини, оскільки вона має лише 4 Гб пам'яті.
Кейд

@ Vioz- Гм ... Ну, я безнадійно продовжувати тестування на своєму телефоні ...
Beta Decay

1
@undergroundmonorail Якщо ви використовуєте його лише один раз, тоді для <= 4 символів краще прямий імпорт (5 рівних перерв). Але якщо ви використовуєте його не раз, то from blah import*завжди найкраще. Єдиним винятком, про який я можу придуматись із вищезазначеного, є те, якщо у вас є кілька imports, це єдиний час, коли вам приходить в голову, де asнасправді корисно.
Sp3000

1

JavaScript, 261 256 261

d="length";function g(a){for(z=y=0;y<a[d];z+=+a[y++]);return z}x=[40,20,10,9,6,4];l=prompt().split(",");o=g(l);p=[];for(i=0;i<x[d];i++)r=g(p),s=r+x[i],(s<o-3||s==o)&&p.push(x[i]),(i==x[d]-1||40<o-r)&&r+x[i]<o-3&&(i=-1,0==i||o-r<p[p[d]-1]&&p.pop());g(p)==o&&p||0

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

Здається, це не повільно, до 123456 цього виходить [40 x 3086, 10, 6]майже негайно.

Пояснення:

Ітерація над розмірами самородків (найбільший перший)

  • Якщо сума стека плюс розмір самородка менше мети - 3 -> натисніть його на стек
  • Якщо залишилось більше 40 -> скиньте лічильник циклу
  • Якщо сума стека перевищує мету, коли досягнуто останнього розміру самородка -> вивести останній елемент, скинути лічильник циклу
  • Якщо сума стека додається, поверніть його, інакше поверніть 0

За 199 | 1 побудований стек виглядає приблизно так

i | stack
0   [40]
0   [40, 40]
0   [40, 40, 40]
0   [40, 40, 40, 40]
0   [40, 40, 40, 40]
1   [40, 40, 40, 40, 20]
2   [40, 40, 40, 40, 20, 10]
3   [40, 40, 40, 40, 20, 10, 9]
4   [40, 40, 40, 40, 20, 10, 9]
5   [40, 40, 40, 40, 20, 10, 9]
==> [40, 40, 40, 40, 20, 10, 9]

Для 1

i | stack
0   []
1   []
2   []
3   []
4   []
5   []
==> 0

1
Схоже, ваш підхід не перевіряє, чи можна досягти мети. 11відбитки [6]та 18відбитки [10, 4].
Денніс

@Dennis Привіт, дякую, що вказали на це. Вчора пізня ніч. Виправлено це на 5 символів. 18 надруковано, [10,4]бо мені не вистачало пари паронів. Перевірка була дійсно помилковою, я просто перевіряв, чи був принаймні один елемент у наборі результатів, а не якщо він підсумовується правильно. Я не знаю, що я там думав
C5H8NNaO4
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.