http://qiita.com/arc279/items/7894d582a882906b94c7 Continuation de cela.
C'était beaucoup plus ennuyeux que prévu.
Après quelques essais et erreurs, c'est devenu une chose misérable. C'est intéressant, donc je le posterai en quittant le procès.
J'écris assez grossièrement, donc je serais heureux si vous pouviez me dire si c'est étrange.
Voici la référence. Comme il ne s'agit que d'un jugement de couleur clair, je suis parti d'ici et je l'ai réécrit un peu avec ma super interprétation. http://d.hatena.ne.jp/staebchen/20100403/1270256158
J'ai utilisé la fermeture et le générateur Si vous essayez de le réécrire avec autre chose que python, cela peut être difficile, mais ce n'est pas grave.
C'est le même que celui avant les bases, mais je l'ai retravaillé tel quel, donc je vais tout remettre.
Personnellement, je n'aime pas mettre du code à l'extérieur comme # gist.
mj2.py
#!/usr/bin/env python
# -*- coding: utf8 -*-
import itertools
import random
class Yama(list):
u'''mur'''
WANPAI_NUM = 14
class TsumoDoesNotRemain(Exception):
u'''Seul le roi reste'''
pass
def __init__(self):
pais = [ Pai.from_index(i)
for i in range(Pai.TOTAL_KIND_NUM * Pai.NUM_OF_EACH_KIND) ]
#La lessive
random.shuffle(pais)
super(Yama, self).__init__(pais)
def tsumo(self):
u'''L'autonomie'''
if len(self) <= self.WANPAI_NUM:
raise self.TsumoDoesNotRemain
return self.pop(0)
def wanpai(self):
u'''Roi'''
return self[-self.WANPAI_NUM:]
def haipai(self):
u'''Distribution'''
tehais = [ Tehai(), Tehai(), Tehai(), Tehai() ] #est(parent)Sud Ouest Nord
# 4*3 tours
for j in range(0, 3):
for tehai in tehais:
for i in range(0, 4):
pai = self.tsumo()
tehai.append(pai)
#Choncho
for tehai in tehais:
pai = self.tsumo()
tehai.append(pai)
pai = self.tsumo()
tehais[0].append(pai)
return tehais
class Pai(object):
u'''牌'''
TOTAL_KIND_NUM = 34 # M/P/S +Tous types de personnages
NUM_OF_EACH_KIND = 4 #4 feuilles par type
NUM_OF_EACH_NUMBER_PAIS = 9 # M/P/Le nombre de S est 1..Jusqu'à 9
class Suit:
M = 0 #Homme
P = 1 #Tube
S = 2 #Mesure
J = 3 #Personnage
NAMES = {
M: u"Homme",
P: u"Tube",
S: u"Mesure",
J: u" ",
}
class Num:
NAMES = {
1: u"un",
2: u"deux",
3: u"Trois",
4: u"quatre",
5: u"Cinq",
6: u"Six",
7: u"Sept",
8: u"Huit",
9: u"Neuf",
}
class Tsuhai:
E = 1
S = 2
W = 3
N = 4
HAK = 5
HAT = 6
CHU = 7
NAMES = {
E: u"est",
S: u"Sud",
W: u"Ouest",
N: u"Nord",
HAK: u"blanc",
HAT: u"Repoussant",
CHU: u"Pendant ~",
}
@classmethod
def all(cls):
u'''Tous les carreaux'''
return [cls(suit, num)
for suit in cls.Suit.NAMES
for num in range(1, cls.NUM_OF_EACH_NUMBER_PAIS+1)
if suit != cls.Suit.J
] + [ cls(cls.Suit.J, num) for num in cls.Tsuhai.NAMES.keys() ]
@classmethod
def yaochupai(cls):
u'''么 9 牌'''
return [
cls(cls.Suit.M, 1),
cls(cls.Suit.M, 9),
cls(cls.Suit.P, 1),
cls(cls.Suit.P, 9),
cls(cls.Suit.S, 1),
cls(cls.Suit.S, 9),
cls(cls.Suit.J, cls.Tsuhai.E),
cls(cls.Suit.J, cls.Tsuhai.S),
cls(cls.Suit.J, cls.Tsuhai.W),
cls(cls.Suit.J, cls.Tsuhai.N),
cls(cls.Suit.J, cls.Tsuhai.HAK),
cls(cls.Suit.J, cls.Tsuhai.HAT),
cls(cls.Suit.J, cls.Tsuhai.CHU),
]
@classmethod
def chuchanpai(cls):
u'''Nakahari'''
yaochupai = cls.yaochupai()
return [ x for x in cls.all() if x not in yaochupai ]
def __init__(self, suit, num):
self.suit = suit
self.num = num
@property
def index(self):
return self.suit * self.NUM_OF_EACH_NUMBER_PAIS + self.num - 1
def is_next(self, other, index=1):
u'''Que ce soit le prochain numéro'''
if self.suit != self.Suit.J: #Pas une lettre
if self.suit == other.suit: #Le même type de tuile
if other.num == (self.num + index): #Numéro de série
return True
return False
def is_prev(self, other, index=1):
u'''Que ce soit le numéro précédent'''
return self.is_next(other, -index)
@classmethod
def is_syuntsu(cls, first, second, third):
u'''Que ce soit Junko'''
#return second.is_prev(first) and second.is_next(third)
return first.is_next(second) and first.is_next(third, 2)
def __repr__(self):
#return str((self.suit, self.num)) #Affichage Taple
if self.suit == self.Suit.J:
return self.Tsuhai.NAMES[self.num].encode('utf-8')
else:
return (self.Num.NAMES[self.num] + self.Suit.NAMES[self.suit]).encode('utf-8')
def __eq__(self, other):
return self.suit == other.suit and self.num == other.num
@classmethod
def from_index(cls, index):
u'''Obtenir de l'index'''
kind = index % cls.TOTAL_KIND_NUM
if True:
suit = kind / cls.NUM_OF_EACH_NUMBER_PAIS
num = kind % cls.NUM_OF_EACH_NUMBER_PAIS + 1
else:
if 0 <= kind < 9:
suit = cls.Suit.M
num = kind - 0 + 1
elif 9 <= kind < 18:
suit = cls.Suit.P
num = kind - 9 + 1
elif 18 <= kind < 27:
suit = cls.Suit.S
num = kind - 18 + 1
elif 27 <= kind < 34:
suit = cls.Suit.J
num = kind - 27 + 1
assert(cls.Suit.M <= suit <= cls.Suit.J)
assert(1 <= num <= cls.NUM_OF_EACH_NUMBER_PAIS)
return cls(suit, num)
@classmethod
def from_name(cls, name):
u'''Obtenir du nom'''
for x in cls.all():
if name == repr(x):
return x
return None
class Tehai(list):
u'''Artisanat'''
@staticmethod
def sorter(a, b):
u'''Comment faire'''
return a.suit - b.suit if a.suit != b.suit else a.num - b.num
def rihai(self):
u'''Rimu'''
self.sort(cmp=self.sorter)
return self
@classmethod
def aggregate(cls, tehai):
u'''{牌 graine:Nombre de feuilles}Agrégat sous forme de'''
hash = { x[0]: len(list(x[1])) for x in itertools.groupby(tehai.rihai()) }
#Renvoyer la clé (tuiles triées) ensemble
return hash, sorted(hash.keys(), cmp=cls.sorter)
def show(self):
u'''Affichage sous une forme facile à lire'''
line1 = u"|"
line2 = u"|"
for pai in self.rihai():
if pai.suit != Pai.Suit.J:
line1 += Pai.Num.NAMES[pai.num] + u"|"
line2 += Pai.Suit.NAMES[pai.suit] + u"|"
else:
line1 += Pai.Tsuhai.NAMES[pai.num] + u"|"
line2 += u" |"
print line1.encode("utf-8")
print line2.encode("utf-8")
@classmethod
def search_syuntsu(cls, pais, keys):
u'''Trouver Junko
L'argument est agrégé()Passez sous la même forme que la valeur de retour de.'''
for i in range( len(keys)-2 ): #Pas besoin de vérifier les 2 dernières feuilles
tmp = pais.copy()
first = keys[i]
if tmp[first] >= 1:
try:
second = keys[i+1]
third = keys[i+2]
except IndexError as e:
#Il n'y a pas 2 types restants
continue
if not Pai.is_syuntsu(first, second, third):
continue
if tmp[second] >= 1 and tmp[third] >= 1:
tmp[first] -= 1
tmp[second] -= 1
tmp[third] -= 1
#Junko trouvé,Tuiles restantes
yield (first, second, third), tmp
@classmethod
def search_kohtu(cls, pais, keys):
u'''Trouvez la gravure
L'argument est agrégé()Passez sous la même forme que la valeur de retour de.'''
for i, p in enumerate(keys):
tmp = pais.copy()
if tmp[p] >= 3:
tmp[p] -= 3
#Gravure trouvée,Tuiles restantes
yield (p, p, p), tmp
C'était horrible d'écrire en bon état. Mais non. C'est ennuyeux de le réparer plus.
Attendre le 9e côté Kuren Baotou peut être un peu suspect. Je ne peux pas le vérifier correctement car il y a trop de types d'attente ...
C'est juste un formulaire d'attente et aucun jugement de rôle n'est inclus.
De plus, je suis épuisé, donc j'ai hâte de voir Shichitoko et Kokushi Musou. Eh bien, je pense que cela peut être fait avec un peu de soin pour distinguer le type Agari.
mj2.py
def check_tenpai(tehai):
u'''Vérifiez la forme de l'audition'''
# TODO:En attendant Shichitoko et Kokushi Musou je n'ai pas vérifié
assert(len(tehai) == 13)
# (Atama,visage,Attendre)Forme de
candidate = set()
def check_machi(mentsu, tartsu):
u'''Examiner la forme de l'attente'''
assert(len(mentsu) == 3)
keys = sorted(tartsu.keys(), cmp=Tehai.sorter)
#print mentsu, tartsu, keys
def check_tanki():
u'''Contrôle d'attente pour un seul cheval'''
for i, p in enumerate(keys):
tmp = tartsu.copy()
if tmp[p] == 3:
#La face restante est gravée
assert(len(tmp) == 2)
tmp[p] -= 3
tanki = { pai: num for pai, num in tmp.items() if num > 0 }.keys()
#Plongez dans le visage
ins = tuple( sorted(mentsu + [(p, p, p)]) )
candidate.add( ((), ins, tuple(tanki)) )
else:
#Le visage restant est Junko
first = p
try:
second = keys[i+1]
third = keys[i+2]
except IndexError as e:
continue
if not Pai.is_syuntsu(first, second, third):
continue
tmp[first] -= 1
tmp[second] -= 1
tmp[third] -= 1
tanki = { pai: num for pai, num in tmp.items() if num > 0 }.keys()
#Plongez dans le visage
ins = tuple( sorted(mentsu + [(first, second, third)]) )
candidate.add( ((), ins, tuple(tanki)) )
def check_non_tanki():
u'''Vérification en attente autre qu'un cheval seul'''
for i, p in enumerate(keys):
tmp = tartsu.copy()
#Contrôle de la tête de moineau
if not tmp[p] >= 2:
continue
tmp[p] -= 2
atama = (p, p)
for j, q in enumerate(keys):
#Double face
try:
next = keys[j+1]
if q.is_next(next):
ins = tuple( sorted(mentsu) )
candidate.add( (atama, ins, (q, next) ) )
break
except IndexError as e:
pass
#Raccord
try:
next = keys[j+1]
if q.is_next(next, 2):
ins = tuple( sorted(mentsu) )
candidate.add( (atama, ins, (q, next) ) )
break
except IndexError as e:
pass
#Alors allez
if tmp[q] >= 2:
ins = tuple( sorted(mentsu) )
candidate.add( (atama, ins, (q, q) ) )
break
check_tanki()
check_non_tanki()
#Rechercher 3 visages
pais, keys = Tehai.aggregate(tehai)
#print pais, keys
if True:
#Je me demande si cela se fait récursivement
def search_mentsu(depth, proc):
searchers = [Tehai.search_syuntsu, Tehai.search_kohtu]
#Junko/Recherche de gravure
def inner(pais, mentsu = [], nest = 0):
if nest < depth:
for search in searchers:
for m, a in search(pais, keys):
inner(a, mentsu + [m], nest+1)
else:
proc(mentsu, pais)
inner(pais)
search_mentsu(3, lambda mentsu, pais:
check_machi(mentsu, { x[0]:x[1] for x in pais.items() if x[1] > 0 })
)
else:
#Si tu écris solidement comme ça
searchers = [Tehai.search_syuntsu, Tehai.search_kohtu]
for p1 in searchers:
for p2 in searchers:
for p3 in searchers:
#Application
for m1, a1 in p1(pais, keys):
for m2, a2 in p2(a1, keys):
for m3, a3 in p3(a2, keys):
mentsu = [m1, m2, m3]
#Tuiles restantes
tartsu = { x[0]:x[1] for x in a3.items() if x[1] > 0 }
check_machi(mentsu, tartsu)
return candidate
Cela pour le débogage.
mj2.py
class Debug:
u'''for debug'''
TEST_HOHRA = [
[2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7],
[0, 0, 8, 8, 13, 13, 20, 20, 25, 25, 29, 29, 31, 31], #Quand
[0, 8, 9, 17, 18, 26, 27, 28, 29, 30, 31, 32, 33, 9], #Grinçant
[33, 33, 33, 32, 32, 32, 31, 31, 31, 0, 0, 0, 2, 2], #Daisangen
[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 1], #Churenpoto
[19, 19, 20, 20, 21, 21, 23, 23, 23, 25, 25, 32, 32, 32], #Ryu-so
[0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 0, 1, 2], #Chinitsu Ittsu Epaco
]
TEST_TENPAI = [
[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8], #Véritable Churenpoto
[1, 2, 3, 4, 5, 5, 5, 6, 20, 20, 21, 22, 23], #Kan-chan Shabo(Junko est enlacé)
[13, 14, 15, 18, 19, 19, 20, 21, 24, 24, 24, 31, 31], #Ryanmen Kan-chan
[25, 25, 25, 1, 2, 3, 11, 12, 13, 11, 23, 23, 23], #Ryanmen Tanki
[25, 25, 25, 1, 2, 3, 11, 12, 13, 11, 12, 23, 24], #Ryanmen
[1, 2, 3, 4, 4, 6, 7, 8, 9, 10, 11, 29, 29], #Shabo
]
@classmethod
def tehai_from_indexes(cls, indexes):
assert(len(indexes) == 13 or len(indexes) == 14)
return Tehai([ Pai.from_index(x) for x in indexes ])
@classmethod
def test_hohra(cls, idx = None):
u'''Test d'achèvement'''
return cls.tehai_from_indexes(cls.TEST_HOHRA[idx])
@classmethod
def test_tenpai(cls, idx = 0):
u'''Test de forme d'écoute'''
return cls.tehai_from_indexes(cls.TEST_TENPAI[idx])
@classmethod
def gen_tehai(cls, num = 14):
u'''Faites un arrangement approprié'''
assert(num == 13 or num == 14)
yama = Yama()
return Tehai([ yama.tsumo() for x in range(num) ])
@classmethod
def gen_hohra(cls):
u'''Faire une forme d'agari appropriée'''
tehai = Tehai()
def gen_syuntsu():
u'''Faire Junko'''
first = Pai.from_index(random.choice(range(Pai.TOTAL_KIND_NUM)))
if first.suit == Pai.Suit.J:
#Les personnages ne peuvent pas être Junko
return None
if first.num > 7:
# (7 8 9)Ce qui précède ne peut pas être Junko
return None
second = Pai(first.suit, first.num+1)
third = Pai(first.suit, first.num+2)
if tehai.count(first) == 4 or tehai.count(second) == 4 or tehai.count(third) == 4:
#Nombre restant insuffisant
return None
return [first, second, third]
def gen_kohtu():
u'''Faire de la gravure'''
pai = Pai.from_index(random.choice(range(Pai.TOTAL_KIND_NUM)))
if tehai.count(pai) >= 2:
#Nombre restant insuffisant
return None
return [pai, pai, pai]
def gen_atama():
u'''Faire une tête de moineau'''
pai = Pai.from_index(random.choice(range(Pai.TOTAL_KIND_NUM)))
if tehai.count(pai) >= 3:
#Nombre restant insuffisant
return None
return [pai, pai]
tehai.extend(gen_atama()) #Tête de moineau
#Si Junko et Kokuko ont la même probabilité d'apparition, nous les pondérerons.
weighted_choices = [(gen_syuntsu, 3), (gen_kohtu, 1)]
population = [val for val, cnt in weighted_choices for i in range(cnt)]
while len(tehai) < 14:
ret = random.choice(population)()
if ret is not None:
tehai.extend(ret)
return tehai
@classmethod
def gen_tenpai(cls):
u'''Créez une forme d'écoute appropriée'''
tehai = cls.gen_hohra()
assert(len(tehai) == 14)
#Retirez une pièce de la forme Agari
tehai.pop(random.randrange(len(tehai)))
return tehai
class Test:
u'''for test'''
@classmethod
def check_tenho(cls):
u'''Chèque Tenwa'''
import sys
for cnt in (x for x in itertools.count()):
print >>sys.stderr, cnt
yama = Yama()
oya, _, _, _ = yama.haipai()
ret = check_hohra(oya)
if ret:
print "---------------------------------------------"
print cnt
oya.show()
for atama, mentsu in ret:
print atama, mentsu
break
@classmethod
def check_machi(cls, times = 100):
u'''Vérifiez beaucoup d'attente'''
for x in range(times):
tehai = Debug.gen_tenpai()
ret = check_tenpai(tehai.rihai())
if not ret:
#Quand je viens ici, je ne suis pas tempéré. Le point est un dysfonctionnement. L'artisanat à modifier.
print oya
print [ Pai.from_name(repr(x)).index for x in oya ]
print "complete."
if __name__ == '__main__':
Test.check_machi()
Pour le moment, même si vous cochez beaucoup de formes d'écoute, vous ne les manquerez probablement pas ... La question est de savoir si je peux lister correctement toutes les attentes ...
Je pense qu'il y a place à amélioration parce que je fais beaucoup de choses inutiles.
S'il vous plaît laissez-moi savoir s'il y a des bogues.
Si vous vérifiez l'attente du véritable Kuren Baotou, cela ressemble à ceci.
La première ligne est un artisanat.
2ème et suivantes lignes «En attendant un visage de tête de moineau» Sous la forme de.
[Ichiman, Ichiman, Ichiman,Niman,Sanman,Shiman,Allez mec,Rokuman,Nanaman,Hachiman,Kuman,Kuman,Kuman]
() ((Ichiman, Ichiman, Ichiman), (Sanman,Shiman,Allez mec), (Rokuman,Nanaman,Hachiman), (Kuman, Kuman, Kuman)) (Niman,)
() ((Ichiman, Ichiman, Ichiman), (Niman,Sanman,Shiman), (Allez mec,Rokuman,Nanaman), (Kuman, Kuman, Kuman)) (Hachiman,)
(Kuman, Kuman) ((Ichiman,Niman,Sanman), (Shiman,Allez mec,Rokuman), (Nanaman,Hachiman, Kuman)) (Ichiman, Ichiman)
(Ichiman, Ichiman) ((Ichiman,Niman,Sanman), (Rokuman,Nanaman,Hachiman), (Kuman, Kuman, Kuman)) (Shiman,Allez mec)
(Kuman, Kuman) ((Ichiman, Ichiman, Ichiman), (Niman,Sanman,Shiman), (Allez mec,Rokuman,Nanaman)) (Hachiman, Kuman)
(Kuman, Kuman) ((Ichiman, Ichiman, Ichiman), (Shiman,Allez mec,Rokuman), (Nanaman,Hachiman, Kuman)) (Niman,Sanman)
(Kuman, Kuman) ((Ichiman, Ichiman, Ichiman), (Niman,Sanman,Shiman), (Nanaman,Hachiman, Kuman)) (Allez mec,Rokuman)
(Ichiman, Ichiman) ((Sanman,Shiman,Allez mec), (Rokuman,Nanaman,Hachiman), (Kuman, Kuman, Kuman)) (Ichiman,Niman)
(Ichiman, Ichiman) ((Ichiman,Niman,Sanman), (Shiman,Allez mec,Rokuman), (Nanaman,Hachiman,Kuman)) (Kuman,Kuman)
() ((Ichiman, Ichiman, Ichiman), (Niman,Sanman,Shiman), (Rokuman,Nanaman,Hachiman), (Kuman, Kuman, Kuman)) (Allez mec,)
(Ichiman, Ichiman) ((Ichiman,Niman,Sanman), (Shiman,Allez mec,Rokuman), (Kuman, Kuman, Kuman)) (Nanaman,Hachiman)
Cela vous convient-il vraiment?