sort_stable und pointer
-
Ne, doch lieber alles direkt in ein Array stopfen:
n = 10000000 pos = 1000 Benchmark.bm do |x| x.report { contents = open('d:\handranks.dat', "rb") {|io| io.read }; n.times { contents[pos..(pos+3)].unpack("l").first } } x.report { contents = open('d:\handranks.dat', "rb") {|io| io.read }; values = contents.unpack("l*"); n.times { values[pos] } } end Output: user system total real 13.572000 0.125000 13.697000 ( 13.724785) 2.512000 0.202000 2.714000 ( 2.890166)Das ergäbe dann sowas wie
class HandLookup def initialize @contents = open('d:\handranks.dat', "rb") {|io| io.read }; @contents = @contents[53..-1].unpack("l*") end def eval_hand_7(ary_cards) @contents[ary_cards.inject(:+)] end endDas macht dann 5 Sekunden für 100.000 Durchläufe, wenn man die Initialisierung weglässt

Wie funktioniert das eigentlich mit @ary_nbr_hand_types? So wie ich das sehe, kann handvalue deutlich größer sein als 2^12, also wird oft auf einen viel zu großen Index zugegriffen.
-
Nein die eval_hand_7 funktion ist nicht falsch. So funktionieren direkte, azyklische Graphen. Kann man aber nicht wissen.
http://en.wikipedia.org/wiki/Directed_acyclic_graphEs wird sich also quasi ein Weg durch den Datensatz gesucht. An jeder Station steht eine neue Addresse wo es hingeht daher brauch man die davor nicht mehr bis am Ende der Handrank steht. Wenn du mehr dazu wissen willst guck dir die beiden Links an die ich vorhin gepostet hab.
Und nope handvalue << 12 kann nicht beliebig groß sein
Das format sieht bit-weise betrachtet so aus:
hhhhrrrrrrrrrrrr
hhhh = 1 high card -> 9 straight flush
r..r = rank within the categorie 1 to max of 2861So ich hab den Datensatz jetzt auch in ein Array gepackt und krieg damit so 50000 Hände pro Sekunde hin. Das sind bei 9 Spielern aber leider immer noch nur ca. 5000 Simulationen die Sekunde. Wird wohl doch auf C/C++ rauslaufen.
Mein Code sieht übrigens jetzt so aus. Vorhin war es am fehlenden binmode fuer IO::read und der automatischen crlf Konvertierung gescheitert. Darum hatte ich schwachsinnige Werte die wiederum auf ne Stelle im String gezeigt haben die viel zu groß war. Und daher der bignum error.
class HandLookup def initialize file = File.new(Dir.pwd + "/HandRanks.dat", "rb") file.binmode() rank_table_string = file.read() file.close() @rank_table = rank_table_string.unpack("l*") end def eval_hand_7(ary_cards) p = 53 ary_cards.each do |pc| p = pc + p p = @rank_table[p] end return p end endDie HandRanks.dat kann man jetzt übrigens downloaden. http://www.megaupload.com/?d=ID3ATVST
-
Hört sich ja alles echt interessant an, haltet uns mal auf dem laufenden

-
codecow schrieb:
Nein die eval_hand_7 funktion ist nicht falsch.
Sry, hab mich verlesen.
Wenn das so ist, dann geb ichs mit Ruby auf, das in angemessener Zeit zu schaffen
Vielleicht mach ich ja noch aus Spaß ne C++-Version...
-
So nachdem mir heute Nacht einige Lichter aufgegangen sind bezüglich C++ hab ich es jetzt geschafft. Herzlichen Dank dafür an alle insbesondere der Tipp (und der Beispielcode) mit dem struct war zielführend. Und nebenbei noch ein bisschen was über Ruby gelernt. Ich hab jetzt 1 Millionen durchläufe für 3 Spieler in gefühlt einer Sekunde. Das sollte erstmal ausreichen. Bei Bedarf werd ich es noch mit OpenCL erweitern.
Rein interessehalber hät ich allerdings noch zwei Fragen:
1. Was bedeutet dieser gcc output(g++ Evaluator.cpp -o eval.exe):Info: resolving std::nothrow by linking to __imp___ZSt7nothrow (auto-importc:/mingw/bin/../lib/gcc/mingw32/4.5.0/../../../../mingw32/bin/ld.exe: warning: auto-importing has been activated without --enable-auto-import specified on the command line.
This should work unless it involves constant data structures referencing symbols from auto-imported DLLs.)2. Warum funktioniert HandLookup als C Version hier nicht:
require 'inline' class HandLookup def initialize file = File.new(Dir.pwd + "/HandRanks.dat", "rb") file.binmode() rank_table_string = file.read() file.close() @rank_table = rank_table_string.unpack("l*") end def eval_hand_7(ary_cards) p = 53 ary_cards.each do |pc| p = pc + p p = @rank_table[p] end return p end end class HandLookupC inline(:C) do |code| code.include '<stdio.h>' code.c ' int HR[32487834]; int InitTheEvaluator() { memset(HR, 0, sizeof(HR)); FILE * fin = fopen("HandRanks.dat", "rb"); size_t bytesread = fread(HR, sizeof(HR), 1, fin); fclose(fin); } int GetHandValue(int* pCards) { int p = HR[53 + *pCards++]; p = HR[p + *pCards++]; p = HR[p + *pCards++]; p = HR[p + *pCards++]; p = HR[p + *pCards++]; p = HR[p + *pCards++]; return HR[p + *pCards++]; }' end endHier noch der Code wenns jemanden interessiert:
#include <stdlib.h> #include <windows.h> #include <iostream> #include <algorithm> #include <stdio.h> #include <time.h> using namespace std; struct Tuple { int first; int second; }; int HR[32487834]; int randCards[52]; int hand_categories[] = {0, 1277, 4137, 4995, 5853, 5863, 7140, 7296, 7452, 7462}; int InitTheEvaluator() { memset(HR, 0, sizeof(HR)); FILE * fin = fopen("HandRanks.dat", "rb"); size_t bytesread = fread(HR, sizeof(HR), 1, fin); fclose(fin); } int GetHandValue(int* pCards) { int p = HR[53 + *pCards++]; p = HR[p + *pCards++]; p = HR[p + *pCards++]; p = HR[p + *pCards++]; p = HR[p + *pCards++]; p = HR[p + *pCards++]; return HR[p + *pCards++]; } int PickRandomCard() { int random_card = 0; while (random_card == 0) { char rand_nbr = rand() % 52; random_card = randCards[rand_nbr]; randCards[rand_nbr] = 0; } return random_card; } bool pred(const Tuple& lhs, const Tuple& rhs) { return lhs.second > rhs.second; } void MonteCarlo(int rounds, char players, int player_cards[][2], int* com_cards, int* odds) { srand(time(NULL)); int i; int ii; int loop; int com_cards_t[5]; int player_cards_t[players][2]; Tuple ranks[players]; for (loop = 0; loop < rounds; loop++) { for (i = 0; i < 52; i++) { randCards[i] = i+1; } for (i = 0; i < 5; i++) { if (com_cards[i] != 0) { com_cards_t[i] = com_cards[i]; randCards[com_cards[i]-1] = 0; } } for (i = 0; i < players; i++) { for (ii = 0; ii < 2; ii++) { if (player_cards[i][ii] != 0) { player_cards_t[i][ii] = player_cards[i][ii]; randCards[player_cards[i][ii]-1] = 0; } } } for (i = 0; i < 5; i++) { if (com_cards[i] == 0) { com_cards_t[i] = PickRandomCard(); } } for (i = 0; i < players; i++) { for (ii = 0; ii < 2; ii++) { if (player_cards[i][ii] == 0) { player_cards_t[i][ii] = PickRandomCard(); } } } for (i = 0; i < players; i++) { int eval_array[] = { player_cards_t[i][0], player_cards_t[i][1], com_cards_t[0], com_cards_t[1], com_cards_t[2], com_cards_t[3], com_cards_t[4] }; int value_t = GetHandValue(eval_array); ranks[i].first = i; ranks[i].second = hand_categories[(value_t >> 12)-1] + (value_t & 0x00000FFF); } stable_sort(ranks, ranks+players, pred); odds[ranks[0].first] = odds[ranks[0].first] + 1; for (i = 1; i < players; i++) { if (ranks[i].second == ranks[i-1].second) { odds[ranks[i].first] = odds[ranks[i].first] + 1; } } } } int main() { InitTheEvaluator(); int player_cards[][2] = {{2, 35}, {22, 13}, {26, 7}}; int com_cards[] = {1, 5, 24, 0, 0}; int odds[] = {0, 0, 0}; MonteCarlo(1000000, 3, player_cards, com_cards, odds); printf("%d %d %d", odds[0], odds[1], odds[2]); }