Distribution de numéros

11

Dans ce défi, vous allez utiliser la distribution d' un produit sur des sommes et des différences de nombres, comme expliqué ici .

entrez la description de l'image ici

Exemples

  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)

spécification

L'entrée sera une chaîne du formulaire n(_), avec un seul entier positif non signé nsuivi d'une expression entre parenthèses _. Cette expression _consistera en des sommes et en la différence d'un ou plusieurs termes entiers positifs séparés par des signes +et -. Le premier terme peut être précédé d'un +signe, d'un -signe ou d'aucun signe.

Dans la sortie, le nombre initial ndoit être distribué pour multiplier chacun des termes. Chaque terme de adoit être multiplié nà gauche par pour produire l'expression entre parenthèses (n*a), et ces nouveaux termes doivent être combinés avec +et -signe exactement de la même manière que les termes d'origine.

Entrées invalides

Ce sont des exemples d'entrées que vous n'avez pas à gérer.

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

Gagnant

C'est le , donc le code le plus court en octets l'emporte.

Downgoat
la source
Il me semble que l'expression régulière est vraiment bien adaptée à ce problème. Si vous n'êtes pas d'accord avec les solutions reg-ex, vous pouvez l'interdire, même si les gens y travaillent déjà.
xnor
Les bibliothèques sont-elles autorisées?
orlp
@orlp Dans une certaine mesure, ce qui a été discuté sur la méta .
Downgoat
Cas intéressant:8(-40+18)
BrainSteel

Réponses:

2

Pip, 28 octets

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

Explication:

                              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)

Les objets Pattern de Pip suivent principalement la syntaxe des expressions rationnelles Python, mais le &modèle de remplacement est emprunté à sed.

En savoir plus sur Pip dans le référentiel Github

DLosc
la source
9

JavaScript 65 octets

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

Cela prendra l'entrée. Obtenez le + ou le -, puis les chiffres, puis remplacez-le dans le bon ordre.

Explication

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

Usage

Cela ne fonctionne que dans Firefox et Safari Nightly, peut-être Edge? car il utilise les fonctionnalités ES6. Vous pouvez l'exécuter par:

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

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

la source
(.?)(\d+)est cassé. Cela échoue 23(12+42), produisant 1(23*2)+(23*42).
orlp
@orlp J'ai corrigé cela
Ce code ne fonctionnera que dans Firefox b / c de la fonction flèche, mais c'est très bien
MayorMonty
@SpeedyNinja Il fonctionne également dans Edge. Pour Chrome / Opera, vous devez activer les "fonctionnalités JavaScript expérimentales".
rink.attendant.6
\D?pourrait être utilisé à la place de[+-]?
edc65
6

Python 2.7, 110 108 octets

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:])

Le programme prend l'entrée de stdin, recherche les correspondances avec - ([+-]?)(\d+)regex et crée la chaîne de sortie.
Le tester -

<< 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
la source
4

Rétine , 40 octets

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

Chaque ligne doit aller dans son propre fichier mais vous pouvez exécuter le code comme un seul fichier avec l' -sindicateur. Par exemple:

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

Les deux premières lignes poussent le multiplicateur à côté de chaque nombre sous la forme attendue:

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

Les deux dernières lignes suppriment la partie arrière inutile:

-(8*40)+(8*18)8()
-(8*40)+(8*18)
randomra
la source
3

sed, 105 octets

Je voulais juste voir si cela pouvait être fait avec sed.
Peut-être un peu vieille école, mais ça marche.

$ 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
la source
2

rs , 77 octets

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

Démo en direct et tous les cas de test.

C'est la première fois que les macros de rs sont réellement utilisées!

kirbyfan64sos
la source
2

REGXY , 45 octets

Utilise REGXY, un langage basé sur la substitution d'expression régulière.

/(\d+)\((\D)?(\d+)/\2(\1*\3)\1(/
//
/\d+\(.//
Jarmex
la source
Comment ça //marche? Je suppose qu'il boucle en haut jusqu'à ce que la chaîne change, mais je ne trouve pas pourquoi dans la page esolang.
randomra
C'est un peu un abus insolent du flou dans les spécifications linguistiques, mais je l'ai expliqué ici: codegolf.stackexchange.com/questions/52946/…
Jarmex
1
Je ne comprends toujours pas pourquoi ne //crée pas une boucle infinie, car nothingcela correspondra toujours, donc nous revenons toujours à la première ligne.
randomra
Tu sais quoi? Je ne sais vraiment pas pourquoi. Vous avez absolument raison, y penser maintenant n'a aucun sens logique, mais il compile et s'exécute définitivement dans l'interpréteur fourni. Même en regardant le Perl compilé qu'il génère, je suis confus, car il semble encore plus clair qu'il devrait s'agir d'une boucle infinie: pastebin.com/9q7M0tpZ
Jarmex
2

Perl, 36 octets

Code de 35 octets + ligne de commande de 1 octet

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

Usage:

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

Pyth, 39 38 octets

Une terrible solution regex:

P:eJcz\("([+-]?)(\d+)"X"\\1(_*\\2)"3hJ
orlp
la source
Je n'arrive pas à faire fonctionner cela dans l' interpréteur en ligne .
BrainSteel
@BrainSteel Cela fonctionne dans l'interpréteur hors ligne, il semble que ce soit un problème avec heroku.
orlp
@orlp Ce n'est pas un problème avec heroku. Les importations dynamiques sont désactivées en mode sans échec, pour réduire la probabilité d'un piratage, et le module re effectue une importation dynamique. Donc re ne peut pas être utilisé en mode sans échec, y compris en ligne.
isaacg
1

Rubis, 94 octets

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

CJam, 50 octets

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

Essayez-le en ligne

CJam ne prend pas en charge l'expression régulière, ni rien au-delà de la recherche et du fractionnement de chaînes, ce qui est très pratique pour l'analyse des expressions. Il y a donc du travail ici.

Explication:

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
la source
1

gawk - 60 58

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

Ouf ... n'a pas travaillé avec regexp depuis longtemps.

Cabbie407
la source
1

Perl 5, 70 60 55 44 octets + 1 pénalité

Une solution Perl qui n'utilise que split et 1 expression régulière.
Calcule également les entrées les plus longues.

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

Tester

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

Une version qui prend un paramètre

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

Une version qui utilise uniquement des expressions régulières.

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

Celui-ci fonctionne via un groupe de capture dans un lookahead positif et une correspondance paresseuse. Aurait probablement utilisé un lookbehind positif si Perl 5 le soutenait, mais hélas. Cela m'a pris un certain temps pour comprendre que ce genre de chose est possible avec regex.

LukStorms
la source
1
Hey Luk, vous pourriez être en mesure d'enregistrer certains caractères en utilisant l' -poption de ligne de commande (je pense que c'est +1 caractère contre 9 pour ,<>et ;print) comme splitcela fonctionnera $_par défaut (qui sera tout ce qui est dedans <>) et l'impression est également incluse dans la boucle ! J'espère que ça t'as aidé!
Dom Hastings
1
Merci! Ça m'a aidé. L'option -p ne m'a tout simplement pas traversé l'esprit. Probablement puisque c'est quelque chose qui est rarement utilisé en dehors d'un contexte de golf. Pourquoi pensez-vous que c'est +1 char? Ce défi ne mentionne rien sur les sanctions pour l'utilisation de commutateurs.
LukStorms
Je ne trouve pas le post maintenant, mais ce méta post mentionne un score pour les drapeaux de Perl.
Dom Hastings
1
Mon mauvais, on dirait que je suis venu et vous ai posté une solution très similaire, qui est en fait juste une version légèrement plus golfée de la vôtre! Fondamentalement, vous n'avez même pas besoin de capturer le [+ -] car vous les laissez de toute façon intactes dans la substitution: codegolf.stackexchange.com/a/57117/26977
Jarmex
C'est super. Grâce à vous, Perl bat même les solutions Pyth / Cjam dans ce défi. Je n'aurais pas dû me soucier des entrées invalides de toute façon après que cette séparation ait supprimé les crochets.
LukStorms
1

Rétine , 50 51 43 octets

Je pense que c'est peut- être mon premier programme Retina. Sinon, c'est mon premier programme Retina qui est aussi complexe (pas si complexe, vraiment.) Chaque ligne va dans son propre fichier.

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

Je n'ai pas réellement testé cela avec Retina, je l'ai testé plusieurs fois à l'aide d'un testeur de remplacement de regex, mais cela devrait fonctionner.

Description du premier exemple:

Puisqu'il existe un nombre pair de fichiers, Retina utilise le mode de remplacement. Le premier remplacement (deux premiers fichiers) supprime un nombre à distribuer et ajoute cette paire de distribution (23*12)à la fin, en donnant 23(+42)(23*12). +`au début, dit à Retina de remplacer à plusieurs reprises jusqu'à ce que le motif ne corresponde pas, et puisque cela est à nouveau mis en correspondance, le motif le remplace par 23()(23*12)+(23*42). Cela ne correspond plus, donc les 2 fichiers suivants sont utilisés pour le prochain remplacement. Cette fois, il supprime simplement le 23(). Cela fonctionne bien: comme les produits sont ajoutés à la fin, je n'ai rien à faire de bizarre si un numéro n'a pas de signe, car le seul qui peut être sans signe est le premier numéro.

EDIT: $'en remplacement représente le reste de la chaîne après la correspondance, donc je peux supprimer les (.*)s de fin .

mbomb007
la source
0

k, 98 octets

Pas très golfé.

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

Séparer sur non numérique, supprimer les parenthèses, supprimer les chaînes vides, puis maintenir xconstant comme première chaîne, combiner *avec chaque chaîne restante y, mettre entre parenthèses et déplacer le signe au début s'il est présent; aplatir la sortie en une seule chaîne.

Aaron Davies
la source