diff --git a/alg.py b/alg.py new file mode 100644 index 0000000..0421f0a --- /dev/null +++ b/alg.py @@ -0,0 +1,240 @@ +from collections import namedtuple; +from copy import copy + +def flattenByValue(lst): + return sorted([s for subl in lst for s in subl], key=lambda x: x.value) + +def flatten(lst): + return flattenByValue(lst) + +def flattenBySeed(lst): + return sorted([s for subl in lst for s in subl], key=lambda x: x.seed) + +def print_1(tavolo, n): + print('-------------',n,'-------------') + for t in tavolo.cards: + print(t) + print('-------------',n,'-------------') + +Card = namedtuple('Card', 'seed value') + +class Mano: + cards = list() # lista di cards + def __init__(self, carte): + assert type(carte) is list and type(carte[0]) is Card + self.cards = carte # lista di Carte + def cardsByValue(self): + return sorted(self.cards, key=lambda c: c.value) + def cardsBySeed(self): + return sorted(self.cards, key=lambda c: c.seed) + +class TaggedCards: + cards = None + tag = '' + tipo = '' + def __init__(self, carte): + assert type(carte) is list and type(carte[0]) is Card + self.cards = carte # lista di Carte + self.tag = 'NonValido' if not is_valida(self.cards) else 'Valido' + self.tipo = 'Singolo' if len(carte) == 1 else 'Tris' if carte[0].seed != carte[1].seed else 'Scala' + + def __repr__(self): + return "TaggedCards<%s, %s, %s>" % (self.cards, self.tag, self.tipo) + + def __iter__(self): + return self.cards.__iter__() + + def cardsByValue(self): + return sorted(self.cards, key=lambda c: c.value) + def cardsBySeed(self): + return sorted(self.cards, key=lambda c: c.seed) + +class Tavolo: + cards = list() # lista di taggedcards + def __init__(self, cs): + assert type(cs) is list + self.cards = cs + + def __repr__(self): + return "Tavolo<%s>" % (self.cards,) + + def getNonValide(self): + assert type(self.cards[0]) is TaggedCards + f = [c for c in self.cards if c.tag == 'NonValido'] + # return list(flattenByValue(f)) + return f + + def getValide(self): + assert type(self.cards[0]) is TaggedCards + f = [c for c in self.cards if c.tag == 'Valido'] + # return list(flattenByValue(f)) + return f + + def getAll(self): + # return list(flattenByValue(self.cards)) + return self.cards + +def gioca(tavolo, giocata, da_muovere): + assert type(da_muovere) is Card + idx = tavolo.cards.index(giocata) + for current_tag in ['NonValido', 'Valido']: + for i, t in enumerate(tavolo.cards): + if t.tag == current_tag and da_muovere in t.cards: + t = [c for c in t.cards if c != da_muovere] + if t != []: + tavolo.cards[i] = [TaggedCards(t)] # mettilo davanti cosi` che sia il primo + # preso in considerazione + del tavolo.cards[idx] + tavolo.cards = [TaggedCards(giocata.cards + [da_muovere])] + tavolo.cards + return tavolo + assert False + +def alg(tavolo, tavolo_iniziale, soluzioni, n): + # qua si presume di avere gia` tutte le carte della mano stese sul tavolo come gruppo singolo + # di carte non valide (alla prima iterazione) + print_1(tavolo, n) + nonV = tavolo.getNonValide() + if n >= 20: # maximum depth + return + elif len(nonV) == 0: + return + else: + for carte in nonV: + # carte = nonV[0] # TaggedCards + assert type(carte) is TaggedCards and carte.tag == 'NonValido' + vicini = find_vicini(carte, tavolo) # lista di Card + for v in vicini: + next_tavolo = gioca(copy(tavolo), carte, v) + alg(next_tavolo, tavolo_iniziale, soluzioni, n+1) + +def find_vicini(carte, tavolo): + assert type(tavolo) is Tavolo and type(carte) is TaggedCards + all = flatten(tavolo.getAll()) + if carte.tipo == 'Singolo': + return [a for a in all if is_tris(carte.cards+[a]) or is_straight(carte.cards+[a])] + elif carte.tipo == 'Tris': + return [a for a in all if is_tris(carte.cards+[a])] + elif carte.tipo == 'Scala': + return [a for a in all if is_straight(carte.cards+[a])] + else: + assert False + +def no_double_seed(carte): + seeds = set([c.seed for c in carte]) + return len(seeds) == len(carte) + +def is_only_one_seed(carte): + seeds = set([c.seed for c in carte]) + return len(seeds) == 1 + +def no_double_value(carte): + seeds = set([c.value for c in carte]) + return len(seeds) == len(carte) + +def is_tris(carte): + values = set([c.value for c in carte]) + if len(values) == 1: + return no_double_seed(carte) + else: + return False + +def split(values, accum=[]): + a = values[0] + if len(values) > 2: + b = values[1] + if a == b - 1: + return split(values[1:], accum + [a]) + else: + return accum + [a], values[1:] + else: + return accum + [a], values[1:] + +def is_straight(carte): + assert type(carte) is list and type(carte[0]) is Card + def _is_straight(carte): + if len(carte) == 1: + return True + elif len(carte) == 0: + assert False + else: + a = carte[0] + b = carte[1] + if a == b - 1: + return _is_straight(carte[1:]) + else: + return False + + if not no_double_value(carte) and is_only_one_seed(carte): + return False + else: + values = [v for s, v in sorted(carte, key=lambda x:x.value)] + first, last = values[0], values[-1] + if last == 13 and first == 1: + head, tail = split(values) + return _is_straight(head) and _is_straight(tail) + else: + return _is_straight(values) + +def is_valida(carte): + carte = list(sorted(carte, key = lambda x : x[1])) + if len(carte) < 3: + return False + else: + a = carte[0][1] + b = carte[1][1] + if a == b: + return is_tris(carte) + else: + return is_straight(carte) + +carte_test = [Card('quadri', 1), Card('picche', 1), Card('fiori', 1), Card('cuori', 1)] +print(is_valida(carte_test)) + +carte_test = [Card('picche', 13), Card('picche', 12), Card('picche', 1)] +print(is_valida(carte_test)) + +carte_test = [Card('quadri', 1), Card('picche', 1)] +print(is_tris(carte_test)) +carte_test = [Card('picche', 13), Card('picche', 1)] +print(is_straight(carte_test)) + +# find_vicini test +tavolo_test = Tavolo([TaggedCards([Card('picche', 1), Card('fiori', 1), Card('cuori', 1)])]) +res = find_vicini(TaggedCards([Card('quadri', 1)]), tavolo_test) +assert set(res) == {Card('fiori', 1), Card('cuori', 1), Card('picche', 1)} +# mano_test = [('quadri', 2),('quadri', 4)] +tavolo_test = Tavolo([TaggedCards([Card('picche', 1), Card('fiori', 1), Card('cuori', 1)])]) +# assert set(find_vicini([('quadri', 1), ('quadri', 3)], [carte_test], mano_test)) == set([('fiori', 1), ('picche', 1), ('cuori', 1), ('quadri', 2), ('quadri', 4)]) + + + +if __name__ == '__main__': + # tavolo = [{("picche", 8), ("picche", 9), ("picche", 7)}, {("fiori", 9),("fiori", 8), ("fiori", 7)} ,{("cuori", 10), ("cuori", 9),("cuori", 8), ("cuori", 7)}] + # mano = {("cuori", 11),("cuori", 12), ("quadri", 7)} + tavolo = Tavolo([ + TaggedCards([ + Card("picche", 2), + Card("fiori", 2), + Card("cuori", 2)]), + TaggedCards([ + Card("cuori", 1), + Card("fiori", 1), + Card("picche", 1), + Card("quadri", 1)]), + TaggedCards([ + Card("quadri", 13)]), + TaggedCards([ + Card("quadri", 12)]), + TaggedCards([ + Card("cuori", 13)]), + TaggedCards([ + Card("cuori", 12)]), + TaggedCards([ + Card("fiori", 3)]), + TaggedCards([ + Card("picche", 3)]), + TaggedCards([ + Card("cuori", 12)]) + ]) + alg(tavolo, tavolo, [], 0) +