Computing angestrebte Anzahl von zahlen in einem set
Arbeite ich an einer Hausaufgabe das problem, dass der mich fragt diese:
Tiven einer endlichen Menge von zahlen und eine Ziel-Zahl, finden, wenn das set kann verwendet werden, um die Berechnung der Ziel-Nummer durch einfache mathematische Operationen (add, sub, mult, div) und mit jeder Zahl in der Menge genau einmal (so muss ich zu Auspuff set). Dies hat zu tun mit Rekursion.
So, zum Beispiel, wenn ich über die set
{1, 2, 3, 4}
- und Ziel-10, dann konnte ich abrufen, indem Sie mithilfe
((3 * 4) - 2)/1 = 10.
Ich versuche zu formulieren, die der Algorithmus in pseudo-code, aber bisher noch nicht dazu gekommen zu weit. Ich denke die Grafiken sind der Weg zu gehen, würde aber auf jeden Fall schätzen die Hilfe. danke.
- Was haben Sie bisher studiert? In welcher Klasse / Lektion hast du die Hausaufgaben? Das erste, was mir in den Sinn kommt ist, genetische algorithmen, aber wenn man noch nicht studiert, noch, gibt es wahrscheinlich etwas anderes, wie eine erschöpfende Suche. Auch, müssen Sie Konto für Klammern? Oder sind Sie garantiert in der Lage sein zu Holen Sie sich die Ziel-Zahl, ohne Sie als gut? Und eine weitere Sache, müssen Sie verwenden Sie jede Zahl EXAKT einmal, oder höchstens einmal?
- Sorry, ich sollte gewesen klarer. Lesen wieder das problem, es besagt, dass jede Zahl soll GENAU einmal verwendet werden. Die Klammern wurden Hinzugefügt, für den sake des Beispiels, das ändert sich jetzt in ((3*4)-2)/1 = 10... danke für den Hinweis, diese Dinge.
- Sie könnte vergessen, über den Vorrang einfach durch die Verwendung eines Präfix (oder postfix) - notation: (/ (- (* 3 4) 2) 1).
- Was ist es, was führt Sie zu denken, sollten Sie verwenden ein graph-Algorithmus? Was tun die Knoten/Kanten des Graphen entsprechen, in den das problem?
- Ersetzen Sie die Zahl "10" durch "24" und erhalten Sie stackoverflow.com/questions/2277015/....
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gut, Sie hat nicht erwähnt Effizienz, also werde ich post-ein wirklich brute-force-Lösung und lassen Sie Sie optimieren, wenn Sie wollen. Da können Sie Klammern, es ist einfach zu brute-force es mit Die Umgekehrte Polnische Notation:
Vor allem, wenn Ihre set hat n zahlen, Sie muss exakt n - 1 Operatoren. So wird Ihre Lösung sein, gegeben durch eine Sequenz von 2n - 1 Symbole aus {{Ihre gegebenen Satz}, {*, /, +, - }}
Dies ist nicht dazu gedacht, um die Schnellste Lösung, sondern eher ein lehrreiches ein.
Mit 4 Operanden, 4 mögliche Operatoren, die es erzeugt alle 7680 = 5 * 4! * 4^3
möglich Ausdrücken.
Dies ist definitiv nicht gut skalieren, da die Anzahl der Ausdrücke für N Operanden [1, 8, 192, 7680, 430080, 30965760, 2724986880, ...].
Im Allgemeinen, wenn Sie haben
n+1
Operanden und fügenn
Betreiber ausgewählt ausk
Möglichkeiten, dann gibt es(2n)!/n! k^n
möglich Gleichungen.Glück!
Darüber nachgedacht, wie das problem zu lösen (wie mit Grafiken), es hilft wirklich, schauen Sie nur das problem. Wenn Sie finden, sich selbst stecken und kann nicht scheinen zu kommen mit einem pseudo-code, dann am ehesten, es ist etwas, dass Sie halten sich zurück; Einige andere Frage oder Sorge haben, ist noch nicht angesprochen worden-noch. Ein Beispiel 'sticky' Frage in diesem Fall sein könnte, "Was genau ist rekursiv über dieses problem?"
Bevor Sie im nächsten Absatz Lesen, versuchen, eine Antwort auf diese Frage zum ersten mal. Wenn Sie wüsste, was rekursiv über das problem, dann Schreibe eine rekursive Methode, es zu lösen könnte nicht sehr schwierig sein.
Möchten Sie wissen, wenn einige Ausdruck, der verwendet eine Reihe von zahlen (jede Zahl nur einmal verwendet) gibt Ihnen einen Ziel Wert. Es gibt vier binäre Operationen, die jeweils mit einer inverse. Also, in anderen Worten, Sie wollen wissen, ob die erste Zahl betrieben mit einigen Ausdruck des anderen Nummern gibt Sie das Ziel. Naja, in anderen Worten, Sie wollen wissen, wenn einige Ausdruck des 'anderen' zahlen [...]. Wenn nicht, dann mit der ersten operation, mit der ersten Zahl nicht wirklich geben Ihnen, was Sie brauchen, so versuchen die anderen ops. Wenn Sie nicht funktionieren, dann ist es vielleicht einfach nicht sein soll.
Edit: ich dachte, dies ist für ein infix-Ausdruck der vier Operatoren ohne Klammern, da Sie einen Kommentar auf der ursprünglichen Frage gesagt, die Klammern wurden Hinzugefügt, für den Willen, ein Beispiel (für die Klarheit?) und die Nutzung der Klammer war nicht explizit angegeben.
Generell, wenn Sie etwas tun müssen rekursiv hilft es zu Beginn von "unten" und denken Sie Ihren Weg nach oben.
Bedenken Sie: Sie haben eine Reihe
S
von n zahlen{a,b,c,...}
, und ein Satz von vier Operationen{+,-,*,/}
. Nennen wir Ihre rekursive Funktion, die arbeitet auf der eingestelltenF(S)
F(S)
wird nur sein, dass Nummer.F(S)
acht Dinge:S
(2 Entscheidungen)x
ausS
zu den linken Operanden (n Entscheidungen)F(S-x)
Ich lasse Sie es nehmen von hier aus. 🙂
Bearbeiten: Markieren, stellt eine gültige Kritik, die oben genannten Methode nicht absolut alles. Um dieses problem zu beheben, müssen Sie darüber nachdenken, es in einer etwas anderen Weise:
S
in zwei sets, für die linken und rechten Operanden,F
auf beiden PartitionenFinden Sie alle Partitionen einer Menge in 2 Teile ist nicht trivial, selbst, wenn.
(1+2)*(3+4)
.Ihre besten Anhaltspunkt darüber, wie zur Lösung dieses Problems ist die Tatsache, dass dein Lehrer/professor will Sie, Rekursion zu verwenden. Das heißt, diese nicht ein Mathe-problem - es ist ein such-problem.
Nicht zu viel verraten (es ist Hausaufgaben, nachdem alle), aber Sie haben, um zu laichen einen Aufruf der rekursiven Funktion mit einem operator, einer Zahl und einer Liste mit den restlichen Nummern. Die rekursive Funktion extrahiert eine Zahl aus der Liste, und Sie über den Betrieb übergeben, kombinieren Sie es mit der Nummer übergeben (das ist Ihre laufende Summe). Nehmen Sie die laufende Summe und nennen sich selbst wieder mit der restlichen Gegenstände auf der Liste (haben Sie zum Durchlaufen der Liste in der call aber die Reihenfolge der Aufrufe ist Tiefe-zuerst). Tun Sie dies einmal für jede der vier Betreiber, es sei denn, der Erfolg wurde erreicht durch eine frühere Bein der Suche.
Ich aktualisiert diese mit einer Liste statt einem Stapel
Wenn das Ergebnis der operation ist Ihr Ziel-Nummer und die Liste leer ist, dann haben Sie erfolgreich gefunden, das eine Reihe von Operationen (solche, verfolgt den Pfad des erfolgreichen leaf) - legen Sie die Erfolg-Flagge und entspannen. Beachten Sie, dass die Betreiber nicht auf eine Liste, noch sind Sie in den Ruf: die Funktion sich selbst immer iteriert über alle vier. Ihr Mechanismus für die "Rückabwicklung" der operator-Sequenz aus dem erfolgreichen Blatt zu bekommen, die Folge ist die Rückkehr der aktuelle Betreiber und der Zahl vorangestellt, um den Wert, der zurückgegeben wird, durch rekursiven Aufruf (von denen nur eine erfolgreich sein wird, da Sie halt an Erfolg -, die, natürlich, ist das ein zu verwenden). Wenn kein Erfolg, dann wird das, was Sie zurückgeben, ist nicht wichtig, jedenfalls.
Update Dies ist viel schwieriger, wenn Sie haben zu prüfen, Ausdrücke, wie die, die Daniel gepostet. Sie haben die Kombinatorik auf die zahlen und die Gruppen (zahlen aufgrund der Tatsache, dass /und - sind, um sensibel auch ohne Gruppierung und Gruppierung, weil es änderungen Vorrang). Natürlich haben Sie auch die Kombinatorik der Operationen. Es ist schwieriger zu verwalten, die Unterschiede zwischen (4 + 3) * 2 und 4 + (3 * 2), weil die Gruppierung nicht recurse wie Operatoren oder zahlen (die kannst du einfach Durchlaufen in der Breite ersten Weise während Ihrer (Tiefe-zuerst) rekursive Aufrufe).
Hier einige Python-code, um Ihnen den Einstieg: es ist einfach Drucke alle möglichen Ausdrücke, ohne sich sorgen zu viel über Redundanz. Sie müssten, um es zu ändern, um Ausdrücke auszuwerten und zu vergleichen, um die Ziel-Zahl, anstatt Sie zu drucken.
Die Grundidee ist: gegeben eine Menge S von zahlen, partition von S in zwei Teilmengen
left
undright
in alle möglichen Richtungen (wo wir kümmern uns nicht um die Reihenfolge oder die Elemente inleft
undright
), so dassleft
undright
sind beide nicht leer. Nun für jede dieser Partitionen, finden Sie alle Möglichkeiten der Kombination der Elemente inleft
(rekursiv!), und ähnlich fürright
, und kombinieren Sie die beiden resultierenden Werte mit allen möglichen Operatoren. Die Rekursion Höschen aus, wenn ein Satz hat nur ein element, in dem Fall gibt es nur ein Wert möglich.Selbst wenn Sie nicht wissen, Python, der
expressions
- Funktion sollte relativ einfach zu Folgen; diesplittings
Funktion enthält einige Python Merkwürdigkeiten, aber alle es tut, ist, finden Sie alle Partitionen in der Listel
in Links und rechts Stücke.pusedo code:
dann man einfach das base-case-in. Ich glaube, ich verschenkte zu viel.