[PYTHON] Ten Puzzle-Make 10 mit nur 4 Zahlen und 4 Regeln

Ich glaube, ich habe gespielt, um 10 zu machen, indem ich mir die Nummer des entgegenkommenden Autos angesehen habe, z. B. wenn ich in einem Auto bin, und addiere, subtrahiere, multipliziere und teile, aber manchmal gibt es ein schwieriges Problem Sie müssen etwas tun, bevor Sie fortfahren. Außerdem frage ich mich, wie viele Kombinationen ich nicht lösen kann. Probieren wir also alle vier 0-9-Zahlenpaare und Operatorkombinationen aus und schreiben ein Programm, um die Ergebnisse anzuzeigen.

Verweise:

Wie macht man

Die dritte Referenzstelle befindet sich in Python. Da die Formel jedoch in eine Zeichenfolge konvertiert und an die eval-Funktion übergeben wird, wird die Ausführungsgeschwindigkeit extrem langsam (Programmier-FAQ - Python 2.7ja1-Dokumentation:. Siehe Programmierung.html # id20)). Wie in der zweiten Referenzstelle gezeigt, sind die Operatoren daher sechs Operatoren mit einer Unterscheidung in der Reihenfolge der Subtraktion und Division. Das ist,

from operator import add, sub, mul, div

def rsub(a, b):
    return sub(b, a)

def rdiv(a, b):
    return div(b, a)

o = [add, sub, rsub, mul, div, rdiv]

Erstellen Sie eine Liste der Operatoren als. Der Operator wird dreimal verwendet, vorausgesetzt, a, b, c, d sind Zahlen und o1, o2, o3 sind Operatoren.

((a o1 b) o2 c) o3 d ・ ・ ・ 1 (a o1 b) o3 (c o2 d) ・ ・ ・ 2

Es gibt nur zwei Möglichkeiten.

Es gibt 4! = 24 Möglichkeiten, a, b, c, d auszuwählen, aber wenn 1, werden Duplikate mit a und b ersetzt, sodass 24/2 = 12 Möglichkeiten zur Auswahl stehen. Wenn Sie wie folgt schreiben, listet die Liste "X" alle Fälle aus der Zeichenfolge "q" (wie "1337") auf, mit Ausnahme doppelter Zahlen (wie "3" in "1337"). Kann in gespeichert werden.

from itertools import combinations

q = [float(i) for i in list(q)]

X = []
for a, b in combinations([0, 1, 2, 3], 2):
    t = [0, 1, 2, 3]
    t.remove(a)
    t.remove(b)
    x = (q[a], q[b], q[t[0]], q[t[1]])
    if not x in X:
        X.append(x)
    x = (q[a], q[b], q[t[1]], q[t[0]])
    if not x in X:
        X.append(x)

Im Fall von 2 ist es nicht notwendig, über die Kombination von a und b, die Kombination von c und d und die Kombination von (a, b) und (c, d) nachzudenken. Wenn Sie also über die drei möglichen Anordnungen von Zahlen nachdenken, Ich weiß, dass es gut ist. Da die Anzahl klein ist, ist es möglicherweise einfacher zu verstehen, wenn Sie solide schreiben, anstatt über Kombinationen nachzudenken.

X = [
    (q[0], q[1], q[2], q[3]),
    (q[0], q[2], q[1], q[3]),
    (q[0], q[3], q[1], q[2]),
    ]

Bei der Auswahl von o1 werden 6 Dinge 3 Stellen zugewiesen, daher sollten 6 3 = 216 Möglichkeiten in Betracht gezogen werden.

from itertools import product

O = [i for i in product(range(6), repeat=3)]

So können Sie alle Kombinationen machen.

Danach können Sie für alle Kombinationen von O den Inhalt von X für die beiden Muster berechnen und das Muster aufzeichnen, das 10 wird. Zu diesem Zeitpunkt wird ZeroDivisionError angezeigt, sodass Sie die Ausnahme behandeln müssen. Ich habe die Antwort in eine Zeichenfolge konvertiert, damit sie leicht zu sehen ist. Aufgrund der Beschaffenheit des Computers können auch einige Fehler auftreten. Daher haben wir beschlossen, einen Fehler mit einer Zahl (0,001) zuzulassen, die kleiner ist als die Zahl, die durch Teilen von 1 durch 9 durch die 3. Potenz (= 0,0013717421124828531 ...) erhalten wird.

Produkt

Die tatsächlich hergestellte ist unten gezeigt. Da es auf dem IPython Notebook ausgeführt wurde, ist es nur eine Funktionsdefinition.

from itertools import permutations, combinations, product
from operator import add, sub, mul, div
from ipython_doctester import test

#@test
def make10(q='1337', verbose=True):
    """Make 10 from 4 numbers(0~9).
    
    q : String, ex) 1337
    verbose: Bool, print the results or not
    
    doctest code:
    >>> make10()
    ((7/3)+1)*3
    True
    """
    q = [float(i) for i in list(q)]

    def rsub(a, b):
        return sub(b, a)
    def rdiv(a, b):
        return div(b, a)
    o = [add, sub, rsub, mul, div, rdiv]
    o_k = ['+', '-', '-', '*', '/', '/']
    O = [i for i in product(range(6), repeat=3)]
    
    TOL = 0.001
    
    res = []
    
    for o1, o2, o3 in O:
        # ((a o1 b) o2 c) o3 d
        X = []
        for a, b in combinations([0, 1, 2, 3], 2):
            t = [0, 1, 2, 3]
            t.remove(a)
            t.remove(b)
            x = (q[a], q[b], q[t[0]], q[t[1]])
            if not x in X:
                X.append(x)
            x = (q[a], q[b], q[t[1]], q[t[0]])
            if not x in X:
                X.append(x)
        
        for a, b, c, d in X:
            try:
                result = o[o3](o[o2](o[o1](a,b),c),d)
            except ZeroDivisionError:
                continue
            if abs(result - 10) < TOL:
                if o1 == 2 or o1 == 5:
                    a, b = b, a
                p1 = "(%d%s%d)" % (a, o_k[o1], b)
                if o2 == 2 or o2 == 5:
                    p2 = "%d%s" % (c, o_k[o2]) + p1
                else:
                    p2 = p1 + "%s%d" % (o_k[o2], c)
                if o3 == 2 or o3 == 5:
                    p = "%d%s" % (d, o_k[o3]) + "(" + p2 + ")"
                else:
                    p = "(" + p2 + ")" + "%s%d" % (o_k[o3], d)
                res.append(p)
        
        # (a o1 b) o3 (c o2 d)
        X = [
            (q[0], q[1], q[2], q[3]),
            (q[0], q[2], q[1], q[3]),
            (q[0], q[3], q[1], q[2]),
            ]
        
        for a, b, c, d in X:
            try:
                result = o[o3](o[o1](a,b),o[o2](c,d))
            except ZeroDivisionError:
                continue
            if abs(result - 10) < TOL:
                if o1 == 2 or o1 == 5:
                    a, b = b, a
                p1 = "(%d%s%d)" % (a, o_k[o1], b)
                if o2 == 2 or o2 == 5:
                    c, d = d, c
                p2 = "(%d%s%d)" % (c, o_k[o2], d)
                if o3 == 2 or o3 == 5:
                    p = p2 + o_k[o3] + p1
                else:
                    p = p1 + o_k[o3] + p2
                res.append(p)
        
    if verbose:
        for r in res:
            print r
        
    if len(res) > 0:
        return True
    else:
        return False

Wenn Sie dies für alle Zahlenkombinationen berechnen,

import itertools
A = [''.join(i) for i in 
     itertools.combinations_with_replacement(
            [str(x) for x in range(10)], 4)]
index_A = [make10(a, verbose=False) for a in A]

false = [a for i,a in enumerate(A) if not index_A[i]]

print len(false), false

Ergebnis ist

163 ['0000', '0001', '0002', '0003', '0004', '0005', '0006', '0007', '0008', '0009', '0011', '0012', '0013', '0014', '0015', '0016', '0017', '0018', '0022', '0023', '0024', '0026', '0027', '0029', '0033', '0034', '0035', '0036', '0038', '0039', '0044', '0045', '0047', '0048', '0049', '0056', '0057', '0058', '0059', '0066', '0067', '0068', '0069', '0077', '0078', '0079', '0088', '0089', '0099', '0111', '0112', '0113', '0114', '0116', '0117', '0122', '0123', '0134', '0144', '0148', '0157', '0158', '0166', '0167', '0168', '0177', '0178', '0188', '0222', '0233', '0236', '0269', '0277', '0279', '0299', '0333', '0335', '0336', '0338', '0344', '0345', '0348', '0359', '0366', '0369', '0388', '0389', '0399', '0444', '0445', '0447', '0448', '0457', '0478', '0479', '0489', '0499', '0566', '0567', '0577', '0588', '0589', '0599', '0666', '0667', '0668', '0677', '0678', '0689', '0699', '0777', '0778', '0788', '0799', '0888', '1111', '1112', '1113', '1122', '1159', '1169', '1177', '1178', '1179', '1188', '1399', '1444', '1499', '1666', '1667', '1677', '1699', '1777', '2257', '3444', '3669', '3779', '3999', '4444', '4459', '4477', '4558', '4899', '4999', '5668', '5788', '5799', '5899', '6666', '6667', '6677', '6777', '6778', '6888', '6899', '6999', '7777', '7788', '7789', '7799', '7888', '7999', '8899']

Und zu Wikipedia Das Ergebnis ist das gleiche wie das, was aufgelistet wurde.

Zusammenfassung

Die iterative Berechnung dauerte ungefähr 10 Sekunden, aber jetzt sind es ungefähr 2,5 Sekunden (obwohl es langsam ist), und ich habe viel darüber gelernt, wie man Kombinationen und inklusive Notationen schreibt. Sie können die Anzahl der Operatoren erhöhen, um Strom und Protokolle zu speichern, oder Sie können ein Leerzeichen einfügen und 2- oder 3-stellige Zahlen anstelle von verbundenen Zeichenfolgen verwenden.

Wenn Sie Fehler haben oder mehr tun möchten, weisen Sie bitte darauf hin.

Recommended Posts

Ten Puzzle-Make 10 mit nur 4 Zahlen und 4 Regeln
Sortieren mit einer Mischung aus Zahlen und Buchstaben
Ich habe versucht, natürliche Zahlenausdrücke und arithmetische Verarbeitung nur mit Listenverarbeitung
Mayungos Python Learning Episode 5: Ich habe versucht, vier Regeln mit Zahlen zu machen
Unterscheiden Sie zwischen Zahlen und Buchstaben mit regulären Ausdrücken
Skript zum Twittern mit Vielfachen von 3 und Zahlen mit 3 !!
Holen Sie sich nur Response Header mit Curl und Wget
Generieren Sie Fibonacci-Zahlen mit Python-Closures, Iteratoren und Generatoren
Konvertiert Zahlen mit Kommas und Dreiecken in numerische Typen.
[Python] Extrahieren Sie nur Zahlen aus Listen und Zeichenfolgen