Lösen Sie eine Gleichung mit (fast) beliebigen Zahlen

27

Fügen Sie bei einer Zeichenfolge +=-mit mindestens einem Zeichen =positive Ganzzahlen zwischen allen Symbolen sowie am Anfang und am Ende ein, damit die mathematischen Gleichungen erfüllt sind.

Zum Beispiel angesichts der Eingabe

+-=-=

Sie müssen positive ganze Zahlen A bis F wie folgt einfügen

A+B-C=D-E=F

so dass die Gleichungen alle erfüllt sind, dh A + B - Cund D - Eund Fsind alle die gleiche Zahl.

Es gibt viele Möglichkeiten, dies zu tun, da, solange die Gleichungen funktionieren, ein beliebiger Satz positiver Ganzzahlen verwendet werden kann. Jede Zeile hier ist eine mögliche gültige Ausgabe zur Eingabe +-=-=:

2+3-4=6-5=1
1+1-1=2-1=1
4+2-4=4-2=2
100+1-10=182-91=91
89+231-77=1024-781=243

Beachten Sie, dass der Wert der Ausdrücke keine positive ganze Zahl sein muss, wie dies bei den eingefügten Zahlen der Fall ist. Beispielsweise sind bei einer gegebenen Eingabe -=-die Ausgaben 1-10=8-17(evals bis -9) und 10-1=17-8(evals bis 9) beide gleich gültig. Natürlich ist es für einige Eingaben wie zum Beispiel =unmöglich, ein Negativ als Ausdruck zu verwenden, da nur positive Zahlen wie 5=5eingefügt werden können.

Beachten Sie auch, dass Null keine positive ganze Zahl ist.

Der kürzeste Code in Bytes gewinnt.

Sie können die Zahlen als Liste ausgeben, anstatt sie direkt in die Zeichenfolge einzufügen. Wenn Sie die Zeichenfolge ausgeben, können zwischen Symbolen und Zahlen Leerzeichen stehen. Also, für die Eingabe +-=-=, Ausgabe

2, 3, 4, 6, 5, 1

oder

2 + 3 - 4 = 6 - 5 = 1

ist gleichbedeutend mit der Ausgabe

2+3-4=6-5=1

Testfälle

Input | One Possible Output
= | 1=1
== | 2=2=2
+= | 1+3=4
=+ | 2=1+1
-= | 30-10=20
=- | 1=2-1
=-= | 3=7-4=3
=+= | 2=1+1=2
=== | 100=100=100=100
+=- | 3+2=7-2
-=+ | 7-2=3+2
+=+ | 3+3=3+3
-=- | 1-10=8-17
--= | 60-1-1=58
++= | 60+1+1=62
-+= | 60-9+1=52
+-= | 60+9-1=68
+-=-= | 2+3-4=6-5=1
--=-- | 2-1-1=2-1-1
==-== | 47=47=50-3=47=47
=++=+-=-+=--= | 3=1+1+1=3+1-1=1-1+3=5-1-1=3
+--++-=-+-+- | 35+10-16-29+20+107-1000=5-4+3-2+1-876
====== | 8=8=8=8=8=8=8
Calvins Hobbys
quelle
Verbunden.
Martin Ender
Können wir eine Obergrenze für die Länge der Formel annehmen?
xnor
2
@xnor Sie können davon ausgehen, dass die Eingabe weniger als 2 ^ 16 Zeichen lang ist, wenn dies hilft.
Calvins Hobbys

Antworten:

16

Netzhaut , 58 Bytes

[-+]
$&1
\B((\+1)|(-1))*
$._$*1$#3$*1$#2$*_$&
+`1_

1+
$.&

Probieren Sie es online!

Alternative Lösung bei gleicher Byteanzahl:

((\+)|(-))*
$._$*1$#3$*1$#2$*_$&
+`1_

([+-])1*
$+1
1+
$.&

Probieren Sie es online!

Erläuterung

Die Grundidee ist es, alle zu drehen +s und -s in einfacher +1und -1Operationen und dann eine ausreichend große Zahl vorangestellt wird, dass alle Gleichungen Arbeit macht. Damit die Gleichungen übereinstimmen, können wir einfach jedem die gleiche Zahl voranstellen und sie dann für jeden +1um eins verringern und danach für jeden um eins erhöhen -1. Da wir mit unären Zahlen arbeiten, besteht der einzige Haken darin, dass die erste Zahl groß genug sein muss, damit wir sie um das 1-fache reduzieren können.

[-+]
$&1

Wir beginnen mit dem Einfügen eines 1nach jedem -oder +.

\B((\+1)|(-1))*
$._$*1$#3$*1$#2$*_$&

Die \Bsorgt dafür , dass diese Begegnungen sind entweder zu Beginn des Eingangs oder zwischen ein =und einem +oder -, dh alle Positionen , an denen wir die führende Nummer eines Ausdrucks eingefügt werden sollen. Der ((\+1)|(-1))*Teil zählt dann einfach die Anzahl der +1s und -1s in Gruppen 2und 3jeweils. Lassen Sie uns nun die Ersetzungszeichenfolge aufschlüsseln:

$._$*1   # For each character in the current string, insert a 1. This is
         # an offset which is the same for each expression and is guaranteed
         # to be large enough that all subsequent +1s can be cancelled.
$#3$*1   # For each -1, insert a 1.
$#2$*_   # For each +1, insert a _.
$&       # Re-insert the string of +1s and -1s.
+`1_

Lassen Sie 1_die Zeichenfolge wiederholt los und stornieren Sie die +1s.

1+
$.&

Ersetzen Sie abschließend alle Zeichenfolgen von 1s durch ihre Längen, um sie von unär nach dezimal zu konvertieren.

Martin Ender
quelle
8

Python 2 , 76 Bytes

lambda e:sum([[len(e+s)-2*s.count('+')]+[1]*len(s)for s in e.split('=')],[])

Probieren Sie es online!

xnor
quelle
3
Können Sie eine Erklärung hinzufügen?
Calvins Hobbys
1
@HelkaHomba Die Idee ist ziemlich einfach: Nehmen Sie zuerst jeden Teil der Eingabe, der durch Gleichheitszeichen aufgeteilt ist. Wählen Sie die erste Nummer jedes Blocks aus, der sein soll eqtn_len + plus_signs + minus_signs - 2 * plus_signs = eqtn_len + minus_signs - plus_signs. Da alle anderen Zahlen im Chunk Eins sind, ergibt sich die Summe für den Chunk zu eqtn_len + minus_signs - plus_signs - minus_signs + plus_signs = eqtn_len. Die Gleichungslänge muss positiv sein, damit alles funktioniert.
FryAmTheEggman
6

Python 2, 199 179 178 172 162 158 156 152 151 Bytes

Viel zu lang, aber die Lösung war einfach zu erstellen.

from itertools import*
i=input()
k='%s'
s=k+k.join(i)+k
for p in product(*[range(1,65537)]*-~len(i)):
    if eval((s%p).replace('=','==')):print s%p;break

Probieren Sie es online aus

Dies wird jede Möglichkeit versuchen, bis es eine Lösung findet. Das Programm ist extrem langsam. Außerdem wird der String bei jeder Iteration ersetzt. Der "172" -Edit hat es drastisch langsamer gemacht, da er nicht mit einem kleinen Bereich beginnt, sondern mit dem max. Zum Beispiel müssen die Eingaben -=oder =+2 ** 32 Versuche versuchen, bevor eine Lösung erreicht wird.

Um das Programm zu beschleunigen, verwenden Sie die Version mit 178 Bytes aus dem Bearbeitungsverlauf.

mbomb007
quelle
rangeErstellt python2 nicht sofort den gesamten Bereich als Liste? IIRC können Sie es beschleunigen, indem Sie xrangestattdessen, wie ich denke, das ist die Lazy-Loading-Version (Python3 verwendet Lazy als Standard range)
Delioth
1
@Delioth Das verwendet jedoch ein anderes Byte. Das Ziel ist es , Bytes zu entfernen . Das würde auch nicht viel Beschleunigung bringen, da der Großteil der Verlangsamung von der Anzahl der Iterationen herrührt, nicht von der Erstellung der Liste, die nur einmal auftritt. Ich bin gelaufen print range(1,65537)und in 0.034 s fertig.
mbomb007
Nun, natürlich - eher ein "das könnte es mit genau der gleichen Methodik beschleunigen", da die Sorge so lange dauert. Memory Thrashing kann zu einer deutlichen Verlangsamung führen. Sie könnten auch einige Bytes (vielleicht nur 1) kürzen, indem Sie nichts einstellen l=..., aber das in das Feld rechts setzen product(range(...),repeat=len(s)+1). Wenn Sie Klammern benötigen, wird nur ein Byte
gespeichert
@Delioth Auch wenn ich Parens brauchte len(s)+1, könnte ich -~len(s)stattdessen verwenden, was keine Parens erfordert.
mbomb007
Ah richtig. Ich vergesse immer bitweise Operationen und Tricks - die Arbeit am Frontend-Javascript muss meine Python-Expertise aufbrauchen!
Delioth
5

JavaScript (ES6), 92 82 Byte

8 Bytes mit einem Trick von @xnor gespielt

let f =
x=>x.split`=`.map(q=>(x+q).length-2*~-q.split`+`.length+[...q,''].join(1)).join`=`
<input oninput="if(/^[+=-]+$/.test(value))O.innerHTML=f(value)" value="="><br>
<pre id=O>1=1</pre>

Der Trick besteht hier darin, 1nach jedem +oder ein einzufügen -und jedem Ausdruck die Zahl voranzustellen, die bewirkt, dass der Ausdruck der Länge der Eingabe entspricht. Auf diese Weise können wir garantieren, dass die Zahl immer positiv ist. Da =die Zeichenfolge immer mindestens 1 enthält , kann die Anzahl der +s niemals die Länge der Zeichenfolge erreichen, sodass der Rest immer mindestens 1 ist 1. Sie können dies überprüfen, indem Sie im +obigen Snippet eine beliebige Anzahl von s eingeben .

ETHproductions
quelle
5

Python 2 , 120 119 Bytes

-1 Byte dank mbomb007

a=['1'+(n and('1'.join(n)+'1'))for n in input().split('=')]
print'='.join(`max(map(eval,a))-eval(c)+1`+c[1:]for c in a)

Probieren Sie es online! oder Überprüfen Sie alle Testfälle

Zuerst 1füge ich in jede Position ein, um den höchsten Wert zu überprüfen, und füge ihn dann als Versatz in jede Gleichung ein. Dies funktioniert, weil Sie keine negativen Zahlen hinzufügen können, sodass das minimale Ergebnis durch die Menge von +in der Gleichung angegeben wird, die nur hat +.

Stange
quelle
Sie können einige Leerzeichen entfernen.
mbomb007
5

GNU Prolog, 156 Bytes

x(L,R,V)-->{E#>0},({L=[E|R],E=V};x(L,[E|R],X),("+",{V#=X+E};"-",{V#=X-E})).
q(L,R,V)-->x(L,T,V),({T=R};"=",q(T,R,V)).
s(Q,L):-q(L,[],_,Q,[]),fd_labeling(L).

Erläuterung

Wir müssen eine Reihe von Gleichungen lösen. Warum also nicht einen tatsächlichen Gleichungslöser verwenden?

xist im Grunde ein Gleichungsauswerter für Gleichungen der Form +-+; Zusätzlich zur Gleichung selbst gibt es zwei zusätzliche Argumente (eine Differenzliste L,R, die die Werte der Gleichung enthält, und einen Wert V, den die Gleichung auswertet). Wie üblich in Prolog, kann es jede mögliche Weise Runde verwendet werden (zB können Sie festlegen , Vein und erhalten L,R, geben L,Rund eine bekommen V, die beide angeben , und stellen Sie sicher , dass der Wert korrekt ist, oder keines von beiden in diesem Fall entsprechende Beschränkungen angeben wird auf beide gesetzt werden Vund L,R). Das "aktuelle Element" von L,Rwird benannt E, und wir fügen auch eine Behauptung hinzu, dassEist größer als 0 (da für die Frage die Verwendung positiver Zahlen erforderlich ist). Diese Funktion ist etwas ausführlicher, als ich es gerne hätte, z. B. musste ich die [E|R]Musterübereinstimmung zweimal schreiben , da Listen rechtsassoziativ sind, Addition und Subtraktion jedoch linksassoziativ. Leider müssen wir eine tatsächliche Liste verwenden, anstatt unseren eigenen linksassoziativen Listentyp aus Konsolen zu erfinden, damit wir fd_labelingarbeiten können.

qist ähnlich wie x, enthält aber auch =. Es ruft im Grunde nur auf xund selbst rekursiv. Im übrigen ist es eine sehr klare Demonstration, wie Differenzlisten arbeiten, die zeigen , dass Sie zwei Differenzlisten verketten L,Tund T,Rzu einem einzigen Differenzliste L,R. Die Grundidee ist, dass eine Differenzliste eine Teilfunktion ist, die ein Argument annimmt Rund einen Wert zurückgibt, Ldem Rdie Liste selbst vorangestellt ist. Indem wir also das Argument einer Differenzliste und den Rückgabewert einer anderen identifizieren, können wir die Funktionen zusammensetzen und somit die Listen verketten.

Schließlich ist sdas die Funktion, die die Aufgabe in der Frage tatsächlich löst, eine Wrapper-Funktion, die qmit Argumenten aufruft . Wir wandeln die Differenzliste in eine reguläre Liste um, indem wir []als Argument fd_labelingangeben und eine Lösung für die von uns erstellte Gleichung finden. (Standardmäßig scheint es zu gefallen, Werte auf 1 zu setzen, wenn es keinen Grund gibt, sie auf etwas anderes zu setzen. Sie kann jedoch konfiguriert werden. Sie value_method(random)bietet "interessantere" Lösungen, als beispielsweise überall eine 1 zu setzen, und ist immer noch sehr schnell. )

Beispielausgabe

Mit dem Programm wie geschrieben:

| ?- s("=++=+-=-+=--=", V).

V = [3,1,1,1,3,1,1,3,1,1,5,1,1,3] ?

Wenn ich das Programm etwas länger mache, um a hinzuzufügen value_method(random), variiert das Ergebnis, sieht aber ungefähr so ​​aus:

| ?- s("=++=+-=-+=--=", V).

V = [68,6,12,50,85,114,131,45,3,26,71,1,2,68] ? 

In beiden Fällen ?bedeutet das Ende der Ausgabe, dass es möglicherweise mehr als eine Lösung gibt. (Natürlich wissen wir in diesem Fall, dass es viel mehr als eine Lösung gibt!)


quelle
4

Mathematica, 116 Bytes

Join@@(Prepend[#^2,1-Min[Tr/@c]+Tr@#]&/@(c=Characters@StringSplit["0"<>#<>"0","="]/."+"->-1/."-"->1/."0"->Nothing))&

Reine Funktion, die eine Zeichenfolge als Eingabe verwendet und eine Liste positiver Ganzzahlen zurückgibt. Grundlegende Strategie: Wir addieren immer nur 1 und subtrahieren 1 und wählen die Anfangszahlen in jedem Ausdruck, um alles gleich zu machen.

c=Characters@StringSplit[#,"="]/."+"->-1/."-"->1würde die Eingabezeichenfolge bei jedem Gleichheitszeichen aufteilen und dann jeweils +durch -1und -durch ersetzen 1. Wenn jedoch am Anfang oder Ende ein Gleichheitszeichen steht, wird es ignoriert. Deshalb fügen wir an jedem Ende künstlich ein neues Zeichen hinzu ( "0"<>#<>"0") und lassen es verschwinden, nachdem die Aufteilung der Zeichenfolgen abgeschlossen ist ( /."0"->Nothing).

Die Summe jeder Unterliste entspricht nun einer ganzen Zahl, die wir vor das +s und -s stellen können, um jeden Ausdruck gleich zu machen. 1-Min[Tr/@c]ist die kleinste Ganzzahl, die wir zu jeder Summe addieren können, um sie alle positiv zu machen. Also Prepend[#^2,1-Min[Tr/@c]+Tr@#]&nimmt jede Unterliste (die ^2alle ihre Einträge 1aufdreht) und stellt ihre Summe um diese kleinste kompensierende Ganzzahl verschoben voran. Die resultierenden Listen werden Joinzusammengefügt, um die Ausgabe zu erzeugen.

Greg Martin
quelle
3

Rubin, 76

->s{(?1+s.gsub(/./){|a|a+?1}).split(?=).map{|e|e[0]="#{5**8-eval(e)}";e}*?=}

Der Zielwert für die Ausdrücke ist 5**8aus Golfgründen auf minus 1 festgelegt ! Ursprünglich habe ich s.size+1minus 1 verwendet.

Ungolfed im Testprogramm

f=->s{(?1+s.gsub(/./){|a|a+?1}).           #add a 1 at the beginning and after every symbol
       split(?=).                          #split into an array of expressions at = signs
       map{|e|                             #for each expression string
         e[0]="#{5**8-eval(e)}";e          #change the first number to 5**8-eval(e)
       }*?=                                #and rejoin the strings
}


puts f["="] 
puts f["=="] 
puts f["+="] 
puts f["=+"]
puts f["-="]
puts f["=-"]
puts f["=-="]
puts f["=+="]
puts f["==="]
puts f["+=-"]
puts f["-=+"]
puts f["+=+"]
puts f["-=-"]
puts f["--="]
puts f["++="]
puts f["-+="]
puts f["+-="]
puts f["+-=-="]
puts f["--=--"]
puts f["==-=="]
puts f["=++=+-=-+=--="]
puts f["+--++-=-+-+-"]
puts f["======"]

Ausgabe

390624=390624
390624=390624=390624
390623+1=390624
390624=390623+1
390625-1=390624
390624=390625-1
390624=390625-1=390624
390624=390623+1=390624
390624=390624=390624=390624
390623+1=390625-1
390625-1=390623+1
390623+1=390623+1
390625-1=390625-1
390626-1-1=390624
390622+1+1=390624
390624-1+1=390624
390624+1-1=390624
390624+1-1=390625-1=390624
390626-1-1=390626-1-1
390624=390624=390625-1=390624=390624
390624=390622+1+1=390624+1-1=390624-1+1=390626-1-1=390624
390624+1-1-1+1+1-1=390625-1+1-1+1-1
390624=390624=390624=390624=390624=390624=390624
Level River St
quelle
2

PHP 207 204 197 114 Bytes

direkter anflug: viel kürzer und schneller

foreach(explode("=",$argn)as$t)echo"="[!$c],strlen($argn)+($c=count_chars($t))[45]-$c[43],@chunk_split($t,!!$t,1);

Laufen Sie mit echo '<input>' | php -nR '<code>'oder testen Sie es online .

Nervenzusammenbruch

foreach(explode("=",$argn)as$t) // loop through terms
    echo                            // print ...
        "="[!$c],                       // 1. "=" if not first term
        strlen($argn)                   // 2. maximum number
            +($c=count_chars($t))[45]   //    + number of "-"
            -$c[43],                    //    - number of "+"
        @chunk_split($t,!!$t,1);        // 3. each operator followed by "1"
  • !$cist wahr in der ersten Iteration, die 1für die Indexierung von Zeichenfolgen verwendet wird; "="[1]ist leer.
    Danach $cwird gesetzt und !$cfalse, umgewandelt in 0und "="[0]ist das erste Zeichen.
  • Der Maximalwert für einen Term darf die Anzahl der Pluspunkte +1 nicht überschreiten.
    Wir sind also mit der Länge der Eingabe auf jeden Fall sicher. Alle Begriffe werden dahingehend bewertet.
  • chunk_split($s,$n,$i)fügt $inach jedem $nZeichen von $s- und am Ende ein.
    Um zu verhindern, dass leere Begriffe in geändert werden, 1wird ein Fehler erzwungen, indem die Blocklänge auf festgelegt wird 0.
Titus
quelle
1

Röda , 112 110 109 Bytes

f x{[(`:$x:`/"=")()|{|p|p~=":",""a=p;a~=`\+`,""b=p;b~="-","";["=",#x-#b+#a];{(p/"")|{|o|[o,"1"*#o]}_}}_][1:]}

Probieren Sie es online!

Die Split-Funktion funktionierte mit diesem Programm nicht so, wie ich es wollte. Gibt beispielsweise split("", sep="")eine leere Zeichenfolge anstelle von nichts zurück. Wie ist das logisch? Aufgrund dessen ist das Programm fast 20 Bytes größer als es sein könnte, wenn die geteilte Semantik ideal wäre.

Die Idee dieser Antwort ist, dass wir wissen, dass die Länge der Eingabezeichenfolge größer oder gleich dem Wert der Gleichung sein muss, daher definieren wir den Wert der Gleichung als Länge der Zeichenfolge. Für jeden Teil der Gleichung denken wir, dass jeder Operator +1oder ist, -1und subtrahieren und addieren sie zum Wert der Gleichung.

Ungolfed:

function f(x) {
    /* Adds ":"s around the string to prevent "=" being split wrong. */
    [split(`:$x:`, sep="=") | for p do
        p ~= ":", ""          /* Removes colons. */
        a := p; b := p        /* Initializes a and b to be p. */
        a ~= "\\+", ""        /* The lengths of a and are now equal to the */
        b ~= "-", ""          /* numbers of "-" and "+" characters in x. */
        push("=", #x-#b+#a)   /* Prints "=" and the value of the equation */
                              /* minus number of "+"s plus number of "-"s. */
        split(p, sep="") | for o do /* For each operator: */
            push(o)                 /* Prints the operator. */
            push(1) if [o != ""]    /* Prints 1 unless the operator is "". */
        done
    done][1:] /* Removes the first character of the output ("="). */
}
fergusq
quelle