[PYTHON] Ten Puzzle-Make 10 avec seulement 4 chiffres et 4 règles

Je pense que j'ai joué pour faire 10 en regardant le numéro de la voiture venant en sens inverse, comme lorsque je suis dans une voiture, et en ajoutant, en soustrayant, en multipliant et en divisant. Vous devez faire quelque chose avant de continuer. Aussi, je me demande combien de combinaisons je ne peux pas résoudre. Alors, essayons les quatre paires de nombres 0-9 et combinaisons d'opérateurs et écrivons un programme pour afficher les résultats.

Les références:

Comment faire

Le troisième site de référence est en Python. Cependant, comme la formule est convertie en chaîne de caractères et transmise à la fonction eval, la vitesse d'exécution devient extrêmement lente (FAQ de programmation - documentation Python 2.7ja1:. Voir programmation.html # id20)). Par conséquent, comme le montre le deuxième site de référence, les opérateurs sont six opérateurs avec une distinction dans l'ordre de soustraction et de division. C'est,

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]

Créez une liste d'opérateurs sous forme de. L'opérateur est utilisé trois fois, en supposant que a, b, c, d sont des nombres et o1, o2, o3 sont des opérateurs.

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

Il n'y a que deux façons.

Il y a 4! = 24 façons de sélectionner a, b, c, d, mais quand 1, il y a des doublons avec a et b remplacés, donc il y a 24/2 = 12 façons de choisir. Plus précisément, si vous écrivez comme suit, la liste «X» listera tous les cas de la chaîne de caractères «q» (comme «1337») sauf les nombres en double (comme «3» dans «1337»). Peut être stocké au format.

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)

Dans le cas de 2, il n'est pas nécessaire de penser à la combinaison de a, b, à la combinaison de c, d et à la combinaison de (a, b) et (c, d), donc si vous pensez à la séquence de trois nombres. Je sais que c'est bon. Puisque le nombre est petit, il peut être plus facile à comprendre si vous écrivez solidement plutôt que de penser à des combinaisons.

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

Quant à la façon de sélectionner o1, 6 choses sont attribuées à 3 places, donc 6 3 = 216 façons doivent être considérées.

from itertools import product

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

Vous pouvez donc faire toutes les combinaisons.

Après cela, pour toutes les combinaisons de O, nous pouvons calculer les deux modèles en utilisant le contenu de X et enregistrer celui qui devient 10. À ce moment-là, ZeroDivisionError sera affiché, vous devez donc gérer l'exception. J'ai converti la réponse en une chaîne pour la rendre plus facile à voir. De plus, en raison de la nature de l'ordinateur, certaines erreurs peuvent survenir, nous avons donc décidé d'autoriser une erreur d'un nombre (0,001) plus petit que le nombre obtenu en divisant 1 par 9 à la 3e puissance (= 0,0013717421124828531 ...).

Produit

Celui qui est réellement fabriqué est illustré ci-dessous. Puisqu'il fonctionnait sur le notebook IPython, il ne s'agit que d'une définition de fonction.

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

Ensuite, si vous calculez cela pour toutes les combinaisons de nombres,

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

Le résultat est

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']

Et à Wikipedia Le résultat est le même que celui qui a été répertorié.

Résumé

Cela a pris environ 10 secondes pour le calcul itératif, mais maintenant c'est environ 2,5 secondes (même si c'est lent), et j'ai beaucoup appris sur la façon d'écrire des combinaisons et la notation inclusive. Vous pouvez augmenter le nombre d'opérateurs pour mettre la puissance et les journaux, ou vous pouvez mettre un espace et utiliser des nombres à 2 ou 3 chiffres au lieu de chaînes connectées.

Si vous avez des erreurs ou si vous souhaitez en faire plus, veuillez le signaler.

Recommended Posts

Ten Puzzle-Make 10 avec seulement 4 chiffres et 4 règles
Tri avec un mélange de chiffres et de lettres
J'ai essayé l'expression des nombres naturels et le traitement arithmétique uniquement avec le traitement de liste
Mayungo's Python Learning Episode 5: J'ai essayé de faire quatre règles avec des nombres
Distinguer les chiffres et les lettres avec des expressions régulières
Script pour tweeter avec des multiples de 3 et des nombres avec 3 !!
Obtenez uniquement l'en-tête de réponse avec curl et wget
Générez des nombres de Fibonacci avec des fermetures, des itérateurs et des générateurs Python
Convertit les nombres avec des virgules et des triangles en types numériques.
[Python] Extraire uniquement les nombres des listes et des chaînes de caractères