Najmniej operacji do 100

15

Przegląd

Biorąc pod uwagę listę cyfr, znajdź najmniej operacji, aby uzyskać 100

Wejście

Ciąg cyfr, który może, ale nie musi, być w kolejności numerycznej. Kolejności cyfr nie można zmienić, jednak można dodać między nimi operatory plus (+) lub minus (-), aby całkowita suma była równa 100.

Wynik

Liczba dodanych operatorów, po których następuje pełna sekwencja cyfr i operatorów. Obie mogą być oddzielone spacją, tabulatorem lub nową sekwencją linii.

Przykłady

ważny

Wejście: 123456789
Wyjście:3 123–45–67+89

Nieprawidłowe dane
wejściowe: Dane 123456789
wyjściowe:
6 1+2+34-5+67-8+9
(Istnieją sposoby na rozwiązanie tego przy mniejszej liczbie operacji)

CyberJacob
źródło
Powiązane
Adám
Czy musimy używać wszystkich cyfr? Czy możemy używać tylko +i -? Czy możemy założyć, że zawsze będziemy w stanie dokonać 100na podstawie danych wejściowych?
TheLethalCoder
6
Mile widziane są kolejne przypadki testowe.
Arnauld
2
Czy możesz potwierdzić, że znaki nie mogą być poprzedzone pierwszą cyfrą? Czy dane dane wejściowe 299399byłyby -299+399prawidłowe?
Luis Mendo
1
Czy „0” jest cyfrą? Np. Czy „10808” jest prawidłowym wejściem? Czy „1 108-08” jest prawidłową odpowiedzią?
Chas Brown

Odpowiedzi:

10

JavaScript (ES6), 153 176 bajtów

EDYCJA: W trybie nie ścisłym JS interpretuje wyrażenia liczbowe z prefiksem 0 jako liczby ósemkowe (np. 017Jest analizowany jako 15 w systemie dziesiętnym). To jest stała wersja, która obsługuje wiodące zera.

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"))

Arnauld
źródło
Fajnie, a co z danymi wejściowymi 20172117?
mdahmoune
@LuisMendo Właściwie myślę, że oczekiwana odpowiedź to 2-017-2+117. Ale 017jest notacją ósemkową w JS, która daje 15 w systemie dziesiętnym. Więc mój obecny kod znajduje tylko 2-0-17-2+117. Spróbuję rozwiązać ten problem później dzisiaj.
Arnauld
@Arnauld Ah, nie widziałem tego innego rozwiązania. Usunięcie mojego komentarza
Luis Mendo,
@mdahmoune Dzięki za poruszenie tego tematu. Teraz naprawione.
Arnauld
3**(l=s.length,l-1) => 3**~-(l=s.length)
l4m2
5

MATL , 37 36 bajtów

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

Przypadek testowy zajmuje około 6 sekund w TIO.

Wypróbuj online!

Jak to działa

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
Luis Mendo
źródło
Świetnie, a co z 299399 jako wkładem?
mdahmoune
1
@mdahmoune 299399nie ma rozwiązania i dlatego nie jest poprawnym wejściem (operatorzy zostali wymienieni, aby „przechodzić” między cyframi, wejście to wymagałoby, -299+399gdy -nie ma między cyframi).
Jonathan Allan
@mdahmoune Jeśli znaki można wstawić tylko między cyframi (jak mówi tekst wyzwania), myślę, że nie ma rozwiązania. Jeśli można je również wstawić do pierwszej cyfry, rozwiązaniem jest -299+399i w takim przypadku potrzebuję niewielkiej zmiany w kodzie . Poprosiłem OP o wyjaśnienia
Luis Mendo
Warto również zauważyć, że jeśli miałoby to być zarówno przed, jak i między nimi, wówczas przykład 123456789powinien mieć liczbę operatorów 4nie 3.
Jonathan Allan
@mdahmoune OP potwierdził, że znaki mogą znajdować się tylko między cyframi. Więc mój kod jest poprawny i 299399jest nieprawidłowym wejściem, ponieważ, jak wyjaśnił PO, każde wejście powinno mieć co najmniej jedno rozwiązanie
Luis Mendo
3

[Python 2], 164 158 bajtów

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)

Wypróbuj online!

Weź N jako ciąg cyfr; zwraca krotkę (numOps, expressionString).

Zasadniczo takie samo podejście jak inne; używa itertools.product do konstruowania pojedynczych „przypadków”, np. dla N == „1322”, „przypadek” byłby ('-','','+')i oceniałby „1-32 + 2”.

Zgłasza błąd ValueError, jeśli dane wejściowe są nieprawidłowe (ale myślę, że OP nie ma nieprawidłowych danych wejściowych).

Chas Brown
źródło
3

PHP, 166 171 bajtów

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);

Uruchom jako potok -nRlub przetestuj go online .

używa sformatowanych liczb do sortowania wyników ->
może wydrukować początkowe spacje (i może się nie powieść przy wprowadzaniu więcej niż 99 cyfr; zwiększyć liczbę w %2dcelu naprawy).

nie więcej niż 10 cyfr, 161 bajtów

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);

awaria

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
Tytus
źródło
3

Galaretka , 32 bajty

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

Pełny program wyświetlający za pomocą operatorów Jelly ( _zamiast -).

Uwaga: Aby wyświetlić -na wyjściu zamiast _(nie jest to wymóg), dodaj ⁾_-ypomiędzy Fi ( ⁾_-jest literą pary znaków ['_','-']iy jest dyadycznym atomem „translate”).

W jaki sposób?

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

Wypróbuj online!

Jonathan Allan
źródło
2

Mathematica, 136 146 149 156 165 166 bajty

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

Zwraca {3, 123-45-67+89}na przykład.

Wykonanie przypadku testowego zajmuje około 0,09 sekundy.

Keyu Gan
źródło
2

Python 2 , 256 230 208 205 172 171 170 165 bajtów, metoda iteracyjna

  • 33 dzięki Chas Brown
  • Jeden zapisany bajt podczas zastępowania len(a)przezw
  • Jeden zapisany bajt podczas zastępowania z-=1;d=zprzezd=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)

Wypróbuj online!

Małe wyjaśnienie Korzystając z reprezentacji w bazie 3, kod przeplata cyfry z operatorami {'+', '-', konkatenacja} zgodnie ze wszystkimi możliwymi kombinacjami.

Python 2 , 167 bajtów, metoda rekurencyjna

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)

Wypróbuj online!

Niektóre wyjścia

"399299"    --> (1, '399-299')
"987654321" --> (4, '98-76+54+3+21')
"1111111"   --> (3, '1+111-1-11')
mdahmoune
źródło
1
Lubię używać divmod! Kilka golfów, które widzę: zamień na list(input())just input(), ponieważ ciąg jest już iterowalny, aby zapisać 6 bajtów; wymienić b.count('+')+b.count('-')z len(b)-len(a)zaoszczędzić 12 bajtów; i wymienić chr(r+43)z chr(r+43)*(d>0!=r-1)czym można usunąć linię b=b[:-1].replace(',',''), aby zapisać netto 15 bajty ( (d>0!=r-1)odpowiada (d>0 and 0!=r-1)).
Chas Brown
2

Brachylog , 36 bajtów

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

Wypróbuj online!

Ponad połowa z nich ma jednak na celu uzyskanie właściwego formatu wyjściowego. Rzeczywista podstawowa logika to tylko:

15 bajtów

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

Wypróbuj online!

Zwraca listę taką jak [123, –45, –67,89]. Wyrażenie jest sumą elementów, a liczba operatorów jest o 1 mniejsza niż długość listy.

~cLhℕ∧100~+Lprawie działa na 12 bajtów ( Wypróbuj online! ) - ale jest zbyt wolny, aby obsłużyć pełne 9-cyfrowe wejście w TIO, a co ważniejsze, nie udaje się na wejściach takich jak 10808- Brachylog jest zbyt inteligentny, aby rozdzielać liczby, aby miały początkowe zera, więc nie robi tego zobacz partycję [108, -08].

sundar - Przywróć Monikę
źródło
1

Haskell , 180 178 bajtów

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]

Wypróbuj online! Zastosowanie: g "123456789"plony (3,"123-45-67+89").

#buduje listę wszystkich możliwych terminów, ?ocenia je i gfiltruje te, które oceniają na 100, i zwraca ten z minimalną liczbą operandów.

Laikoni
źródło
0

Galaretka , 27 bajtów

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

Wypróbuj online!

Nie mogę powiedzieć, że nie skorzystałem z kilku wskazówek ze starszej odpowiedzi Jonathana Allana. ;-)

W porównaniu do jego odpowiedzi, ten jest tylko dwa bajty krótszy (30), a nie pięć, jeśli sprawimy, że porównanie będzie uczciwe z powodu aktualizacji językowych:

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

Jeśli porównamy w drugą stronę (nowsza wersja zamiast starszej), różnica jest taka sama (jego staje się 29 bajtów, jak pokazano poniżej):

ŒṖżⱮL’⁾+_ṗƲ$€ẎFV=ȷ2ƲƇLÞḢFṄḟ³L
Erik the Outgolfer
źródło