Menos operações para 100

15

Visão geral

Dada uma lista de dígitos, encontre o menor número de operações para fazer 100

Entrada

Uma sequência de dígitos, que pode ou não estar em ordem numérica. A ordem dos dígitos não pode ser alterada, no entanto, os operadores mais (+) ou menos (-) podem ser adicionados entre cada um para que a soma total seja igual a 100.

Resultado

O número de operadores adicionados, seguido pela sequência completa de dígitos e operadores. Os dois podem ser separados por um espaço, tabulação ou nova sequência de linhas.

Exemplos

válido

Entrada: 123456789
Saída:3 123–45–67+89


Entrada inválida : 123456789
saída:
6 1+2+34-5+67-8+9
(existem maneiras de resolver isso com menos operações)

CyberJacob
fonte
Relacionado
Adám
Temos que usar todos os dígitos? Podemos usar apenas +e -? Podemos supor que sempre seremos capazes de fazer a 100partir da entrada?
TheLethalCoder
6
Mais alguns casos de teste seriam bem-vindos.
Arnauld
2
Você pode confirmar que os sinais não podem ser anexados ao primeiro dígito? Ou seja, dado entrada 299399, seria -299+399válido?
Luis Mendo
1
'0' é um dígito? Por exemplo, '10808' é uma entrada válida? '1 108-08' é uma resposta válida?
quer

Respostas:

10

JavaScript (ES6), 153 176 bytes

EDIT: No modo não estrito, JS interpreta expressões numéricas com prefixo 0 como octal (por exemplo, 017é analisado como 15 em decimal). Esta é uma versão fixa que suporta zeros à esquerda.

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
fonte
Bom, e quanto a 20172117 como entrada?
Mdahmoune 4/07
@LuisMendo Na verdade, acho que a resposta esperada é 2-017-2+117. Mas 017é uma notação octal em JS, que fornece 15 em decimal. Então, meu código atual encontra apenas 2-0-17-2+117. Vou tentar resolver esse problema ainda hoje.
Arnauld
@ Arnauld Ah, eu não tinha visto essa outra solução. Removendo meu comentário
Luis Mendo
@mdahmoune Obrigado por trazer isso à tona. Agora consertado.
Arnauld
3**(l=s.length,l-1)=>3**~-(l=s.length)
l4m2
5

MATL , 37 36 bytes

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

O caso de teste leva cerca de 6 segundos no TIO.

Experimente online!

Como funciona

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
fonte
Ótimo, e quanto a 299399 como entrada?
Mdahmoune 4/07
1
@mdahmoune 299399não tem solução e, portanto, não é uma entrada válida (os operadores foram especificados para ir "entre" os dígitos, essa entrada exigiria -299+399onde -não houvesse entre dígitos).
Jonathan Allan
@mdahmoune Se os sinais puderem ser inseridos apenas entre os dígitos (como diz o texto do desafio), acho que não há solução. Se eles também podem ser anexados ao primeiro dígito, a solução é -299+399e, nesse caso, preciso de uma pequena alteração no meu código . Pedi esclarecimentos ao OP
Luis Mendo
Também é digno de nota que, se deveria ser antes e entre então, o exemplo 123456789deve ter uma contagem de operadores que 4não 3.
Jonathan Allan
@mdahmoune O OP confirmou que os sinais podem ter apenas dígitos. Então meu código está correto e 299399é uma entrada inválida porque, como o OP também esclareceu, cada entrada deve ter pelo menos uma solução
Luis Mendo
3

[Python 2], 164 158 bytes

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)

Experimente online!

Tome N como uma sequência de dígitos; retorna uma tupla (numOps, expressionString).

Basicamente, a mesma abordagem que outras; usa itertools.product para construir os "casos" individuais, por exemplo, para N == '1322', um "caso" seria ('-','','+')e avaliaria '1-32 + 2'.

Lança um ValueError se a entrada for inválida (mas acho que o OP não garantiu entradas inválidas).

Chas Brown
fonte
3

PHP, 166 171 bytes

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

Executar como tubo -nRou testá-lo on-line .

usa números formatados para classificar os resultados ->
pode imprimir espaços em branco à esquerda (e pode falhar na entrada com mais de 99 dígitos; aumente o número em%2d a corrigir).

não mais que 10 dígitos, 161 bytes

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

demolir

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
Titus
fonte
3

Geléia , 32 bytes

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

Um programa completo exibido usando os operadores Jelly (em _vez de- ).

Nota: Para mostrar -na saída em vez de _(não um requisito), adicione ⁾_-yentre Fe ( ⁾_-é um par de caracteres literal ['_','-']ey é o átomo diádico de "conversão").

Quão?

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

Experimente online!

Jonathan Allan
fonte
2

Mathematica, 136 146 149 156 165 166 bytes

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

Retorna {3, 123-45-67+89}por exemplo.

O caso de teste leva cerca de 0,09 segundos para ser concluído.

Keyu Gan
fonte
2

Python 2 , 256 230 208 205 172 171 170 165 bytes, método iterativo

  • 33 agradecimentos a Chas Brown
  • Um byte salvo ao substituir len(a)porw
  • Um byte salvo ao substituir z-=1;d=zpord=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)

Experimente online!

Pouca explicação Usando a representação na base 3, o código intercala os dígitos com os operadores {'+', '-', concatenação} de acordo com todas as combinações possíveis.

Python 2 , 167 bytes, método recursivo

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)

Experimente online!

Algumas saídas

"399299"    --> (1, '399-299')
"987654321" --> (4, '98-76+54+3+21')
"1111111"   --> (3, '1+111-1-11')
mdahmoune
fonte
1
Eu gosto do uso do divmod! Alguns golfs que eu posso ver: substitua list(input())por just input(), já que uma string já é iterável para salvar 6 bytes; substitua b.count('+')+b.count('-')por len(b)-len(a)para salvar 12 bytes; e substitua chr(r+43)por chr(r+43)*(d>0!=r-1)e, em seguida, você pode excluir a linha b=b[:-1].replace(',','')para economizar 15 bytes de rede ( (d>0!=r-1)é equivalente a (d>0 and 0!=r-1)).
Chas Brown
2

Braquilog , 36 bytes

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

Experimente online!

Mais da metade disso é para obter o formato de saída correto. A lógica central real é apenas:

15 bytes

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

Experimente online!

Isso retorna uma lista como [123, –45, –67,89]. A expressão é a soma dos elementos e o número de operadores é 1 menor que o comprimento da lista.

~cLhℕ∧100~+Lquase funciona para 12 bytes ( Experimente on-line! ) - mas é muito lento para lidar com entradas completas de 9 dígitos no TIO e, mais importante, falha em entradas como 10808- o Brachylog é inteligente demais para dividir números para ter zeros à esquerda, o que não acontece ' veja a partição [108, -08].

sundar - Restabelecer Monica
fonte
1

Haskell , 180 178 bytes

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]

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

#constrói uma lista de todos os termos possíveis, ?avalia um termo e gfiltra os termos que avaliam para 100 e retornam aquele com o número mínimo de operandos.

Laikoni
fonte
0

Gelatina , 27 bytes

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

Experimente online!

Não posso dizer que não recebi algumas dicas da resposta mais antiga de Jonathan Allan. ;-)

Comparado à sua resposta, este é apenas dois bytes mais curto (30), e não cinco, se tornarmos a comparação justa devido a atualizações de idioma:

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

Se compararmos de outra maneira (versão mais recente em vez de mais antiga), a diferença é a mesma (a dele se torna 29 bytes, vista abaixo):

ŒṖżⱮL’⁾+_ṗƲ$€ẎFV=ȷ2ƲƇLÞḢFṄḟ³L
Erik, o Outgolfer
fonte