Найменше операцій до 100


15

Огляд

Давши список цифр, знайдіть найменше операцій, щоб зробити 100

Вхідні дані

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

Вихідні дані

Кількість доданих операторів, а потім повна послідовність цифр та операторів. Їх можна розділити пробілом, вкладкою або новою послідовністю рядків.

Приклади

дійсний

Вхід: 123456789
Вихід:3 123–45–67+89

Недійсний
ввід: 123456789
Вихід:
6 1+2+34-5+67-8+9
(Є способи вирішити це за допомогою меншої кількості операцій)



Чи потрібно використовувати всі цифри? Чи можемо ми лише використовувати +і -? Чи можемо ми припустити, що ми завжди зможемо зробити 100з вхідних даних?
TheLethalCoder

6
Ще кілька тестових випадків будуть дуже бажані.
Арнольд

2
Чи можете ви підтвердити, що знаки не можуть бути попередньо додані до першої цифри? Тобто, дані дані 299399були -299+399б дійсними?
Луїс Мендо

1
Чи є "0" цифрою? Наприклад, чи "10808" є дійсним введенням? Чи "1 108-08" є дійсною відповіддю?
Час Браун

Відповіді:


10

JavaScript (ES6), 153 176 байт

EDIT: У нестрогому режимі JS інтерпретує 0-префіксні числові вирази як вісімкові (наприклад 017, розбирається як 15 у десятковій частині). Це фіксована версія, яка підтримує провідні нулі.

let f =

s=>[...Array(3**(l=s.length,l-1))].map((_,n)=>m=eval((x=s.replace(/./g,(c,i)=>c+['','+','-'][o=(n/3**i|0)%3,j-=!o,o],j=l)).replace(/\b0+/g,' '))-100|j>m?m:(S=x,j),m=l)&&m+' '+S

console.log(f("123456789"))
console.log(f("20172117"))


Приємно, а як 20172117 як вхід?
mdahmoune

@LuisMendo Насправді, я думаю, очікувана відповідь 2-017-2+117. Але 017це восьмеричне позначення в JS, яке дає 15 у десятковій частині. Тож мій поточний код лише знаходить 2-0-17-2+117. Я спробую вирішити цю проблему пізніше сьогодні.
Арнольд

@Arnauld Ах, я не бачив іншого рішення. Видалення мого коментаря
Луїс Мендо

@mdahmoune Дякую за те, що підняв це. Тепер виправлено.
Арнольд

3**(l=s.length,l-1)=>3**~-(l=s.length)
l4m2

5

MATL , 37 36 байт

n'+-'OhZ^!t2\s&SZ)"G@!vXzU100=?@z3M.

Тестовий випадок займає близько 6 секунд у TIO.

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

Як це працює

n        % Implicitly input a string. Number of elements, say k
'+-'     % Push this string
Oh       % Append char 0. This is treated like ' ' (space)
Z^       % Cartesian power of the three-char string '+- ' raised to k.
         % Gives a matrix where each row is a Cartesian k-tuple
!        % Transpose
t        % Duplicate
2\       % Modulo 2. This turns '+' and '-' into 1, and ' ' into 0
s        % Sum of each column: number of '+' and '-' symbols
&S       % Sort and push the indices of the sorting
Z)       % Apply as column indices. This sorts the columns (k-tuples)
         % by the number of '+' and '-' they contain
"        % For each column, i.e. each k-tuple formed by '+', '-' and ' '
  G      %   Push input string again
  @!     %   Push k-tuple as row vector (string)
  v      %   Concatenate vertically into a 2×k char array
  Xz     %   Remove space (and char 0). Gives a string as result. In this
         %   process, the 2×k array is linearized in column major order 
         %   (down, then across). So the '+' and '-' signs are between 
         %   digits of the input, or at the end
  U      %   Convert to number. This performs the operation determined by
         %   by the '+' and '-' signs and returns the result. A trailing
         %   '+' or '-' sign makes the input invalid, which causes an
         %   empty result
  100=   %   Is it equal to 100?
  ?      %   If so
    @    %     Push current k-tuple
    z    %     Number of nonzeros, i.e. of '+' and '-' signs
    3M   %     Push linearized string without spaces again
    .    %     Break for loop
         %   Implicit end
         % Implicit end
         % Implicitly dispplay stack

Чудово, що про 299399 як вхід?
mdahmoune

1
@mdahmoune 299399не має рішення і, отже, не є коректним вводом (операторам було вказано переходити "між" цифрами, для цього введення знадобиться -299+399там, де -немає між цифрами).
Джонатан Аллан

@mdahmoune Якщо знаки можна вставити лише між цифрами (як говориться в тексті виклику), я думаю, що рішення немає. Якщо вони також можуть бути попередньо додані до першої цифри, рішення є -299+399, і в цьому випадку мені потрібна невелика зміна коду . Я попросив ОП роз'яснити
Луїс Мендо

Також слід зазначити , що якщо це повинні були бути як до , так і між тоді приклад 123456789повинен мати лічильник оператору 4НЕ 3.
Джонатан Аллан

@mdahmoune ОП підтвердило, що знаки можуть бути лише між цифрами. Отже, мій код правильний і 299399є недійсним введенням, оскільки, як уточнив також ОП, кожен вхід повинен мати принаймні одне рішення
Луїс Мендо

3

[Python 2], 164 158 байт

from itertools import*
f=lambda N:min((len(s)-len(N),s)for s in(''.join(sum(zip(N,p+('',)),()))for p in product(('+','-',''),repeat=len(N)-1))if eval(s)==100)

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

Візьміть N як рядок цифр; повертає кортеж (numOps, expressString).

В основному той же підхід, що й інші; використовує itertools.product для побудови окремих "випадків", наприклад, для N == '1322', "case" був би ('-','','+')і оцінював би "1-32 + 2".

Викидає ValueError, якщо введення недійсне (але я думаю, що ОП гарантовано не містить недійсних даних).


3

PHP, 166 171 байт

for(;$n<3**$e=strlen($x=$argn);eval("return $s;")-100?:$r[]=sprintf("%2d $s",strlen($s)-$e))for($i=0,$s="",$k=$n++;a&$c=$x[$i];$k/=3)$s.="+-"[$i++?$k%3:2].$c;echo min($r);

Запустити як трубу -nRабо випробувати його в Інтернеті .

використовує відформатовані номери для сортування результатів ->
може друкувати провідні пробіли (і може не вдатися до введення з більш ніж 99 цифрами; збільшити число при %2dвиправлення).

не більше 10 цифр, 161 байт

for(;$n<3**$e=strlen($x=$argn);eval("return $s;")-100?:$r[]=(strlen($s)-$e)." $s")for($i=0,$s="",$k=$n++;a&$c=$x[$i];$k/=3)$s.="+-"[$i++?$k%3:2].$c;echo min($r);

зламатися

for(;$n<3**$e=strlen($x=$argn); # loop $n up
    eval("return $s;")-100?:        # 2. evaluate term, if 100 then
                                    # prepend number of operations, add to results
        $r[]=sprintf("%2d $s",strlen($s)-$e)
)
                                # 1. create term
    for($i=0,$s="",$k=$n++;         # init variables, increment $n
        a&$c=$x[$i];$k/=3)          # loop through digits/operator index
        $s.="+-"[$i++?$k%3:2].$c;   # prepend operator for base-3 digit (nothing for 2)
echo min($r);                   # print lowest result

3

Желе , 32 байти

L’⁾+_ṗż@€
ŒṖÇ€ẎµFV=ȷ2µÐfLÞḢFṄḟ³L

Повна програма, яка відображається за допомогою операторів Jelly (_ замість них -).

Примітка. Щоб показати -у висновку замість _(не вимога), додайте ⁾_-yміж Fта ( ⁾_-є буквами пара символів['_','-'] і yє діадичним атомним "перекладом").

Як?

L’⁾+_ṗż@€ - Link 1, form all sums from a partition: list of lists of characters
                                     e.g. ["12","345","67"]
L         - length                        3
 ’        - decremented                   2
  ⁾+_     - literal ['+','_']
     ṗ    - Cartesian power               ["++","+_","_+","__"]
      ż@€ - zip for €ach (swap @rguments) ["12+345+67","12+345_67","12_345+67","12_345_67"]

ŒṖÇ€ẎµFV=ȷ2µÐfLÞḢFṄḟ³L - Main link: list of characters
ŒṖ                     - all partitions
  Ç€                   - call the last link (1) as a monad for €ach
    Ẏ                  - tighten (flatten by 1 level)
     µ     µÐf         - filter keep if:
      F                -   flatten
       V               -   evaluate as Jelly code (perform the sum)
         ȷ2            -   literal 100
        =              -   equal?
               Þ       - sort by:
              L        -  length
                Ḣ      - head
                 F     - flatten
                  Ṅ    - print that and a newline
                   ḟ³  - filter out the characters from the input
                     L - length (number of operators)
                       - implicit print

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


2

Математика, 136 146 149 156 165 166 байт

#&@@Sort[{StringLength@#-e+9!(ToExpression@#-100)^2,#}&/@StringJoin/@(Riffle[b,#]&)/@Tuples[{"","+","-"},(e=Length[b=Characters@#])-1]]&

Повертається, {3, 123-45-67+89}наприклад.

На тестовий випадок потрібно близько 0,09 секунд.


2

Python 2 , 256 230 208 205 172 171 170 165 байт, ітеративний метод

  • 33 завдяки Шасу Брауну
  • Один збережений байт при заміні len(a)наw
  • Один збережений байт при заміні z-=1;d=zнаd=z=z-1
q=[];a=input()
w=len(a);z=n=3**w
while z-n/3:
 d=z=z-1;j=0;b=''
 while d:r=d%3;d/=3;b+=a[j]+chr(r+43)*(d>0!=r-1);j+=1
 if eval(b)==100:q+=[(len(b)-w,b)]
print min(q)

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

Невелике пояснення Використовуючи представлення в базі 3, код перемежовує цифри з операторами {'+', '-', конкатенація} відповідно до всіх можливих комбінацій.

Python 2 , 167 байт, рекурсивний метод

def f(s):
 if len(s)==1:return[s]
 b=s[0];q=[]
 for z in f(s[1:]):q+=[b+'+'+z,b+'-'+z,b+z]
 return q
a=input()
print min((len(x)-len(a),x)for x in f(a)if eval(x)==100)

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

Деякі виходи

"399299"    --> (1, '399-299')
"987654321" --> (4, '98-76+54+3+21')
"1111111"   --> (3, '1+111-1-11')

1
Мені подобається використання divmod! Я можу побачити кілька гольфів: замінити list(input())на справедливі input(), оскільки рядок уже ітерабельний, щоб зберегти 6 байт; замінити b.count('+')+b.count('-')з , len(b)-len(a)щоб зберегти 12 байт; і замінити chr(r+43)на, chr(r+43)*(d>0!=r-1)а потім можна видалити рядок, b=b[:-1].replace(',','')щоб зберегти чисті 15 байт ( (d>0!=r-1)еквівалентно (d>0 and 0!=r-1)).
Час Браун

2

Брахілог , 36 байт

~cịᵐ{|ṅ}ᵐ{+100&{ℕṫ,"+"↻|ṫ}ᵐcbE&kl;E}

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

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

15 байт

~cịᵐ{|ṅ}ᵐ.+100∧

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

Це повертає список типу [123, –45, –67,89]. Вираз - це сума елементів, а кількість операторів на 1 менше, ніж довжина списку.

~cLhℕ∧100~+Lмайже працює на 12 байт ( спробуйте в Інтернеті! ) - але це занадто повільно, щоб обробляти повний 9-значний вхід на TIO, і що ще важливіше, він не вдається для входів, таких як 10808- Брахілог занадто розумний, щоб розділити числа, щоб мати провідні нулі, так що не ' t див. розділ [108, -08].


1

Haskell , 180 178 байт

m#[a]=[[a]]
m#(b:r)|s<-m#r=m(b:)=<<[s,m('+':)s,m('-':)s]
o '-'=(-)
o _=(+)
(p:r)?a|[(b,s)]<-lex r=s?o p a(read b)
_?a=a
g s=minimum[(sum[1|c<-t,c<'0'],t)|t<-map#s,('+':t)?0==100]

Спробуйте в Інтернеті! Використання: g "123456789"урожайність (3,"123-45-67+89").

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


0

Желе , 27 байт

L’““+“_”ṗ⁸żF¥ⱮV⁼ȷ2ƊƇLÞḢṄḟ⁸L

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

Не можу сказати, що я не взяв декількох підказок зі старої відповіді Джонатана Аллана. ;-)

Якщо порівнювати його з відповіддю, то це лише на два байти коротше (30), а не на п’ять, якщо зробити порівняння справедливим через оновлення мови:

L’““+“_”ṗ⁸żF¥Ð€V⁼ȷ2$$ÐfLÞḢṄḟ⁸L

Якщо порівнювати інший спосіб (новіша версія замість старої), різниця така ж (його стає 29 байт, видно нижче):

ŒṖżⱮL’⁾+_ṗƲ$€ẎFV=ȷ2ƲƇLÞḢFṄḟ³L
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.