Максимально об'єднаний продукт


11

Нам надається перелік цілих чисел p1, ..., pk (не обов'язково окремий), де кожне має значення від 1 до 9 включно. Використовуючи кожен з p1, ..., pk рівно один раз, ми можемо сформувати об'єднання цифр, щоб досягти нового списку чисел; Потім ми виводимо продукт цього нового списку. Мета - максимізувати цей продукт, вибираючи найкращі сполучення цифр.

Наприклад, нам подано список: 2 3 2 (розділені пробілами). Ми можемо сформувати такі конкатенації:

  • 2 3 2(продуктом цих конкатенацій є 12)
  • 23 2(продукт є 46)
  • 32 2(продукт є 64)
  • 22 3(продукт є 66)

Оскільки найбільшим продуктом, який ми можемо створити, є 66, ми виводимо це.

Правила:

  • Повинно бути принаймні одне множення (тобто ви не можете просто об'єднати всі цифри і вивести це).
  • Ви не можете використовувати будь-які інші оператори, крім множення, або вставляти круглі дужки тощо.
  • Припустимо, що наведений список цілих чисел розділений пробілами, а всі цілі числа мають значення від 1 до 9.

Найкоротший код (у байтах) виграє!

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

Вхідні дані : 1 2 3; Вихід: 63(тобто, 21*3)

Вхідні дані : 2 5 9; Вихід: 468( 52*9)

Вхідні дані : 1 2 3 4; Вихід: 1312( 41*32)


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

@randomra Так, це добре.
Райан

Для кожної пари чисел a, b добуток a * b. менший від простого конкатенації ab (= a * 10 ^ (цифри b) + b). Так що лише 1 продукт (як це обов’язково). Додайте це: codegolf.stackexchange.com/q/49854/21348
edc65

Відповіді:


8

CJam, 32 28 23 12 байт

0le!f{~*}:e>

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

Дякуємо @ user23013, що допомагає мені зберегти 16 цілих байтів!

Ідея

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

Код

 le!         e# Push all possible character permutations of the input.
0   f{  }    e# For each permutation:
             e#   Push 0, then the permuted string.
      ~      e#   Evaluate the string. Pushes one or more integers.
       *     e#   Multiply the two topmost integers.
         :e> e# Retrieve the greatest integer in the array.

1
l2%_,,1>\e!m*{~S+m<~*}%$W=.
jimmy23013

2
l2%S+e!{0\~*}%$W=.
jimmy23013

2

CJam, 36 35 байт

q~]_,([SL]m*{s},\e!\m*{z[s~]:*}%$W=

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

Додамо пояснення незабаром.

Спробуйте його онлайн тут


1

JavaScript (ES6) 125

Редагувати Я думаю, що @oberon це правильно зрозумів: "кожну нову цифру потрібно об'єднати до найменшого числа"

Я не зміню цю відповідь, крадучи його думку. Реалізація в ES6 складе 70 байт (знак змінено порівняно для порівняння як числа, а не рядків)

f=l=>l.split(' ').sort().reverse().map(d=>-a>-b?a+=d:b+=d,a=b='')||a*b

Моє рішення

f=l=>(i=>{for(r=0;a=b='',k=--i;r<a*b?r=a*b:0)for(v of l)k&1?a+=v:b+=v,k/=2})(1<<~-(l=l.split(' ').sort().reverse()).length)|r

Як я вже говорив у коментарях, для кожної пари чисел a, b добуток a * b менший від простого конкатенації ab (= a * 10 ^ (цифри b) + b). Тож краще уникати продуктів і віддавати перевагу конкатенації, але оскільки потрібно щонайменше 1 продукт, ми повинні створити 2 числа і помножити їх.

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

Наприклад, зі списком із 4 чисел, [1 2 3 4] - спробуйте:

  • 4 * 321
  • 43 * 21
  • 42 * 31
  • 41 * 32
  • 432 * 1
  • 431 * 2
  • 421 * 3

Макс цих значень - це результат, який нам потрібен.

Групування можна перерахувати циклічно на растровій карті 4-х біт, з мінімальним значенням 0001 та максимальним значенням 0111 (тобто 1 << (4 -1) - 1)

Не такий гольф

f=l=>{
  l = l.split(' '); // string to array
  l.sort().reverse(); // decreasing order 
  m = 1 << (l.length-1); starting value fro loop
  r = 0 
  // loop from m-1 down to 1
  for(i=m; --i; )
  {
    a = b = '';
    k = i;
    for(v of l) // divide the digits base on bits of i
    {
      k & 1 ? a+=v : b+=v;
      k /= 2;
    }
    if (r < a*b) r = a*b; // remember max value in r
  }
  return r
}

Перевірте, використовуючи фрагмент нижче у Firefox.

f=l=>(i=>{for(r=0;a=b='',k=--i;r<a*b?r=a*b:0)for(v of l)k&1?a+=v:b+=v,k/=2})(1<<~-(l=l.split(' ').sort().reverse()).length)|r

t=l=>(i=>{for(x=r='';a=b='',k=--i;r<a*b?(r=a*b,x=' = '+a+'x'+b):0)for(v of l)k&1?a+=v:b+=v,k/=2})
(1<<~-(l=l.split(' ').sort().reverse()).length)|| x

function go()
{
  R.value = f(I.value) // TEST AS IS
   + t(I.value) // Some more info
}

test=['1 2 3 4','1 2 3','2 5 9','8 9 8']

test.forEach(t => O.innerHTML = O.innerHTML + (t + ' -> ' + f(t)) + '\n')
Type your list: <input id=I><button onclick='go()'>-></button><input readonly id=R><br>
<pre id=O></pre>


1

Пітон 3, 111 байт

Це, мабуть, набагато голірніше. Мені подобається час його роботи, хоча (O ( n log n ), чи не так?).

l=sorted(map(int,input().split()),reverse=1);m=[0,0]
for x in l:i=m[0]>m[1];m[i]=m[i]*10+x
print(m[0]*m[1])

Нероздягнений з поясненнями.

# edc65 has already explained that the optimal solution can be found applying a single
# multiplication. thus, given that
#     (10x + d)y > (10y + d)x
# where x, y are the two numbers and d is the next digit to insert, it follows that
#     y > x
# and thus each new digit must be concatenated to the smallest number. obviously, digits
# should be added in descending order.
l = sorted(map(int, input().split()), reverse=1)
m = [0,0]
for x in l:
    i = m[0] > m[1]
    m[i] = m[i]*10 + x
print(m[0] * m[1])

0

Pyth, 25 байт

eSsmm*ss<dkss>dkr1ld.pcz)

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


0

R, 164

function(n){l=length(n);a=sort(n,T);i=1;while(a[i]==a[i+1]&&i<l-2)i=i+2;a[c(i,i+1)]=a[c(i+1,i)];eval(parse(t=paste0(c(a[1:l%%2==1],"*",a[1:l%%2==0]),collapse='')))}

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

Загальний процес:

  • Сортуйте список у порядку зменшення
  • Поміняйте місцями першу непарну / парну пару
  • Об'єднайте парні та непарні елементи списку
  • Оцініть добуток двох результатів

Розширився з деякими коментарями

function(n){
    l=length(n);
    a=sort(n,T);    # sort descending order
    # Determine which pair to swap
    i=1;
    while(a[i]==a[i+1]&&i<l-2)i=i+2;
    a[c(i,i+1)]=a[c(i+1,i)];  # swap pair   
    # concatenate the even and odd indices items around a * and evaluate    
    eval(parse(t=paste0(c(a[1:l%%2==1],"*",a[1:l%%2==0]),collapse=''))) 
}

І деякі тестові запуски (реалізовані у вигляді функції g)

> g(c(1,2,3))
[1] 63
> g(c(2,5,9))
[1] 468
> g(c(1,2,3,4))
[1] 1312
> g(c(1,2,3,5,5,5))
[1] 293132
> g(c(1,5,7,7,9,9))
[1] 946725
> g(c(1,7,8,9,9,9))
[1] 978117
> g(c(7,8,9,9,9))  #Test case provided edc65 to randomra
[1] 97713
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.