Zahlen verteilen

11

Bei dieser Herausforderung werden Sie ein Produkt über Summen und Zahlenunterschiede verteilen , wie hier erläutert .

Geben Sie hier die Bildbeschreibung ein

Beispiele

  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)

Spezifikation

Die Eingabe ist eine Zeichenfolge des Formulars n(_)mit einer einzelnen positiven Ganzzahl ohne Vorzeichen, ngefolgt von einem Ausdruck in Klammern _. Dieser Ausdruck _besteht aus Summen und Differenzen eines von mehreren positiv-ganzzahligen Begriffen, die durch +und -Zeichen getrennt sind. Dem ersten Begriff kann ein +Zeichen, ein -Zeichen oder kein Zeichen vorangestellt werden .

In der Ausgabe sollte die Anfangszahl nverteilt werden, um jeden der Begriffe zu multiplizieren. Jeder Term von asollte mit links multipliziert werden n, um den Ausdruck in Klammern zu erhalten (n*a), und diese neuen Terme sollten mit +und -Zeichen genauso kombiniert werden wie die ursprünglichen Terme.

Ungültige Eingaben

Dies sind Beispiele für Eingaben, die Sie nicht verarbeiten müssen.

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

Gewinnen

Dies ist , also gewinnt der kürzeste Code in Bytes.

Downgoat
quelle
Mir fällt auf, dass Regex für dieses Problem wirklich gut geeignet ist. Wenn Sie mit Reg-Ex-Lösungen nicht einverstanden sind, können Sie sie verbieten, obwohl die Leute möglicherweise bereits daran arbeiten.
xnor
Sind Bibliotheken erlaubt?
Orlp
@orlp Bis zu einem gewissen Grad wurde das auf Meta diskutiert .
Downgoat
Interessanter Fall:8(-40+18)
BrainSteel

Antworten:

2

Pip, 28 Bytes

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

Erläuterung:

                              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)

Pips Pattern-Objekte folgen meistens der Python-Regex-Syntax, aber das &Ersatzmuster ist von sed entlehnt.

Weitere Informationen zu Pip finden Sie im Github-Repository

DLosc
quelle
9

JavaScript 65 Bytes

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

Dies übernimmt die Eingabe. Holen Sie sich das + oder -, dann die Ziffern und ersetzen Sie es in der richtigen Reihenfolge.

Erläuterung

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

Verwendung

Dies funktioniert nur in Firefox und Safari Nightly vielleicht Edge? weil es ES6-Funktionen verwendet. Sie können es ausführen durch:

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)

quelle
(.?)(\d+)ist kaputt. Dies scheitert am 23(12+42)Produzieren 1(23*2)+(23*42).
Orlp
@orlp Ich habe das behoben
Dieser Code funktioniert nur in Firefox b / c der
Pfeilfunktion
@SpeedyNinja Es funktioniert auch in Edge. Für Chrome / Opera müssen Sie "experimentelle JavaScript-Funktionen" aktivieren.
rink.attendant.6
\D?könnte anstelle von[+-]?
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:])

Das Programm nimmt Eingaben von stdin entgegen, sucht nach Übereinstimmungen mit - ([+-]?)(\d+)regex und erstellt die Ausgabezeichenfolge.
Testen -

<< 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
quelle
4

Netzhaut , 40 Bytes

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

Jede Zeile sollte in eine eigene Datei gehen, aber Sie können den Code als eine Datei mit dem -sFlag ausführen . Z.B:

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

Die ersten beiden Zeilen drücken den Multiplikator neben jede Zahl in der erwarteten Form:

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

Die letzten beiden Zeilen entfernen den unnötigen nachlaufenden Teil:

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

sed, 105 Bytes

Ich wollte nur sehen, ob dies mit sed möglich ist.
Vielleicht ein bisschen altmodisch, aber es funktioniert.

$ 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
quelle
2

rs , 77 Bytes

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

Live-Demo und alle Testfälle.

Dies ist das erste Mal, dass die Makros von rs tatsächlich verwendet wurden!

kirbyfan64sos
quelle
2

REGXY , 45 Bytes

Verwendet REGXY, eine auf Regex-Substitution basierende Sprache.

/(\d+)\((\D)?(\d+)/\2(\1*\3)\1(/
//
/\d+\(.//
Jarmex
quelle
Wie funktioniert das //? Ich nehme an, es wird nach oben geschleift, bis sich die Zeichenfolge ändert, aber ich kann auf der Esolang-Seite nicht finden, warum.
Randomra
Es ist ein bisschen ein frecher Missbrauch der Unbestimmtheit in der Sprachspezifikation, aber ich habe es hier erklärt: codegolf.stackexchange.com/questions/52946/…
Jarmex
1
Ich verstehe immer noch nicht, warum nicht //eine Endlosschleife erstellt wird, da nothingdiese immer übereinstimmt, sodass wir immer zur ersten Zeile zurückkehren.
Randomra
Weißt du was? Ich habe eigentlich keine Ahnung warum. Sie haben absolut Recht, wenn Sie jetzt darüber nachdenken, macht es keinen logischen Sinn, aber es wird definitiv kompiliert und läuft im bereitgestellten Interpreter. Auch Blick auf die kompilierte Perl erzeugt es verwirrt mich, weil es noch deutlicher sieht , dass es eine unendliche Schleife sein sollte: pastebin.com/9q7M0tpZ
Jarmex
2

Perl, 36 Bytes

35-Byte-Code + 1-Byte-Befehlszeile

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

Verwendung:

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

Pyth, 39 38 Bytes

Eine schreckliche Regex-Lösung:

P:eJcz\("([+-]?)(\d+)"X"\\1(_*\\2)"3hJ
orlp
quelle
Ich kann nicht scheinen, dass dies im Online-Interpreter ausgeführt wird .
BrainSteel
@BrainSteel Es funktioniert im Offline-Interpreter, es scheint ein Problem mit Heroku zu sein.
Orlp
@orlp Es ist kein Problem mit Heroku. Dynamische Importe werden im abgesicherten Modus deaktiviert, um die Wahrscheinlichkeit eines Hacks zu verringern, und das Modul re führt einen dynamischen Import durch. Daher kann re nicht im abgesicherten Modus verwendet werden, auch nicht online.
isaacg
1

Ruby, 94 Bytes

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

CJam, 50 Bytes

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

Probieren Sie es online aus

CJam bietet keine Regex-Unterstützung oder etwas anderes als das Suchen und Teilen von Zeichenfolgen, das für das Parsen von Ausdrücken sehr praktisch ist. Hier ist also etwas Arbeit erforderlich.

Erläuterung:

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
quelle
1

gawk - 60 58

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

Puh ... habe seit einiger Zeit nicht mehr mit Regexp gearbeitet.

Cabbie407
quelle
1

Perl 5, 70 60 55 44 Bytes + 1 Strafe

Eine Perl-Lösung, die nur Split und 1 regulären Ausdruck verwendet.
Berechnet auch die längeren Eingaben.

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

Prüfung

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

Eine Version, die einen Parameter akzeptiert

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

Eine Version, die nur reguläre Ausdrücke verwendet.

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

Dieser funktioniert über eine Erfassungsgruppe innerhalb eines positiven Lookaheads und eines faulen Matchings. Wahrscheinlich hätte ein positives Aussehen verwendet, wenn Perl 5 es unterstützt hätte, aber leider. Ich habe eine Weile gebraucht, um herauszufinden, dass so etwas mit Regex möglich ist.

LukStorms
quelle
1
Hey Luk, Sie können möglicherweise einige Zeichen mithilfe der -pBefehlszeilenoption speichern (ich denke, dies ist +1 Zeichen gegenüber 9 für ,<>und ;print), da dies standardmäßig splitfunktioniert $_(was auch immer darin enthalten ist <>) und der Druck auch in der Schleife enthalten ist ! Ich hoffe, das hilft!
Dom Hastings
1
Vielen Dank! Es half. Die Option -p kam mir einfach nicht in den Sinn. Wahrscheinlich, weil es etwas ist, das außerhalb eines Golfkontexts selten verwendet wird. Warum denkst du, ist es +1 Zeichen? Diese Herausforderung erwähnt nichts über Strafen für die Verwendung von Schaltern.
LukStorms
Ich kann den Beitrag jetzt nicht finden, aber in diesem Meta-Beitrag wird die Bewertung für Perls Flaggen erwähnt.
Dom Hastings
1
Mein schlechtes, sieht so aus, als wäre ich auf Sie zugekommen und habe eine sehr ähnliche Lösung für Sie veröffentlicht, die praktisch nur eine etwas Golfversion von Ihnen ist! Grundsätzlich müssen Sie nicht einmal die [+ -] erfassen, da Sie sie ohnehin in der Ersetzung intakt lassen: codegolf.stackexchange.com/a/57117/26977
Jarmex
Das ist cool. Wegen dir schlägt Perl bei dieser Herausforderung sogar die Pyth / Cjam-Lösungen. Ich hätte mich sowieso nicht um die ungültigen Eingaben kümmern sollen, nachdem diese Aufteilung die Klammern entfernt hatte.
LukStorms
1

Netzhaut , 50 51 43 Bytes

Ich denke, dies könnte mein erstes Retina-Programm sein. Wenn nicht, ist es mein erstes Retina-Programm, das so komplex ist (eigentlich nicht so komplex). Jede Zeile wird in einer eigenen Datei abgelegt.

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

Ich habe dies nicht mit Retina getestet, sondern mehrmals mit einem Regex-Replace-Tester, aber es sollte funktionieren.

Beschreibung für das erste Beispiel:

Da es eine gerade Anzahl von Dateien gibt, verwendet Retina den Ersetzungsmodus. Das erste Ersetzen (die ersten beiden Dateien) entfernt eine zu verteilende Nummer und fügt dieses Verteilungspaar (23*12)am Ende hinzu 23(+42)(23*12). +`Zu Beginn weist Retina an, wiederholt zu ersetzen, bis das Muster nicht mehr übereinstimmt. Da dies erneut übereinstimmt, ersetzt das Muster dies durch 23()(23*12)+(23*42). Dies stimmt nicht mehr überein, daher werden die nächsten 2 Dateien für das nächste Ersetzen verwendet. Dieses Mal wird lediglich das entfernt 23(). Das funktioniert gut: Da Produkte an das Ende angehängt werden, muss ich nichts Seltsames tun, wenn eine Nummer kein Zeichen hat, da die einzige Nummer, die ohne Zeichen sein kann, die erste Nummer ist.

BEARBEITEN: Ersetzt $'als Ersatz den Rest der Zeichenfolge nach dem Match, sodass ich die nachfolgenden (.*)s entfernen kann .

mbomb007
quelle
0

k, 98 Bytes

Nicht sehr golfen.

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

Auf nicht-Ziffern teilen, Parens entfernen, leere Zeichenfolgen entfernen und dann xals erste Zeichenfolge konstant halten , *mit jeder verbleibenden Zeichenfolge kombinieren y, in Klammern setzen und das Zeichen an den Anfang verschieben, falls vorhanden; Reduzieren Sie die Ausgabe in eine einzelne Zeichenfolge.

Aaron Davies
quelle