Distribuindo números

11

Neste desafio, você estará usando a distribuição de um produto por somas e diferenças de números, conforme explicado aqui .

insira a descrição da imagem aqui

Exemplos

  Input      |     Output
-------------|-------------
23(12+42)    | (23*12)+(23*42)
9(62-5)      | (9*62)-(9*5)
4(17+8-14)   | (4*17)+(4*8)-(4*14)
15(-5)       | -(15*5)
2(3)         | (2*3)
8(+18)       | +(8*18)
8(-40+18)    | -(8*40)+(8*18)

Especificação

A entrada será uma cadeia de caracteres do formulário n(_), com um único inteiro positivo não assinado, nseguido de uma expressão entre parênteses _. Essa expressão _consistirá em somas e diferenças de um dos termos inteiros positivos separados por +e -sinais. O primeiro termo pode ser precedido por um +sinal, um -sinal ou por nenhum sinal.

Na saída, o número inicial ndeve ser distribuído para multiplicar cada um dos termos. Cada termo de adeve ser multiplicado à esquerda npara produzir a expressão entre parênteses (n*a), e esses novos termos devem ser combinados com +e -assinados exatamente da mesma maneira que os termos originais.

Entradas inválidas

Estes são exemplos de entradas com as quais você não precisa lidar.

3(5 plus 3)
6(5 13)
(5+8)(6+6)
(5+3)8

Ganhando

Isso é , então o código mais curto em bytes vence.

Downgoat
fonte
Ocorre-me que o regex é realmente adequado para esse problema. Se você não concorda com as soluções regulares, você pode proibi-lo, embora as pessoas já estejam trabalhando nisso.
xnor
Bibliotecas são permitidas?
orlp
@orlp Até certo ponto, o que foi discutido no meta .
Downgoat 23/08/15
Caso interessante:8(-40+18)
BrainSteel 23/08/2015

Respostas:

2

Pip, 28 bytes

DQaUnxWa^'(xR`\d+`'(.n.`*&)`

Explicação:

                              a is first cmdline arg (implicit)
DQa                           Remove (DeQueue) the closing paren from a
   UnxWa^'(                   Unify n and x with a split on open paren--Python equivalent
                                n,x=a.split("(")
                              n is thus the number to be distributed, and x is the
                                addition/subtraction expression
           xR                 In x, replace...
             `\d+`            ... regex matching numbers...
                  '(.n.`*&)`  ... with the replacement pattern (n*&), where n is the
                                appropriate number and & substitutes the complete match
                              Print result (implicit)

Os objetos Pattern de Pip seguem principalmente a sintaxe regex do Python, mas o &padrão de substituição é emprestado do sed.

Leia mais sobre o Pip no repositório do Github

DLosc
fonte
9

JavaScript 65 bytes

s=>(q=s.split(/[()]/))[1].replace(/(\D?)(\d+)/g,`$1(${q[0]}*$2)`)

Isso levará a entrada. Obtenha o + ou -, os dígitos e substitua-o na ordem correta.

Explicação

s=>   // Function with argument "s"
  (q= // Set q to...
    s.split(/[()]/) // Splits on parenthesis, returns array
  )
  [1] // Gets second match or text inside brackets
  .replace(/ // Replaces string 
     (\D?)  // Try to match a non-digit, the +-/* (group 1)
     (\d+)  // Then match one or more digits (group 2)
  /,
      // $1 is group 1 and $2 is group 2 q[0] is the text before the parenthesis 
  `$1(${q[0]}*$2)`
  ) 

Uso

Isso só funciona no Firefox e Safari Nightly, talvez Edge? porque ele usa os recursos do ES6. Você pode executá-lo:

var t = s => (q = s.split (/ [()] /)) [1]. substitua (/ (\ D?) (\ d +) / g, `$ 1 ($ {q [0]} * $ 2) `)

t ( "5 (-6 + 7 + 3-8 + 9)" ); // - (5 * 6) + (5 * 7) + (5 * 3) - (5 * 8) + (5 * 9)

fonte
(.?)(\d+)está quebrado. Isso falha 23(12+42), produzindo 1(23*2)+(23*42).
orlp
@orlp eu fixo que
Esse código funcionará apenas no Firefox b / c da função de seta, mas tudo bem
MayorMonty 24/08/2015
@SpeedyNinja Também funciona no Edge. Para o Chrome / Opera, você precisa ativar "recursos experimentais de JavaScript".
precisa saber é o seguinte
\D?poderia ser usado em vez de[+-]?
edc65
6

Python 2.7, 110 108 bytes

import re
p=re.findall('([+-]?)(\d+)',raw_input())
print"".join("%s(%s*%s)"%(e[0],p[0][1],e[1])for e in p[1:])

O programa pega a entrada do stdin, procura por correspondências contra - ([+-]?)(\d+)regex e cria a string de saída.
Testando -

<< 23(12+42)
>> (23*12)+(23*42)

<< 9(62-5)
>> (9*62)-(9*5)

<< 4(17+8-14)
>> (4*17)+(4*8)-(4*14)

<< 15(-5)
>> -(15*5)

<< 2(3)
>> (2*3)

<< 8(+18)
>> +(8*18)

<< 8(-40+18)
>> -(8*40)+(8*18)
Kamehameha
fonte
4

Retina , 40 bytes

+`(\d+)\((\D)?(\d+)
$2($1*$3)$1(
\d+..$
<empty line>

Cada linha deve ir para seu próprio arquivo, mas você pode executar o código como um arquivo com o -ssinalizador. Por exemplo:

>echo -n "8(-40+18)"|retina -s distributing_numbers
-(8*40)+(8*18)

As duas primeiras linhas empurram o multiplicador ao lado de cada número na forma esperada:

8(-40+18)
-(8*40)8(+18)
-(8*40)+(8*18)8()

As duas últimas linhas removem a parte final desnecessária:

-(8*40)+(8*18)8()
-(8*40)+(8*18)
randomra
fonte
3

sed, 105 bytes

Só queria ver se isso pode ser feito com o sed.
Talvez um pouco da velha escola, mas funciona.

$ cat distnum.sed
s@\([0-9]*\)(\([0-9]*\)\([+-]*\)\([0-9]*\)\([+-]*\)\([0-9]*\))@(\1*\2)\3(\1*\4)\5(\1*\6)@
s@([0-9]*\*)@@g

$ cat distnum.txt
23(12+42)
9(62-5)
4(17+8-14)
15(-5)
2(3)
8(+18)
8(-40+18)

$ sed -f distnum.sed distnum.txt
(23*12)+(23*42)
(9*62)-(9*5)
(4*17)+(4*8)-(4*14)
-(15*5)
(2*3)
+(8*18)
-(8*40)+(8*18)
LukStorms
fonte
2

rs , 77 bytes

$$d=(?<!\))([+-]?)(\d+)
+$d\($d([+-])/\3(\1\2*\4)\5\1\2(
$d\($d\)/\3(\1\2*\4)

Demonstração ao vivo e todos os casos de teste.

Esta é a primeira vez que as macros do rs foram realmente usadas!

kirbyfan64sos
fonte
2

REGXY , 45 bytes

Usa REGXY, um idioma baseado em substituição de regex.

/(\d+)\((\D)?(\d+)/\2(\1*\3)\1(/
//
/\d+\(.//
Jarmex
fonte
Como funciona o //trabalho? Suponho que ele faça um loop até o topo até que a string seja alterada, mas não consigo encontrar o porquê da página esolang.
Random #
É um pouco um abuso atrevido da imprecisão na especificação de idioma, mas eu expliquei aqui: codegolf.stackexchange.com/questions/52946/…
Jarmex 6/15
1
Ainda não entendo por que não //cria um loop infinito, como nothingsempre corresponderá, então sempre voltaremos para a primeira linha.
Random #
Sabe o que mais? Na verdade, eu não tenho ideia do porquê. Você está absolutamente certo, pensando nisso agora, não faz sentido lógico, mas definitivamente compila e executa no intérprete fornecido. Mesmo olhando para o Perl compilado gera me confunde, porque parece ainda mais claro que ele deve ser um loop infinito: pastebin.com/9q7M0tpZ
Jarmex
2

Perl, 36 bytes

Código de 35 bytes + linha de comando de 1 byte

($a,$_)=split/[()]/;s/\d+/($a*$&)/g

Uso:

echo "4(17+8-14)" | perl -p entry.pl
Jarmex
fonte
1

Pitão, 39 38 bytes

Uma solução regex terrível:

P:eJcz\("([+-]?)(\d+)"X"\\1(_*\\2)"3hJ
orlp
fonte
Parece que não consigo fazer isso funcionar no intérprete online .
BrainSteel
@BrainSteel Funciona no intérprete offline, parece ser um problema com o heroku.
orlp
@ orlp Não é um problema com o heroku. As importações dinâmicas são desativadas no modo de segurança, para reduzir a probabilidade de um hack, e o re-módulo faz uma importação dinâmica. Portanto, re não pode ser usado no modo de segurança, inclusive online.
Isaacg
1

Ruby, 94 bytes

gets.scan(/(\d+)\(([[-+]?\d+]+)/){|a,b|b.scan(/([-+]?)(\d+)/).map{|c,d|$><<"#{c}(#{a}*#{d})"}}
JWT
fonte
1

CJam, 50 bytes

l__'(#_@<'*+@@)>);'+/'-f/\ff{1$'(@@++')+L?}'-f*'+*

Experimente online

O CJam não possui suporte a regex ou qualquer coisa além da pesquisa e divisão de cadeias que seja muito conveniente para analisar expressões. Portanto, há algum trabalho envolvido aqui.

Explicação:

l__   Get input and push 2 copies for splitting.
'(#   Find index of '(.
_     Copy index, will be used twice.
@<    Get one copy of input to top, and slice to get first multiplier.
'*+   Append '* to first multiplier.
@@    Get another copy of input and '( index to top.
)>    Increment and slice to get everything after '(.
);    Remove trailing ').
'+/   Split at '+.
'-f/  Split each part at '-.
\     Swap first multiplier to top.
ff{   Apply block to nested list of second multipliers.
  1$    Copy term. Will use this copy as condition to skip empty second multipliers
        that result from unary + or -.
  '(    Opening parentheses.
  @@    Get first and second multiplier to top.
  ++    Concatenate it all.
  ')+   Concatenate closing parentheses.
  L     Push empty string for case where term is skipped.
  ?     Ternary if to pick term or empty string.
}     End of loop over list of second multipliers.
'-f*  Join sub-lists with '-.
'+*   Join list with '+.
Reto Koradi
fonte
1

gawk - 60 58

$0=gensub(/(.*\()?(+|-)?([0-9]+))?/,"\\2("$0+0"*\\3)","G")

Ufa ... não trabalha com regexp há um bom tempo.

Cabbie407
fonte
1

Perl 5, 70 60 55 44 Bytes + 1 penalidade

Uma solução perl que usa apenas expressões regulares divididas e 1.
Também calcula as entradas mais longas.

($a,$_)=split/[()]/;s/(\D?)(\d+)/$1($a*$2)/g

Teste

$ echo "8(9-10+11-12+13-14)"|perl -p distnums.pl   
(8*9)-(8*10)+(8*11)-(8*12)+(8*13)-(8*14)

Uma versão que aceita um parâmetro

($a,$_)=split/[()]/,pop;s/(\D?)(\d+)/$1($a*$2)/g;print

Uma versão que usa apenas expressões regulares.

s/(\d+)\((.*)\)/$2:$1/;s/(\D?)(\d+)(?=.*:(\d+)).*?/$1($3*$2)/g;s/:.*//

Este funciona através de um grupo de captura com uma aparência positiva e uma correspondência lenta. Provavelmente teria usado um olhar positivo se o Perl 5 o suportasse, mas infelizmente. Demorei um pouco para descobrir que isso é possível com o regex.

LukStorms
fonte
1
Ei, Luk, você pode salvar alguns caracteres usando a -popção de linha de comando (acho que isso é +1 char vs 9 para ,<>e ;print), pois splitfuncionará $_por padrão (que será o que estiver dentro <>) e a impressão também está incluída no loop ! Espero que ajude!
Dom Hastings
1
Obrigado! Ajudou. A opção -p simplesmente não passou pela minha cabeça. Provavelmente, já que é algo que raramente é usado fora de um contexto de golfe. Por que você acha que é +1 de caractere? Esse desafio não menciona nada sobre penalidades pelo uso de switches.
LukStorms 02/09/2015
Não consigo encontrar a postagem agora, mas essa meta post menciona a pontuação dos sinalizadores de Perl.
Dom Hastings
1
Meu mal, parece que eu vim e publiquei uma solução muito semelhante a você, que é efetivamente apenas uma versão um pouco mais sua! Basicamente, você nem precisa capturar o [+ -] porque os deixa intactos na substituição de qualquer maneira: codegolf.stackexchange.com/a/57117/26977
Jarmex 6/15
Isso é legal. Por sua causa, o Perl supera até as soluções Pyth / Cjam nesse desafio. Eu não deveria ter me importado com as entradas inválidas de qualquer maneira, depois que essa divisão removeu os colchetes.
LukStorms
1

Retina , 50 51 43 bytes

Eu acho que este pode ser o meu primeiro programa de Retina. Caso contrário, é o meu primeiro programa Retina que é tão complexo (não tão complexo, realmente.) Cada linha tem seu próprio arquivo.

+`(\d+)\((\D?)(\d+)
$1($'$2($1*$3)
.+?\)
$'

Na verdade, eu não testei isso com o Retina, testei usando um testador de substituição de expressão regular várias vezes, mas deve funcionar.

Descrição para o primeiro exemplo:

Como há um número par de arquivos, o Retina usa o modo de substituição. A primeira substituição (dois primeiros arquivos) remove um número a ser distribuído e adiciona esse par de distribuição (23*12)ao final, fornecendo 23(+42)(23*12). +`no início, informa ao Retina para substituir repetidamente até que o padrão não corresponda e, como isso é correspondido novamente, o padrão o substitui por 23()(23*12)+(23*42). Isso não corresponde mais, portanto, os próximos 2 arquivos são usados ​​para a próxima substituição. Desta vez, apenas remove o 23(). Isso funciona muito bem: como os produtos são anexados até o final, não preciso fazer nada estranho se um número não tiver um sinal, pois o único que pode ficar sem sinal é o primeiro número.

EDIT: $'em substituição representa o resto da string após a partida, para que eu possa remover os (.*)s à direita .

mbomb007
fonte
0

k, 98 bytes

Não é muito golfista.

{,/(*x){(s#y),("*"/:(x;(s:(*y)in"+-")_y))/:$"()"}/:1_x@:&~~#:'x:((0,&~x in .Q.n)_x){x_'x?'y}/"()"}

Divida com não dígito, remova parênteses, remova cadeias vazias e mantenha xconstante como a primeira cadeia, combine *com cada cadeia restante y, entre parênteses e mova o sinal para o início, se presente; achatar a saída em uma única sequência.

Aaron Davies
fonte