This commit is contained in:
Francesco Mecca 2019-08-13 23:55:50 +02:00
parent 23d38adf7f
commit 52a41690cf
5 changed files with 235 additions and 147 deletions

208
alg.py
View file

@ -1,6 +1,8 @@
from collections import namedtuple; from collections import namedtuple;
from copy import deepcopy as copy # FUK from copy import deepcopy as copy # FUK
DO_TESTS = False
DO_PRINT = True
MAX = -1000 MAX = -1000
best = None best = None
DONE = False DONE = False
@ -16,6 +18,8 @@ def flattenBySeed(lst):
return sorted([s for subl in lst for s in subl], key=lambda x: x.seed) return sorted([s for subl in lst for s in subl], key=lambda x: x.seed)
def print_1(tavolo, n): def print_1(tavolo, n):
if not DO_PRINT:
return
global MEM, MAX global MEM, MAX
st = ('------------- '+str(n)+':'+str(tavolo.punteggio())+':'+str(MAX)+' -------------'+'='+str(len(MEM))) st = ('------------- '+str(n)+':'+str(tavolo.punteggio())+':'+str(MAX)+' -------------'+'='+str(len(MEM)))
print(st) print(st)
@ -30,10 +34,6 @@ class Mano:
def __init__(self, carte): def __init__(self, carte):
assert type(carte) is list and type(carte[0]) is Card assert type(carte) is list and type(carte[0]) is Card
self.cards = carte # lista di Carte 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: class TaggedCards:
cards = None cards = None
@ -79,12 +79,6 @@ class TaggedCards:
else: else:
return False return False
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: class Tavolo:
cards = list() # lista di taggedcards cards = list() # lista di taggedcards
def __init__(self, cs): def __init__(self, cs):
@ -100,13 +94,11 @@ class Tavolo:
def getNonValide(self): def getNonValide(self):
assert type(self.cards[0]) is TaggedCards assert type(self.cards[0]) is TaggedCards
f = [c for c in self.cards if c.tag == 'NonValido'] f = [c for c in self.cards if c.tag == 'NonValido']
# return list(flattenByValue(f))
return f return f
def getValide(self): def getValide(self):
assert type(self.cards[0]) is TaggedCards assert type(self.cards[0]) is TaggedCards
f = [c for c in self.cards if c.tag == 'Valido'] f = [c for c in self.cards if c.tag == 'Valido']
# return list(flattenByValue(f))
return f return f
def getAll(self): def getAll(self):
@ -129,11 +121,8 @@ def gioca(tavolo, giocata, da_muovere):
if not rimpiazzata and da_muovere in t.cards: if not rimpiazzata and da_muovere in t.cards:
t = [c for c in t.cards if c != da_muovere] t = [c for c in t.cards if c != da_muovere]
if t != []: if t != []:
# tavolo.cards[i] = TaggedCards(t)
news.append(TaggedCards(t)) news.append(TaggedCards(t))
rimpiazzata = True rimpiazzata = True
# tavolo.cards[idx] = TaggedCards(giocata.cards + [da_muovere])
# return tavolo
else: else:
news.append(t) news.append(t)
return Tavolo(news) return Tavolo(news)
@ -181,12 +170,10 @@ def alg(tavolo, tavolo_iniziale, soluzioni, n, punteggio):
for v in vicini: for v in vicini:
next_tavolo = gioca(tavolo, carte, v) next_tavolo = gioca(tavolo, carte, v)
assert startL == next_tavolo.llen() assert startL == next_tavolo.llen()
# recur
alg(next_tavolo, tavolo_iniziale, soluzioni, n+1, copy(punteggio)) alg(next_tavolo, tavolo_iniziale, soluzioni, n+1, copy(punteggio))
def find_vicini(carte, tavolo): def find_vicini(carte, tavolo):
def _find_vicini(carte, all): def _find_vicini(carte, all):
# all = flatten(tavolo.getAll())
if carte.tipo == 'Singolo': if carte.tipo == 'Singolo':
return [a for a in all if is_tris(carte.cards+[a]) or is_straight(carte.cards+[a])] return [a for a in all if is_tris(carte.cards+[a]) or is_straight(carte.cards+[a])]
elif carte.tipo == 'Tris': elif carte.tipo == 'Tris':
@ -267,101 +254,101 @@ def is_valida(carte):
else: else:
return is_straight(carte) return is_straight(carte)
carte_test = [Card('quadri', 1), Card('picche', 1), Card('fiori', 1), Card('cuori', 1)] if DO_TESTS:
print(is_valida(carte_test)) 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)] carte_test = [Card('picche', 13), Card('picche', 12), Card('picche', 1)]
print(is_valida(carte_test)) print(is_valida(carte_test))
carte_test = [Card('quadri', 1), Card('picche', 1)] carte_test = [Card('quadri', 1), Card('picche', 1)]
print(is_tris(carte_test)) print(is_tris(carte_test))
carte_test = [Card('picche', 13), Card('picche', 1)] carte_test = [Card('picche', 13), Card('picche', 1)]
print(is_straight(carte_test)) print(is_straight(carte_test))
# find_vicini test # find_vicini test
tavolo_test = Tavolo([TaggedCards([Card('picche', 1), Card('fiori', 1), Card('cuori', 1)])]) tavolo_test = Tavolo([TaggedCards([Card('picche', 1), Card('fiori', 1), Card('cuori', 1)])])
res = find_vicini(TaggedCards([Card('quadri', 1)]), tavolo_test) res = find_vicini(TaggedCards([Card('quadri', 1)]), tavolo_test)
assert set(res) == {Card('fiori', 1), Card('cuori', 1), Card('picche', 1)} assert set(res) == {Card('fiori', 1), Card('cuori', 1), Card('picche', 1)}
# mano_test = [('quadri', 2),('quadri', 4)] # mano_test = [('quadri', 2),('quadri', 4)]
tavolo_test = Tavolo([TaggedCards([Card('picche', 1), Card('fiori', 1), Card('cuori', 1)])]) 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)]) # assert set(find_vicini([('quadri', 1), ('quadri', 3)], [carte_test], mano_test)) == set([('fiori', 1), ('picche', 1), ('cuori', 1), ('quadri', 2), ('quadri', 4)])
tavolo_test = Tavolo([ tavolo_test = Tavolo([
TaggedCards([Card(seed='cuori', value=1), Card(seed='fiori', value=1), Card(seed='picche', value=1), Card(seed='quadri', value=1)]), TaggedCards([Card(seed='cuori', value=1), Card(seed='fiori', value=1), Card(seed='picche', value=1), Card(seed='quadri', value=1)]),
TaggedCards([Card(seed='quadri', value=12), Card(seed='cuori', value=12), Card(seed='cuori', value=12), Card(seed='cuori', value=13)])]) TaggedCards([Card(seed='quadri', value=12), Card(seed='cuori', value=12), Card(seed='cuori', value=12), Card(seed='cuori', value=13)])])
res = find_vicini(TaggedCards([Card(seed='quadri', value=13)]), tavolo_test) res = find_vicini(TaggedCards([Card(seed='quadri', value=13)]), tavolo_test)
assert set(res) == {Card('quadri', 1), Card('quadri', 12), Card('cuori', 13)} assert set(res) == {Card('quadri', 1), Card('quadri', 12), Card('cuori', 13)}
assert TaggedCards([Card('picche', 2)]) < TaggedCards([Card('picche',2), Card('fiori', 2)]) assert TaggedCards([Card('picche', 2)]) < TaggedCards([Card('picche',2), Card('fiori', 2)])
assert TaggedCards([Card('picche', 2)]) < TaggedCards([Card('picche',2), Card('fiori', 2)]) assert TaggedCards([Card('picche', 2)]) > TaggedCards([Card('picche',2), Card('fiori', 2), Card('cuori', 2), Card('quadri', 2)])
assert TaggedCards([Card('picche', 2)]) > TaggedCards([Card('picche',2), Card('fiori', 2), Card('cuori', 2), Card('quadri', 2)])
if __name__ == '__main__': if __name__ == '__main__':
# tavolo = Tavolo([ tavolo1 = Tavolo([
# TaggedCards([ TaggedCards([
# Card("picche", 2), Card("picche", 2),
# Card("fiori", 2), Card("fiori", 2),
# Card("cuori", 2)]), Card("cuori", 2)]),
# TaggedCards([ TaggedCards([
# Card("cuori", 1), Card("cuori", 1),
# Card("fiori", 1), Card("fiori", 1),
# Card("picche", 1), Card("picche", 1),
# Card("quadri", 1)]), Card("quadri", 1)]),
# # mano # mano
# TaggedCards([ TaggedCards([
# Card("quadri", 13)]), Card("quadri", 13)]),
# TaggedCards([ TaggedCards([
# Card("quadri", 12)]), Card("quadri", 12)]),
# TaggedCards([ TaggedCards([
# Card("cuori", 13)]), Card("cuori", 13)]),
# TaggedCards([ TaggedCards([
# Card("cuori", 12)]), Card("cuori", 12)]),
# TaggedCards([ TaggedCards([
# Card("fiori", 3)]), Card("fiori", 3)]),
# TaggedCards([ TaggedCards([
# Card("picche", 3)]), Card("picche", 3)]),
# TaggedCards([ TaggedCards([
# Card("cuori", 12)]) Card("cuori", 12)])
# ]) ])
# tavolo = Tavolo([ tavolo2 = Tavolo([
# TaggedCards([ TaggedCards([
# Card("picche", 2), Card("picche", 2),
# Card("fiori", 2), Card("fiori", 2),
# Card("quadri", 2), Card("quadri", 2),
# Card("cuori", 2)]), Card("cuori", 2)]),
# TaggedCards([ TaggedCards([
# Card("cuori", 1), Card("cuori", 1),
# Card("fiori", 1), Card("fiori", 1),
# Card("picche", 1), Card("picche", 1),
# Card("quadri", 1)]), Card("quadri", 1)]),
# # mano # mano
# TaggedCards([ TaggedCards([
# Card("picche", 3)]), Card("picche", 3)]),
# ]) ])
# tavolo = Tavolo([ tavolo3 = Tavolo([
# TaggedCards([ TaggedCards([
# Card("fiori", 7), Card("fiori", 7),
# Card("fiori", 8), Card("fiori", 8),
# Card("fiori", 9)]), Card("fiori", 9)]),
# TaggedCards([ TaggedCards([
# Card("picche", 7), Card("picche", 7),
# Card("picche", 8), Card("picche", 8),
# Card("picche", 9)]), Card("picche", 9)]),
# TaggedCards([ TaggedCards([
# Card("cuori", 7), Card("cuori", 7),
# Card("cuori", 8), Card("cuori", 8),
# Card("cuori", 9), Card("cuori", 9),
# Card("cuori", 10)]), Card("cuori", 10)]),
# # mano # mano
# TaggedCards([ TaggedCards([
# Card("cuori", 11)]), Card("cuori", 11)]),
# TaggedCards([ TaggedCards([
# Card("cuori", 12)]), Card("cuori", 12)]),
# TaggedCards([ TaggedCards([
# Card("quadri", 7)]) Card("quadri", 7)])
# ]) ])
tavolo = Tavolo([ tavolo4 = Tavolo([
TaggedCards([ TaggedCards([
Card("fiori", 7), Card("fiori", 7),
Card("fiori", 8), Card("fiori", 8),
@ -381,6 +368,17 @@ if __name__ == '__main__':
TaggedCards([ TaggedCards([
Card("cuori", 8)]) Card("cuori", 8)])
]) ])
tavolo5 = Tavolo([
# mano
TaggedCards([
Card("cuori", 7)]),
TaggedCards([
Card("cuori", 6)]),
TaggedCards([
Card("cuori", 8)])
])
tavolo = tavolo5
alg(tavolo, tavolo, [], 0, []) alg(tavolo, tavolo, [], 0, [])
print('*************************************') print('****BEST:')
print_1(best, MAX) print_1(best, MAX)

14
hashset.ml Normal file
View file

@ -0,0 +1,14 @@
open Hashtbl;;
(* This is a mess but I need sets for memoization.
* This is my best effort as of now *)
(* let null = ()
*
* let s = Hashtbl.create 1024
*
* let add key =
* Hashtbl.add s key null;
* false
*
* let has key =
* Hashtbl.mem s key *)

72
main.ml
View file

@ -5,8 +5,10 @@ open Cards;;
open Tcards;; open Tcards;;
open Table;; open Table;;
let card_to_string c = String.concat ["{ seed: "; card_type_to_string c.seed; (* let card_to_string c = String.concat ["{ seed: "; card_type_to_string c.seed;
"; value: "; string_of_int c.value; " }"] * "; value: "; string_of_int c.value; " }"] *)
let card_to_string c = String.concat ["{"; card_type_to_string c.seed;":"; string_of_int c.value; "}"]
let print_card chan card = Out_channel.output_string chan (card_to_string card);; let print_card chan card = Out_channel.output_string chan (card_to_string card);;
let tcards_to_string c = "TCards: <":: let tcards_to_string c = "TCards: <"::
@ -17,42 +19,15 @@ let tcards_to_string c = "TCards: <"::
"]"::[] |> String.concat "]"::[] |> String.concat
let print_tcards chan tcards = Out_channel.output_string chan (tcards_to_string tcards);; let print_tcards chan tcards = Out_channel.output_string chan (tcards_to_string tcards);;
let table_to_string c = "Table: <":: let table_to_string c = ""::
(List.map ~f:(fun c -> tcards_to_string c) c.cards |> String.concat):: (List.map ~f:(fun c -> tcards_to_string c) c.cards |> String.concat ~sep:";\n")::
">"::[] |> String.concat ;; ">"::[] |> String.concat ;;
let print_table chan table = Out_channel.output_string chan (table_to_string table);; let print_table chan table = Out_channel.output_string chan (table_to_string table);;
let t = play (make [
Tcards.make [
Cards.make Pikes 2;
Cards.make Tiles 2;
Cards.make Hearts 2;
];
Tcards.make [
Cards.make Hearts 2;
]
]) (* table_cards *)
(Tcards.make [
Cards.make Pikes 2;
Cards.make Tiles 2;
Cards.make Hearts 2;
]) (* in_play *)
(Cards.make Hearts 2) (* to_move *)
(* in make [
* Tcards.make [
* Cards.make Pikes 2;
* Cards.make Tiles 2;
* Cards.make Hearts 2;
* Cards.make Hearts 2;
* ]
* ] ;; *)
in
Printf.printf "%a\n" t
let deck = Cards.init let deck = Cards.init
let card, _ = draw deck;; let card, _ = draw deck;;
Printf.printf "%a\n" print_card card (* Printf.printf "%a\n" print_card card *)
(* Mosse: Aggiunta, spostamento *) (* Mosse: Aggiunta, spostamento *)
(* (*
@ -62,4 +37,37 @@ Printf.printf "%a\n" print_card card
*) *)
(* TESTS TODO: *) (* TESTS TODO: *)
let printer table =
Printf.printf "********\n%a\n********\n" print_table table;;
(* let rec alg table original_table n (scores:int list) best max_score (dbg: table -> unit) = *)
open Hashtbl;;
let table = Table.make [
Tcards.make [
Cards.make Hearts 7;
Cards.make Hearts 8;
Cards.make Hearts 9;
];
Tcards.make [
Cards.make Pikes 7;
Cards.make Pikes 8;
Cards.make Pikes 9;
];
Tcards.make [
Cards.make Hearts 7;
Cards.make Hearts 8;
Cards.make Hearts 9;
Cards.make Hearts 10;
];
Tcards.make [
Cards.make Hearts 6;
];
Tcards.make [
Cards.make Hearts 8;
]
] in
let new_tables = Table.alg table 0 [] in
(* List.iter ~f:(fun (t,_,_) -> printer t) new_table *)
Table.prova table [] [] (-1000) printer new_tables []

View file

@ -10,6 +10,9 @@ type table = { cards: tcards list}
let make tcards = let make tcards =
{ cards=tcards } { cards=tcards }
let empty =
{ cards = [] }
let valids table = let valids table =
List.filter (fun ts -> ts.tag == Valid) table.cards;; List.filter (fun ts -> ts.tag == Valid) table.cards;;
@ -27,17 +30,22 @@ let size table =
List.map (fun tl -> Tcards.length tl) table.cards |> List.map (fun tl -> Tcards.length tl) table.cards |>
List.fold_left sum 0 ;; List.fold_left sum 0 ;;
let flatten table = let flatten table : card list=
List.map (fun (ts:tcards) -> ts.cards) table.cards |> List.map (fun (ts:tcards) -> ts.cards) table.cards |>
List.concat ;; List.concat ;;
let neighbors tcs table = let contains tc table =
List.mem tc table.cards
let neighbors tcs table : card list=
let all = flatten table in
match tcs.strategy with match tcs.strategy with
| Tris -> List.filter (fun (x:tcards) -> tcs.cards@x.cards |> Cards.is_tris) table.cards | Tris -> List.filter (fun x -> tcs.cards@[x] |> Cards.is_tris) all
| Straight -> List.filter (fun (x:tcards) -> tcs.cards@x.cards |> Cards.is_straight) table.cards | Straight -> List.filter (fun x -> tcs.cards@[x] |> Cards.is_straight) all
| Single -> List.filter (fun (x:tcards) -> | Single -> all |>
tcs.cards@x.cards |> Cards.is_straight || tcs.cards@x.cards |> Cards.is_tris) List.filter (fun x -> let cs = tcs.cards@[x] in
table.cards Cards.is_straight cs || Cards.is_tris cs)
let constraints start eend = let constraints start eend =
let hand = List.filter (fun ts -> ts.strategy == Single) start.cards in let hand = List.filter (fun ts -> ts.strategy == Single) start.cards in
@ -59,11 +67,60 @@ let play table in_play to_move =
| hd::tl when hd = in_play -> _play tl in_play to_move ((Tcards.make (to_move::in_play.cards))::accum) | hd::tl when hd = in_play -> _play tl in_play to_move ((Tcards.make (to_move::in_play.cards))::accum)
| [] -> accum (* generate a new table *) | [] -> accum (* generate a new table *)
| hd::tl -> if hd |> Tcards.contains to_move then | hd::tl -> if hd |> Tcards.contains to_move then
let filtered = List.filter (fun x -> x != to_move) hd.cards in match (Tcards.remove to_move hd) with
_play tl in_play to_move ((Tcards.make filtered)::accum) | None -> _play tl in_play to_move accum
| Some x -> _play tl in_play to_move (x::accum)
else else
_play tl in_play to_move (hd::accum) _play tl in_play to_move (hd::accum)
in in
assert (table |> contains in_play) ;
_play table.cards in_play to_move [] |> make _play table.cards in_play to_move [] |> make
;; ;;
let update best max_score original newt score =
if score > max_score && (constraints original newt) then
score, newt
else
max_score, best
let is_best_outcome table =
(invalids table |> List.length) == 0
(* let rec alg table original_table n (scores:int list) best max_score (dbg: table -> unit) =
* dbg table ;
* let ascore = score table in
* (\* if Hashset.has (hash table) then () *\)
* (\* else ( *\)
* (\* Hashset.add (hash table) ; *\)
* let mmax, bbest = update best max_score original_table table ascore in
* if is_best_outcome table || n > 14 || doesnt_improve (scores@[ascore]) then
* ()
* else
* table.cards |>
* List.map (fun tcs -> neighbors tcs table |> List.map (fun v -> (tcs,v))) |> (\* lista di carta:vicini *\)
* List.concat |> (\* flatten *\)
* List.map (fun (card, neigh) -> play table card neigh) |> (\* list of new_tables *\)
* List.iter (fun new_table -> alg new_table original_table (n+1) (scores@[ascore]) bbest mmax dbg)
* (\* ) *\) *)
let alg table n (scores:int list) : (table * int * int list) list =
table.cards |>
List.map (fun tcs -> neighbors tcs table |> List.map (fun v -> (tcs,v))) |> (* lista di carta:vicini *)
List.concat |> (* flatten *)
List.map (fun (card, neigh) -> (play table card neigh), (n+1), (scores@[score table]) )
let condizioni table n scores set =
if List.mem (hash table) set || doesnt_improve scores ||
is_best_outcome table || n > 14 then
true
else false
let rec prova original_table set best max_score (dbg: table -> unit) (accum: (table*int*int list) list)
(sols: (table*int*int list) list) =
match accum with
| [] -> sols
| (table, n, scores)::tl -> dbg table ;
if condizioni table n scores set then
prova original_table ((hash table)::set) best max_score dbg tl ([table, n, scores]@sols)
else
prova original_table ((hash table)::set) best max_score dbg ((alg table n scores)@tl) sols

View file

@ -33,7 +33,7 @@ let make cards =
let contains needle haystack = List.mem needle haystack.cards let contains needle haystack = List.mem needle haystack.cards
let (=) a b = let (=) a b =
if List.length a.cards != List.length b.cards || a.tag != b.tag || a.strategy != b.strategy then if List.length a.cards <> List.length b.cards || a.tag != b.tag || a.strategy != b.strategy then
false false
else else
a.cards = b.cards a.cards = b.cards
@ -58,3 +58,14 @@ let hash ts =
ts.cards |> ts.cards |>
List.sort (fun a b -> if a.seed == b.seed then Cards.value_cmp a b else Cards.seed_cmp a b) |> List.sort (fun a b -> if a.seed == b.seed then Cards.value_cmp a b else Cards.seed_cmp a b) |>
Hashtbl.hash;; Hashtbl.hash;;
let remove card tcards =
assert (List.mem card tcards.cards);
match (List.filter (fun x -> x <> card) tcards.cards) with
| [] -> None
| (hd::tl) as lst -> Some (make lst) ;;
let r = remove (Cards.make Hearts 7) (make [Cards.make Hearts 7; Cards.make Clovers 7; Cards.make Pikes 7;]) in
match r with
| None -> assert false
| Some x -> if x <> (make [Cards.make Clovers 7; Cards.make Pikes 7]) then assert false