Meno operazioni a 100


15

Panoramica

Dato un elenco di cifre, trova il minor numero di operazioni per fare 100

Ingresso

Una stringa di cifre, che possono essere o non essere in ordine numerico. L'ordine delle cifre non può essere modificato, tuttavia è possibile aggiungere tra gli operatori più (+) o meno (-) in modo che la somma totale sia uguale a 100.

Produzione

Il numero di operatori aggiunti, seguito dalla sequenza completa di cifre e operatori. I due possono essere separati da uno spazio, una scheda o una nuova sequenza di linee.

Esempi

valido

Ingresso: 123456789
Uscita:3 123–45–67+89


Input non valido : 123456789
Output:
6 1+2+34-5+67-8+9
(Esistono modi per risolverlo con meno operazioni)



Dobbiamo usare tutte le cifre? Possiamo usare solo +e -? Possiamo presumere che saremo sempre in grado di ricavare 100dall'input?
TheLethalCoder

6
Altri casi di test sarebbero i benvenuti.
Arnauld,

2
Potete confermare che i segni non possono essere anteposti alla prima cifra? Cioè, dato input 299399, sarebbe -299+399valido?
Luis Mendo,

1
'0' è una cifra? Ad esempio, "10808" è un input valido? '1 108-08' è una risposta valida?
Chas Brown,

Risposte:


10

JavaScript (ES6), 153 176 byte

EDIT: in modalità non rigorosa, JS interpreta le espressioni numeriche con prefisso 0 come ottale (ad es. 017È analizzato come 15 in decimale). Questa è una versione fissa che supporta gli zeri iniziali.

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


Bello, che dire di 20172117 come input?
mdahmoune,

@LuisMendo In realtà, penso che la risposta prevista sia 2-017-2+117. Ma 017è una notazione ottale in JS, che fornisce 15 in decimale. Quindi il mio codice attuale trova solo 2-0-17-2+117. Proverò a risolvere questo problema più tardi oggi.
Arnauld,

@Arnauld Ah, non avevo visto quell'altra soluzione. Rimuovendo il mio commento
Luis Mendo il

@mdahmoune Grazie per averlo sollevato. Ora risolto.
Arnauld,

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

5

MATL , 37 36 byte

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

Il test case richiede circa 6 secondi in TIO.

Provalo online!

Come funziona

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

Fantastico, che ne dici di 299399 come input?
mdahmoune,

1
@mdahmoune 299399non ha soluzione e quindi non è un input valido (gli operatori sono stati specificati per andare "tra" le cifre, quell'input richiederebbe -299+399dove -non è tra le cifre).
Jonathan Allan,

@mdahmoune Se i segni possono essere inseriti solo tra le cifre (come dice il testo della sfida), penso che non ci sia soluzione. Se possono anche essere anteposti alla prima cifra, la soluzione è -299+399, e in quel caso ho bisogno di una piccola modifica nel mio codice . Ho chiesto chiarimenti all'OP
Luis Mendo il

È anche degno di nota il fatto che se fosse pensato per essere sia prima che tra allora l'esempio 123456789dovrebbe avere un conteggio dell'operatore di 4no 3.
Jonathan Allan il

@mdahmoune L'OP ha confermato che i segni possono essere solo tra le cifre. Quindi il mio codice è corretto ed 299399è un input non valido perché, come anche l'OP ha chiarito, ogni input dovrebbe avere almeno una soluzione
Luis Mendo,

3

[Python 2], 164 158 byte

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)

Provalo online!

Prendi N come una stringa di cifre; restituisce una tupla (numOps, expressionString).

Fondamentalmente lo stesso approccio degli altri; usa itertools.product per costruire i singoli "casi", ad esempio per N == "1322", un "caso" sarebbe ('-','','+')e valuterà "1-32 + 2".

Genera un ValueError se l'input non è valido (ma penso che OP non abbia fornito input non validi).


3

PHP, 166 171 byte

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

Esegui come pipe con -nRo testalo online .

utilizza numeri formattati per ordinare i risultati ->
può stampare spazi vuoti iniziali (e potrebbe non riuscire per l'input con più di 99 cifre; aumentare il numero %2dper risolvere).

non più di 10 cifre, 161 byte

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

abbattersi

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

Gelatina , 32 byte

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

Un programma completo che viene visualizzato utilizzando gli operatori Jelly ( _anziché -).

Nota: per mostrare -nell'output anziché _(non un requisito) aggiungere ⁾_-ytra Fe ( ⁾_-è una coppia di caratteri letterale ['_','-']ey è l'atomo diadico di "traduzione").

Come?

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

Provalo online!


2

Mathematica, 136 146 149 156 165 166 byte

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

Restituisce {3, 123-45-67+89}ad esempio.

Il completamento del test case richiede circa 0,09 secondi.


2

Python 2 , 256 230 208 205 172 171 170 165 byte, metodo iterativo

  • 33 grazie a Chas Brown
  • Un byte salvato quando viene sostituito len(a)daw
  • Un byte salvato quando viene sostituito z-=1;d=zdad=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)

Provalo online!

Piccola spiegazione Usando la rappresentazione in base 3, il codice interlaccia le cifre con gli operatori {'+', '-', concatenazione} in base a tutte le possibili combinazioni.

Python 2 , 167 byte, metodo ricorsivo

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)

Provalo online!

Alcune uscite

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

1
Mi piace l'uso di divmod! Alcuni golf posso vedere: sostituisci list(input())con just input(), poiché una stringa è già iterabile per salvare 6 byte; sostituire b.count('+')+b.count('-')con len(b)-len(a)per salvare 12 byte; e sostituirlo chr(r+43)con chr(r+43)*(d>0!=r-1)e quindi è possibile eliminare la riga b=b[:-1].replace(',','')per salvare netti 15 byte ( (d>0!=r-1)equivale a (d>0 and 0!=r-1)).
Chas Brown,

2

Brachylog , 36 byte

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

Provalo online!

Più della metà di questo è però per ottenere il formato di output giusto. La vera logica di base è solo:

15 byte

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

Provalo online!

Questo restituisce un elenco come [123, –45, –67,89]. L'espressione è la somma degli elementi e il numero di operatori è 1 in meno della lunghezza dell'elenco.

~cLhℕ∧100~+Lfunziona quasi per 12 byte ( provalo online! ) - ma è troppo lento per gestire l'input completo a 9 cifre su TIO e, soprattutto, non riesce per input come10808 - Brachylog è troppo intelligente per dividere i numeri per avere zeri iniziali, quindi non t vedere la partizione [108, -08].


1

Haskell , 180 178 byte

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]

Provalo online! Uso:g "123456789" rese (3,"123-45-67+89").

#crea un elenco di tutti i termini possibili, ?valuta un termine e gfiltra quei termini che valutano 100 e restituisce quello con il numero minimo di operandi.


0

Gelatina , 27 byte

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

Provalo online!

Non posso dire che non ho preso alcuni suggerimenti dalla risposta più vecchia di Jonathan Allan. ;-)

Rispetto alla sua risposta, questo è solo due byte più corto (30), non cinque, se rendiamo il confronto corretto a causa degli aggiornamenti del linguaggio:

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

Se confrontiamo diversamente (versione più recente anziché precedente), la differenza è la stessa (la sua diventa 29 byte, vista sotto):

ŒṖżⱮL’⁾+_ṗƲ$€ẎFV=ȷ2ƲƇLÞḢFṄḟ³L
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.