Знайдіть максимальну операцію


12

Завдання полягає у пошуку максимальної кількості, яку можна отримати зі списку цілих чисел, використовуючи основні арифметичні оператори (додавання, віднімання, множення, одинарне заперечення)

Вхідні дані

Список цілих чисел

Вихідні дані

Максимальний результат з використанням кожного цілого числа вхідного сигналу.

Порядок введення не має значення, результат повинен бути однаковим.

Вам не потрібно виводити повну операцію, а лише результат.

Приклади

Input : 3 0 1
Output : 4 (3 + 1 + 0)

Input : 3 1 1 2 2
Output : 27 ((2+1)*(2+1)*3))

Input : -1 5 0 6
Output : 36 (6 * (5 - (-1)) +0)

Input : -10 -10 -10
Output : 1000 -((-10) * (-10) * (-10))

Input : 1 1 1 1 1
Output : 6 ((1+1+1)*(1+1))

Правила

  • Найкоротший код виграє

  • Застосовуються стандартні «лазівки»

  • Ви можете використовувати лише оператори + * - (додавання, множення, віднімання, одинарне заперечення)

  • Код повинен працювати до тих пір, поки результат може бути збережений у 32-бітовому цілому.

  • Будь-яка поведінка переповнення залежить від вас.

Я сподіваюся, що це досить зрозуміло, це моя перша пропозиція Code Golf щодо виклику.


Одним із ваших прикладів є використання операції, яка не дозволена: якщо передбачається, що унарне заперечення буде у вашому білому списку, віднімання насправді не потрібно.
Пітер Тейлор

Відредаговано та додано одинарне заперечення. Субстракція зберігається у білому списку.
CNicolas

1
Це має бути повноцінною програмою або достатньо функцій?
ThreeFx

Повна програма. Ще краще, якщо його можна запустити в Інтернеті, але, очевидно, не обов’язково
CNicolas

@INSeed Я повинен додати спосіб запуску в Інтернеті?
гордий haskeller

Відповіді:


9

C - 224 байти - час роботи O (n)

o=0,w=0,n[55],t,*m=n,*p=n;main(r){for(;scanf("%d",++p);t<3?--p,w+=t/2,o+=t&1:t<*m|m==n?m=p:9)t=*p=abs(*p);t=o<w?o:w;o-=t;w-=t;t+=o/3;for(o%3?o%3-2?t?t--,w+=2:++*m:w++:9;t--;)r*=3;for(r<<=w;--p>n;)r*=*p;printf("%d",r>1?r:o);}

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

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

log (a + b) <log (a) + log (b), за винятком випадків, коли a = 1 або b = 1, тож це єдиний випадок, коли ми зацікавлені в тому, щоб щось додати разом. Взагалі краще додати 1 до меншої кількості, оскільки це спричиняє більший приріст логарифму, тобто більший відсотковий приріст, ніж додавання 1 до великої кількості. Існує чотири можливі сценарії, упорядковані якнайменше кращі, для їх використання:

  1. Додавання одного до 2 дає + log .405 [log (3) - log (2)]
  2. Об'єднання в трійці дає + log .366 за один [log (3) / 3]
  3. Створення 2 з них дає + log .347 за один [log (2) / 2]
  4. Додавання його до числа 3 або вище дає + log .288 або менше [log (4) - log (3)]

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


6

Haskell, 126 символів

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

import Data.List
f[x]=abs x::Int
f l=maximum$subsequences l\\[[],l]>>= \p->[f p+f(l\\p),f p*f(l\\p)]
main=interact$show.f.read

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


5

SWI-Prolog - 250

О, хлопче, я занадто довго витрачав на це.

o(A,B,A+B).
o(A,B,A-B).
o(A,B,A*B).
t([],0).
t([A,B|T],D):-t(T,Q),o(A,B,C),o(C,Q,D).
t([A|T],C):-t(T,Q),o(A,Q,C).
a(A):-t(A,B),n(C),B>C,retract(n(C)),assert(n(B)).
m(A):-assert(n(0)),\+p(A),n(R),R2 is R,write(R2).
p(A):-permutation([0|A],B),a(B),0=1.

Викликається з командного рядка (наприклад):

> swipl -s filename.pl -g "m([1, 1, 1, 1, 1])" -t halt
6

(Без особливих причин я вважаю дивовижним те, що в моїй функції гольфу назви написані "томатний горщик".)

Негольована версія:

% Possible operations
operation(Left, Right, Left + Right).
operation(Left, Right, Left - Right).
operation(Left, Right, Left * Right).

% Possible ways to transform
transform([], 0).
transform([A, B|T], D) :- transform(T, Q), operation(A, B, C), operation(C, Q, D).
transform([A|T], C) :- transform(T, Q), operation(A, Q, C).

% Throw the given array through every possible transformation and update the max
all_transforms(A) :- transform(A, B), n(C), B>C, retract(n(C)), assert(n(B)).

% Find all the permutations and transformations, then fail and continue execution.
prog(A) :- assert(n(0)), !, permutation([0|A], B), all_transforms(B), fail.

% End the program
finished :- n(R), write(R), nl, R2 is R, write(R2), nl.

% Run the program
main(A) :- ignore(prog(A)), finished.

Пояснення:

  1. Візьміть масив як аргумент.
  2. Отримати всі перестановки масиву.
  3. Знайдіть деяке розташування операторів для додавання до масиву. (Це робиться за допомогою динамічного програмування. Ми бачимо, чи краще, поєднуючи перші два елементи чи ні.)
  4. Перевірте це на нашому поточному максимальному значенні. Якщо краще, замініть його.
  5. Скажіть програмі, що ми не змогли, щоб вона продовжувала перевірку, але потім заперечуйте це (використовуючи ignoreабо \+), щоб дозволити загальному поверненню предиката trueта продовжити.
  6. Нам дається рядок предикатів замість числа, тому призначте його за допомогою, isа потім запишіть його.

4

Скала, 134

print(args.map(Math abs _.toInt)./:(Seq(Array(0)))((l,a)=>l.map(a+:_)++l.flatMap(_.permutations.map{r=>r(0)+=a;r}))map(_.product)max)

Ungolfed та прокоментував:

print(
  args
    .map(Math abs _.toInt)                     // to int, ignoring -
    .foldLeft(Seq(Array(0))){ (list,num) =>    // build up a list of sums of numbers
      list.map(num+:_) ++                      // either add the new number to the list
      list.flatMap(_.permutations.map{ copy =>
        copy(0)+=num                           // or add it to one of the elements
        copy
      })
    }
    .map(_.product) // take the maximum of the the products-of-sums
    .max
)

Трохи інший підхід - від усвідомлення того, що найбільшу відповідь завжди можна виразити як добуток сум.

Так близько, але купа тупості бібліотеки (перестановки повертає Iterator замість Seq, жахливий висновок типу порожніх послідовностей, повернення Array.update Unit).


3

Python 278 (O (n!))

from itertools import*
def f(n):
 f,n,m=lambda n:[(n,)]+[(x,)+y for x in range(1,n)for y in f(n-x)],map(abs,map(int,n.split())),0
 for p,j in product(permutations(n),f(len(n))):
  i=iter(p)
  m=max(m,reduce(lambda e,p:e*p,(sum(zip(*zip([0]*e,i))[1])for e in j)))
 return m

Пояснення

  1. Унарний негат слід з розумом використовувати для перетворення всіх від’ємних чисел у позитивні
  2. Знайдіть усі можливі перестановки чисел
  3. Використовуючи розділ Integer для пошуку всіх наборів живлення даної перестановки
  4. Знайдіть добуток сум
  5. Поверніть максимум виробленої суми

3

Haskell - 295 290 265 246 203 189 182 байт


Нарешті працює! Крім того, тепер це груба сила, а не динамічне рішення.


Дякую гордіскешлеру за деякі поради з гольфу.

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

import Data.List
main=interact$show.g.read
g x=maximum[product$a#b|a<-sequence$replicate(length x-1)[0,1],b<-permutations x]
(a:b)#(c:d:e)|a>0=b#(c+d:e)|0<1=c:b#(d:e)
_#x=x

Нові тестові справи:

[1,1,1,2,2]
12

[1,1,3,3,3]
54

[1,1,1,1,1,1,1,1,5,3]
270

Пояснення рішення:

mainФункція просто отримує вхідний сигнал і працює gз ним.

g приймає вхід і повертає максимум усіх можливих комбінацій сум і списків.

# це функція, яка обчислює суми у такому списку:

a = [1,0,0,1]
b = [1,1,1,2,2]
a#b = [2,1,4]

це здається цілком сприятливим для виконання рішенням.
гордий haskeller

Ви можете, будь ласка, написати нові рядки, а не ;коли це можливо? це не змінює кількість байтів, але допомагає читатимо тріумфозно
гордий haskeller

@proudhaskeller Я не мав уявлення, як жорстоко це зробити, тому мені довелося придумати щось інше: D
ThreeFx

моя порада щодо гольфу в цьому - 1) вбудовуйте кожну функцію, яка використовується лише один раз (якщо тільки вона не використовує відповідність шаблонів або захисні елементи). 2) ви можете реалізувати d як d n=[0,2,1]!!nабо d n=mod(3-n)3. 3) складіть oі gприймайте довжину списку замість того, щоб брати сам список, оскільки вони залежать лише від довжини (очевидно, це стоїть лише до тих пір, поки вони не позначаються). 4) замінити otherwiseна 0<1. 5) скласти останнє визначення r бути r$o x:y. 6) видаліть a@і замініть на x:y. удачі в гольфі!
гордий haskeller

Ваш алгоритм дає неправильну відповідь для [3,3,3,2,2,2,1,1,1]. Я запустив ваш код, і він повертає 216 (найбільший результат, який я зміг придумати, - 729).
Brilliand

1

GolfScript (52 символи)

~]0-{abs}%.1-.1,or@,@,-,-1%{!\$.0=3<@+{()}1if+}/{*}*

Демонстрація в Інтернеті

Аналіз feersum досить хороший, але його можна прийняти далі, якщо мета - це гольф, а не ефективність. У псевдокоді:

filter zeros from input and replace negatives with their absolute value
filter ones to get A[]
count the ones removed to get C
while (C > 0) {
    sort A
    if (A[0] < 3 || C == 1) A[0]++
    else A.append(1)
    C--
}
fold a multiply over A
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.