The Daily WTF: Curious Perversions in Information Technology
Welcome to TDWTF Forums Sign in | Join | Help
in Search

Speed Challenge 23: Fun N' Games

Last post 06-13-2007 6:38 AM by Faxmachinen. 19 replies.
Page 1 of 1 (20 items)
Sort Posts: Previous Next
  • 06-01-2007 12:25 PM

    Speed Challenge 23: Fun N' Games

    This challenge is quite open: Invent a simple board game and implement it in ASCII graphics. And by invent I don't mean tic-tac-toe.
    rpar PROTON all
  • 06-02-2007 10:09 AM In reply to

    Re: Speed Challenge 23: Fun N' Games

    Tic-Turn-Tumble: just like TicTacToe except after each turn you rotate the board 90 degrees and all the X's and O's slide to the bottom (making the first move on the middle square MEANINGLESS!)

     

    #include <stdio.h>

    void printboard( void );
    void getmove( int );
    void turnboard( int*, int );
    int checkwin( int* );

    int board[9] = { 0,0,0,0,0,0,0,0,0 };

    #define TOCHR(xx)  (xx==0?'.':(xx==1)?'X':'O')

    int main() {
        int moves = 9;
        while(moves > 0) {
            printboard();
            getmove(moves%2);
            turnboard( board, 1 );
            if( checkwin(board) )
                break;
            moves--;
        }
        return(0);
    }

    void printboard( void ) {
        int i,j;
        for(i=0;i<3; i++ )
            for( j=0; j<3; j++ )
                printf(" %c%s", TOCHR(board[j*3+i]),j==2?"\n":" ");
        printf("\n");
    }

    void getmove( int player ) {
        int i,j;
        int x,y;
        char c;
        int b[9];
        if( player == 0 ) {
            j = 0;
            for(i=0;i<9;i++) {
                for(x=0;x<9;x++) b[x] = board[x];
                if(b[i]) continue;
                b[i] = player+1;
                turnboard(b,0);
                if( checkwin(b) == 1 ) {
                    board[i] = player+1;
                    return;
                }
            }
            for(i=0;i<9;i++) {
                for(x=0;x<9;x++) b[x] = board[x];
                if(b[i]) continue;
                b[i] = player+1;
                turnboard(b,0);
                if( checkwin(b) != 2 ) {
                    board[i] = player+1;
                    return;
                }
            }
            for(i=0;i<9;i++) {
                if(b[i]) continue;
                board[i] = player+1;
                return;
            }
            return;
        }

        for(i=0;i<3; i++ ) {
            for( j=0; j<3; j++ ) {
                c = (board[j*3+i] == 0) ? ('1'+j+3*i) : (board[j*3+i] == 1 ? 'X' : 'O' );
                printf(" %c%s", c,j==2?"\n":" ");
            }
        }
        printf("\n");

        do {
            printf("\rEnter square to move...\b");
            i = getc(stdin);
            i -= '0';
            if( i < 1 || i > 9 ) continue;
            i--;
            x = i%3;
            y = i/3;
            if( board[x*3+y] != 0 ) continue;
            break;
        } while(1);
        board[x*3+y] = player+1;
    }

    void turnboard( int *b, int show ) {
        int ngrid[9];
        int i,j,k;
        for(i=0;i<9;i++)
            ngrid[i] = b[i];

        if( show ){ printboard();
        printf("    %c\n", TOCHR(b[6]));
        printf("  %c   %c\n", TOCHR(b[3]),TOCHR(b[7]));
        printf("%c   %c   %c\n",TOCHR(b[0]),TOCHR(b[4]),TOCHR(b[8]));
        printf("  %c   %c\n",TOCHR(b[1]),TOCHR(b[5]));
        printf("    %c\n\n",TOCHR(b[2]));
        }

        b[0] = ngrid[6];
        b[3] = ngrid[7];
        b[6] = ngrid[8];
        b[7] = ngrid[5];
        b[8] = ngrid[2];
        b[5] = ngrid[1];
        b[2] = ngrid[0];
        b[1] = ngrid[3];

        if(show) printboard();

        for(k=0; k<3; k++ ) {
            for(i=1 ; i < 3; i++ ) {
                for(j=0;j<3;j++) {
                    if( b[j*3+i] == 0 ) {
                        b[j*3+i] = b[j*3+i-1];
                        b[j*3+i-1] = 0;
                    }
                }
            }
        }
    }

    int checkwin( int *b ) {
        int i;
        for(i=0;i<3;i++) {
            if( b[i*3] == b[i*3+1] && b[i*3] == b[i*3+2] && b[i*3] ) return(b[i*3]);
            if( b[i] == b[3+i] && b[i] == b[6+i] && b[i] ) return(b[i]);
        }
        if( b[0] == b[4] && b[8] == b[0] && b[0] ) return(b[0]);
        if( b[2] == b[4] && b[4] == b[6] && b[4] ) return(b[2]);
        return(0);
    }

  • 06-03-2007 11:34 AM In reply to

    Re: Speed Challenge 23: Fun N' Games

    Tic!, a simplified variant of Tic-Tac-Toe that consists of just one square. Unlike the ordinary Tic-Tac-Toe, it can be played by an arbitrary number of people, which makes it great for parties. (Also, a secret tip from a pro-gamer, because it's you: The opening move is really important. Make sure you get to be the first player, it will greatly enhance your chances. But you didn't hear that from me...)

    #include <stdio.h>

    int main(){
       cout << "Welcome to Tic!\n\n[ ]\n\nPlayer 1, your turn. Press RETURN to make your move.";
       cin;
       cout << "[X]\n\nPlayer 1 wins!";
    }

  • 06-03-2007 7:58 PM In reply to

    Re: Speed Challenge 23: Fun N' Games

    Okay, time's up. Here's the verdict:
     
    Even if neither entry was a plain tic-tac-toe clone, they did not break with the biggest gaming cliché of the last two centuries either; the grid. Hardly surprising, considering even the most innovative games such as chess and Darwinia utilizes them.
    As for gameplay, neither entry had a lot of variation - omega0's only had a handfull of different states, while PSWorx's only had two. Though omega0's program was behind on declaring the victor, the more advanced graphics made up for it. And while PSWorx's entry had a higher fun-per-line-of-code ratio, omega0's code was a lot more extensible. Indeed, Tic-Turn-Tumble became twice as fun just by making the O's float instead of fall, and then only one step at a time.
     
    As such, the winner is omega0. Congratulations.
     
    rpar PROTON all
  • 06-03-2007 8:25 PM In reply to

    Re: Speed Challenge 24: Fun N' Games #2

    Lets move from board games to card games: I'd like a program to determine the frequency of drawing a specific five card hand.  The contents of the hand is specified in five arguments containing one or more of the following characters:  * - any card, r - same rank as the previous card, s - same suit as the previous card, Rn of the rank n (n=A,2,3,4,5,6,7,8,9,T,J,Q,K), n - one higher rank than the previous card.

    So the standard poker hands are:
    * r * * * (pair)
    * r * r * (two pair) 
    * r r * * (three of a kind)
    * n n n n (straight)
    * s s s s (flush) 
    * r r * r (full house)
    * r r r * (four of a kind)
    * sn sn sn sn (straight flush)
    RT sn sn sn sn (royal flush)

    The program does not need to deal with overlaps, if run with the arguments for a pair, A,A,A,2,3 would be a valid hand configuration.  I don't care if you count all the permutations or not (i.e. does 1s,2s,3s,4s,5s count as 1 way to make a straight flush or 5! ways) provided it's consistent.

  • 06-04-2007 9:02 AM In reply to

    Re: Speed Challenge 24: Fun N' Games #2

    I'm going to be extremely lazy this morning and use PseudoCode as my language of choice. (plus, what good programmer does more work than is required for problems that have already been solved?):

     Program To Find Probability of Poker Hands:

    1. Open a connection to a search engine website.

    2. Search for "Poker Hand Probability"

    3. Print out the results.


    }:-) 

    (P.S.: I'm going for something akin to the IOCCC "Best Abuse of the Rules" category here .... ) 

  • 06-04-2007 3:21 PM In reply to

    Re: Speed Challenge 24: Fun N' Games #2

    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>

    // the brute force approach, using arrays of 5 cards
    // it's a bit slow but gets there in the end

    // for cards:
    // lowest 4 bits is the value
    // highest 4 bits is the suit
    // 1 is Ace, 13 is King
    // Suits have no name

    // for rules:
    // either a specific card value 1 to 13
    // or one of the following
    const int ruleAny = 32;
    const int ruleSameRank = 32 + 1;
    const int ruleSameSuit = 32 + 2;
    const int ruleSameSuitAndRank = 32 + 3;
    const int ruleNextRank = 32 + 4;

    // order is the ordered section of hand to teset against rules, bucket is
    // the unused cards.

    // it started out as more of a brute force acronym finder which is why it's a
    // bit knobbly.

    bool RecursiveTest (char* order, int orderLen, char* bucket, int* rules)
    {
        if (order[0] != 0)
        {
            // test the order so far
            
            // the first rule can only be Rsomething
            if (!(rules[0] & 32))
                if ((order[0] & 0x0f) != rules[0])
                    return false;
                   
            char rank, rankPrev;
            int i;
           
            // no need to loop through previous cards as they've already been tested
            i = orderLen - 1;
            if (i > 0)
            {   
                rank = order[i] & 0x0f;
                rankPrev = order[i-1] & 0x0f;
               
                switch(rules[i])
                {
                    case ruleSameRank:
                        if (rank != rankPrev)
                            return false;
                        break;
                       
                    case ruleSameSuit:
                        if ((order[i] & 0xf0) != (order[i-1] & 0xf0))
                            return false;
                        break;
                       
                    case ruleSameSuitAndRank:
                        if (rank != rankPrev)
                            return false;
                        if ((order[i] & 0xf0) != (order[i-1] & 0xf0))
                            return false;
                        break;
                       
                    case ruleNextRank:
                        if (rank != rankPrev + 1)
                        {
                            if (!(rank == 1 && rankPrev == 13))
                                return false;
                        }
                        if (i > 1)
                        {
                            // can't wrap King Ace 2
                            if (rank == 2 && rules[i-1] == ruleNextRank)
                                return false;
                        }
                        break;
                       
                    default:
                        break;
                }
            }
        }
       
        if (bucket[0] != 0)
        {   
            // if we've some more values in bucket, test again, returning true if any of these matched
            char testBucket[6];
            char testOrder[6];
            char *s, *d;
            for (int i=0; i<5 && bucket[i] != 0; ++i)
            {
                // copy the current order, adding the new card to the end of it
                d = testOrder;
                s = order;
               
                switch(orderLen)
                {
                case 5: *(d++) = *(s++);
                case 4: *(d++) = *(s++);
                case 3: *(d++) = *(s++);
                case 2: *(d++) = *(s++);
                case 1: *(d++) = *(s++);
                }
               
                *(d++) = bucket[i];
                *d = 0;
               
                // copy the current bucket, removing the new card
    #if 0
                d = testBucket;
                s = bucket;
                while(*s != 0) { if (*s != bucket[i]) *(d++) = *(s++); else s++; };
                *d = 0;
    #else
                switch(i)
                {
                case 0:
                    testBucket[0] = bucket[1];
                    testBucket[1] = bucket[2];
                    testBucket[2] = bucket[3];
                    testBucket[3] = bucket[4];
                    testBucket[4] = 0;
                    break;
                case 1:
                    testBucket[0] = bucket[0];
                    testBucket[1] = bucket[2];
                    testBucket[2] = bucket[3];
                    testBucket[3] = bucket[4];
                    testBucket[4] = 0;
                    break;
                case 2:
                    testBucket[0] = bucket[0];
                    testBucket[1] = bucket[1];
                    testBucket[2] = bucket[3];
                    testBucket[3] = bucket[4];
                    testBucket[4] = 0;
                    break;
                case 3:
                    testBucket[0] = bucket[0];
                    testBucket[1] = bucket[1];
                    testBucket[2] = bucket[2];
                    testBucket[3] = bucket[4];
                    testBucket[4] = 0;
                    break;
                case 4:
                    testBucket[0] = bucket[0];
                    testBucket[1] = bucket[1];
                    testBucket[2] = bucket[2];
                    testBucket[3] = bucket[3];
                    testBucket[4] = 0;
                    break;
                }
    #endif

                if ( RecursiveTest (testOrder, orderLen + 1, testBucket, rules))
                    return true;
            }
           
            return false;
        }
       
        // we've passed the test with all 5 in order
        return true;
    }

    int BruteForceAnalysis(int* rules)
    {
        const int cardsInDeck = 52;
       
        int count = 0;
       
        // build a quick thing to index cards sequentially
        char cards[cardsInDeck];
        int suit, rank, i = 0;
        for (suit = 1; suit <= 4; ++suit)
        {
            for (rank = 1; rank <= 13; ++rank, ++i)
            {
                cards[i] = (suit << 4) | rank;
            }
        }
       
        // test every single hand
        char order[6] = { 0, 0, 0, 0, 0, 0 };
        char bucket[6] = { 0, 0, 0, 0, 0, 0 };
        int card1, card2, card3, card4, card5;
        for (card1 = 0; card1 < cardsInDeck; ++card1)
        {   
            if (!(card1 & 1)) printf("\nhmm");
            bucket[4] = cards[card1];
           
            for (card2 = 0; card2 < cardsInDeck; ++card2)
            {
                if (!(card2 & 1)) printf(".");
                if (card2 == card1)
                    continue;

                bucket[3] = cards[card2];
                   
                for (card3 = 0; card3 < cardsInDeck; ++card3)
                {
                    if (card1 == card3 || card2 == card3)
                        continue;
                       
                    bucket[2] = cards[card3];
                       
                    for (card4 = 0; card4 < cardsInDeck; ++card4)
                    {
                        if (card1 == card4 || card2 == card4 || card3 == card4)
                            continue;
                           
                        bucket[1] = cards[card4];
                           
                        for (card5 = 0; card5 < cardsInDeck; ++card5)
                        {
                            if (card1 == card5 || card2 == card5 || card3 == card5 || card4 == card5)
                                continue;
                               
                            bucket[0] = cards[card5];
                           
                            order[0] = 0;
                           
                            //printf("testing %x %x %x %x %x\n", bucket[0], bucket[1], bucket[2], bucket[3], bucket[4]);
                            if (RecursiveTest(order, 0, bucket, rules))
                            {
                                //printf("pass\n");
                                count++;
                            }
                        }
                    }
                }
            }
        }
       
        printf("\n");
       
        return count;
    }

    void PrintProbability(const char* name, int* rules)
    {
        const int totalHands = 52 * 51 * 50 * 49 * 48;
       
        printf("calculating probability of %s\n", name);
       
        int prob = BruteForceAnalysis(rules);
        double fprob = (double)prob / (double)totalHands;
       
        printf("probability of %s is %i / %i = %g\n", name, prob, totalHands, fprob);
       
        // print it to file too
        FILE *logFile = fopen("log.txt", "a");
        if (logFile != NULL)
        {
            fprintf(logFile, "probability of %s is %i / %i = %g\n", name, prob, totalHands, fprob);
            fclose(logFile);
        }
        else printf("WARNING: could not write probability to log file\n");
    }

    void PrintTimeTaken(double timeSec)
    {
        printf("calculation took %g seconds\n", timeSec);
       
        FILE *logFile = fopen("log.txt", "a");
        if (logFile != NULL)
        {
            fprintf(logFile, "calculation took %g seconds\n", timeSec);
            fclose(logFile);
        }
        else printf("WARNING: could not write time to log file\n");
    }

    void ClearLogFile(void)
    {
        FILE *f = fopen("log.txt", "w");
        if (f != NULL)
        {
            fclose(f);
        }
        else
        {
            printf("WARNING: could not clear the log file\n");
        }
    }

    int main(int argc, char *argv[])
    {
        ClearLogFile();
       
        int rulesPair[] = { ruleAny, ruleSameRank, ruleAny, ruleAny, ruleAny };
        int rulesTwoPair[] = { ruleAny, ruleSameRank, ruleAny, ruleSameRank, ruleAny };
        int rulesThree[] = { ruleAny, ruleSameRank, ruleSameRank, ruleAny, ruleAny };
        int rulesStraight[] = { ruleAny, ruleNextRank, ruleNextRank, ruleNextRank, ruleNextRank };
        int rulesFlush[] = { ruleAny, ruleSameSuit, ruleSameSuit, ruleSameSuit, ruleSameSuit };
        int rulesHouse[] = { ruleAny, ruleSameRank, ruleSameRank, ruleAny, ruleSameRank };
        int rulesFour[] = { ruleAny, ruleSameRank, ruleSameRank, ruleSameRank, ruleAny };
        int rulesStraightFlush[] = { ruleAny, ruleSameSuitAndRank, ruleSameSuitAndRank, ruleSameSuitAndRank, ruleSameSuitAndRank };
        int rulesRoyal[] = { 10, ruleSameSuitAndRank, ruleSameSuitAndRank, ruleSameSuitAndRank, ruleSameSuitAndRank };
       
        clock_t clockStart = clock();
       
        PrintProbability("a pair", rulesPair);
        PrintProbability("two pair", rulesTwoPair);
        PrintProbability("three of a kind", rulesThree);
        PrintProbability("a straight", rulesStraight);
        PrintProbability("a flush", rulesFlush);
        PrintProbability("a full house", rulesHouse);
        PrintProbability("four of a kind", rulesFour);
        PrintProbability("a straight flush", rulesStraightFlush);
        PrintProbability("a royal flush", rulesRoyal);
       
        printf("\nTada!\n");
       
        clock_t clockTaken = clock() - clockStart;

        double timeTaken = (double)clockTaken / (double)CLOCKS_PER_SEC;
        PrintTimeTaken(timeTaken);
       
        system("PAUSE");
        return EXIT_SUCCESS;
    }

    RRRRAAAAAAAAAGH HULK CALCULATE PROBABILITIES OF POKER HANDS!!!!!
     

  • 06-04-2007 3:55 PM In reply to

    Re: Speed Challenge 24: Fun N' Games #2

    Here's quite an enterprisey attempt. It lets you enter any amount of arguments and assumes an infinite amount of decks:
     
    # handfreq.pl
    
    $magicnumber = 10000;
    
    %cardranks = ('A', 14, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 'T', 10, 'J', 11, 'Q', 12, K, 13);
    @allsuits = qw/S H C D/;
    
    sub max { ($_[0] > $_[1]) ? $_[0] : $_[1]; }
    
    print "Please enter the hand arguments.\n";
    @handargs = split / /, <STDIN>;
    
    $i = 0;
    @rexplist = (0) * ($#handargs + 1);
    @ranks = ();
    # 1 = store suite, 2 = store rank
    # 4 = fetch suite, 8 = fetch rank, 16 = fetch rank+1
    # 32 = use rank X
    for $arg (@handargs)
    {
    	if ($arg =~ /R(.)/) { $rexplist[$i+1] = 32; push @ranks, ($1); }
    	if ($arg =~ /s/) { $rexplist[$i] |= 1; $rexplist[$i+1] |= 4; }
    	if ($arg =~ /r/) { $rexplist[$i] |= 2; $rexplist[$i+1] |= 8; }
    	elsif ($arg =~ /n/) { $rexplist[$i] |= 2; $rexplist[$i+1] |= 16; }
    	$i++;
    }
    @ranks = reverse @ranks;
    $searchrex = "";
    $ri, $si = 0, 0;
    for $rexp (@rexplist[1..$#rexplist])
    {
    	if ($rexp & 4) { $rexpart =  "\\$si"; }
    	elsif ($rexp & 1) { $rexpart =  '([^R])'; $si = 1 + max $ri, $si }
    	else { $rexpart = '[^R]'; }
    
    	$searchrex .= $rexpart;
    
    	if ($rexp & 8) { $rexpart =  '\\' . $ri; }
    	elsif ($rexp & 16) { $rexpart =  '\\' . $ri . 'R'; }
    	elsif ($rexp & 32) { $rexpart = 'R{' . $cardranks{pop @ranks} . '}'; }
    	else { $rexpart = 'R+'; }
    
    	if ($rexp & 2 and not $rexp & 8 ) { $searchrex .=  '(' . $rexpart . ')'; $ri = 1 + max $ri, $si }
    	else { $searchrex .= $rexpart; }
    }
    
    #print $searchrex, "\n";  # DEBUG
    
    if ($searchrex eq "") { die "The frequency is 1.0.\n"; }
    
    $randcardpool = "";
    $i = 0;
    while ($i < $magicnumber)
    {
    	$randcardpool .= $allsuits[int rand(4)] . 'R';
    	$randrank = int rand(14);
    	while ($randrank > 0) { $randcardpool .= 'R'; $randrank--; }
    	$i++;
    }
    
    study $randcardpool;
    
    @matchinghands = $randcardpool =~ m/$searchrex/g;
    print "The frequency is approximately ", $#matchinghands / $magicnumber;
    
    rpar PROTON all
  • 06-04-2007 6:18 PM In reply to

    Re: Speed Challenge 24: Fun N' Games #2

    Finally got around to testing and discovered the bug, but it's too late to edit the old post:

    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>

    // the brute force approach, using arrays of 5 cards
    // it's a bit slow but gets there in the end

    // for cards:
    // lowest 4 bits is the value
    // highest 4 bits is the suit
    // 1 is Ace, 13 is King
    // Suits have no name

    // for rules:
    // either a specific card value 1 to 13
    // or one of the following
    const int ruleAny = 32;
    const int ruleSameSuit = 32 + 1;
    const int ruleNextRank = 32 + 2;
    const int ruleSameSuitNextRank = 32 + 3;
    const int ruleSameRank = 32 + 4;

    // order is the ordered section of hand to teset against rules, bucket is
    // the unused cards.

    // it started out as more of a brute force acronym finder which is why it's a
    // bit knobbly.

    bool RecursiveTest (char* order, int orderLen, char* bucket, int* rules)
    {
        if (order[0] != 0)
        {
            // test the order so far
           
            // the first rule can only be Rsomething
            if (!(rules[0] & 32))
                if ((order[0] & 0x0f) != rules[0])
                    return false;
                   
            char rank, rankPrev;
            int i;
           
            // no need to loop through previous cards as they've already been tested
            i = orderLen - 1;
            if (i > 0)
            {   
                rank = order[i] & 0x0f;
                rankPrev = order[i-1] & 0x0f;
               
                switch(rules[i])
                {
                    case ruleSameRank:
                        if (rank != rankPrev)
                            return false;
                        break;
                       
                    case ruleSameSuit:
                        if ((order[i] & 0xf0) != (order[i-1] & 0xf0))
                            return false;
                        break;
                       
                    case ruleSameSuitNextRank:
                        if ((order[i] & 0xf0) != (order[i-1] & 0xf0))
                            return false;
                           
                    case ruleNextRank:
                        if (rank != rankPrev + 1)
                        {
                            if (!(rank == 1 && rankPrev == 13))
                                return false;
                        }
                        if (i > 1)
                        {
                            // can't wrap King Ace 2
                            if (rank == 2 && rules[i-1] == ruleNextRank)
                                return false;
                        }
                        break;
                       
                    default:
                        break;
                }
            }
        }
       
        if (bucket[0] != 0)
        {   
            // if we've some more values in bucket, test again, returning true if any of these matched
            char testBucket[6];
            char testOrder[6];
            char *s, *d;
            for (int i=0; i<5 && bucket[i] != 0; ++i)
            {
                // copy the current order, adding the new card to the end of it
                d = testOrder;
                s = order;
               
                switch(orderLen)
                {
                case 5: *(d++) = *(s++);
                case 4: *(d++) = *(s++);
                case 3: *(d++) = *(s++);
                case 2: *(d++) = *(s++);
                case 1: *(d++) = *(s++);
                }
               
                *(d++) = bucket[i];
                *d = 0;
               
                // copy the current bucket, removing the new card
    #if 0
                d = testBucket;
                s = bucket;
                while(*s != 0) { if (*s != bucket[i]) *(d++) = *(s++); else s++; };
                *d = 0;
    #else
                switch(i)
                {
                case 0:
                    testBucket[0] = bucket[1];
                    testBucket[1] = bucket[2];
                    testBucket[2] = bucket[3];
                    testBucket[3] = bucket[4];
                    testBucket[4] = 0;
                    break;
                case 1:
                    testBucket[0] = bucket[0];
                    testBucket[1] = bucket[2];
                    testBucket[2] = bucket[3];
                    testBucket[3] = bucket[4];
                    testBucket[4] = 0;
                    break;
                case 2:
                    testBucket[0] = bucket[0];
                    testBucket[1] = bucket[1];
                    testBucket[2] = bucket[3];
                    testBucket[3] = bucket[4];
                    testBucket[4] = 0;
                    break;
                case 3:
                    testBucket[0] = bucket[0];
                    testBucket[1] = bucket[1];
                    testBucket[2] = bucket[2];
                    testBucket[3] = bucket[4];
                    testBucket[4] = 0;
                    break;
                case 4:
                    testBucket[0] = bucket[0];
                    testBucket[1] = bucket[1];
                    testBucket[2] = bucket[2];
                    testBucket[3] = bucket[3];
                    testBucket[4] = 0;
                    break;
                }
    #endif

                if ( RecursiveTest (testOrder, orderLen + 1, testBucket, rules))
                    return true;
            }
           
            return false;
        }
       
        // we've passed the test with all 5 in order
        return true;
    }

    int BruteForceAnalysis(int* rules)
    {
        const int cardsInDeck = 52;
       
        int count = 0;
       
        // build a quick thing to index cards sequentially
        char cards[cardsInDeck];
        int suit, rank, i = 0;
        for (suit = 1; suit <= 4; ++suit)
        {
            for (rank = 1; rank <= 13; ++rank, ++i)
            {
                cards[i] = (suit << 4) | rank;
            }
        }
       
        // test every single hand
        char order[6] = { 0, 0, 0, 0, 0, 0 };
        char bucket[6] = { 0, 0, 0, 0, 0, 0 };
        int card1, card2, card3, card4, card5;
        for (card1 = 0; card1 < cardsInDeck; ++card1)
        {   
            if (!(card1 & 1)) printf("\nhmm");
            bucket[4] = cards[card1];
           
            for (card2 = 0; card2 < cardsInDeck; ++card2)
            {
                if (!(card2 & 1)) printf(".");
                if (card2 == card1)
                    continue;

                bucket[3] = cards[card2];
                   
                for (card3 = 0; card3 < cardsInDeck; ++card3)
                {
                    if (card1 == card3 || card2 == card3)
                        continue;
                       
                    bucket[2] = cards[card3];
                       
                    for (card4 = 0; card4 < cardsInDeck; ++card4)
                    {
                        if (card1 == card4 || card2 == card4 || card3 == card4)
                            continue;
                           
                        bucket[1] = cards[card4];
                           
                        for (card5 = 0; card5 < cardsInDeck; ++card5)
                        {
                            if (card1 == card5 || card2 == card5 || card3 == card5 || card4 == card5)
                                continue;
                               
                            bucket[0] = cards[card5];
                           
                            order[0] = 0;
                           
                            //printf("testing %x %x %x %x %x\n", bucket[0], bucket[1], bucket[2], bucket[3], bucket[4]);
                            if (RecursiveTest(order, 0, bucket, rules))
                            {
                                //printf("pass\n");
                                count++;
                            }
                        }
                    }
                }
            }
        }
       
        printf("\n");
       
        return count;
    }

    void PrintProbability(const char* name, int* rules)
    {
        int totalHands = 52 * 51 * 50 * 49 * 48;
       
        printf("calculating probability of %s\n", name);
       
        int prob = BruteForceAnalysis(rules);
        double fprob = (double)prob / (double)totalHands;
       
        printf("probability of %s is %i / %i = %g\n", name, prob, totalHands, fprob);
       
        // print it to file too
        FILE *logFile = fopen("log.txt", "a");
        if (logFile != NULL)
        {
            fprintf(logFile, "probability of %s is %i / %i = %g\n", name, prob, totalHands, fprob);
            fclose(logFile);
        }
        else printf("WARNING: could not write probability to log file\n");
    }

    void PrintTimeTaken(double timeSec)
    {
        printf("calculation took %g seconds\n", timeSec);
       
        FILE *logFile = fopen("log.txt", "a");
        if (logFile != NULL)
        {
            fprintf(logFile, "calculation took %g seconds\n", timeSec);
            fclose(logFile);
        }
        else printf("WARNING: could not write time to log file\n");
    }

    void ClearLogFile(void)
    {
        FILE *f = fopen("log.txt", "w");
        if (f != NULL)
        {
            fclose(f);
        }
        else
        {
            printf("WARNING: could not clear the log file\n");
        }
    }

    int main(int argc, char *argv[])
    {
        ClearLogFile();
       
        int rulesPair[] = { ruleAny, ruleSameRank, ruleAny, ruleAny, ruleAny };
        int rulesTwoPair[] = { ruleAny, ruleSameRank, ruleAny, ruleSameRank, ruleAny };
        int rulesThree[] = { ruleAny, ruleSameRank, ruleSameRank, ruleAny, ruleAny };
        int rulesStraight[] = { ruleAny, ruleNextRank, ruleNextRank, ruleNextRank, ruleNextRank };
        int rulesFlush[] = { ruleAny, ruleSameSuit, ruleSameSuit, ruleSameSuit, ruleSameSuit };
        int rulesHouse[] = { ruleAny, ruleSameRank, ruleSameRank, ruleAny, ruleSameRank };
        int rulesFour[] = { ruleAny, ruleSameRank, ruleSameRank, ruleSameRank, ruleAny };
        int rulesStraightFlush[] = { ruleAny, ruleSameSuitNextRank, ruleSameSuitNextRank, ruleSameSuitNextRank, ruleSameSuitNextRank };
        int rulesRoyal[] = { 10, ruleSameSuitNextRank, ruleSameSuitNextRank, ruleSameSuitNextRank, ruleSameSuitNextRank };
       
        clock_t clockStart = clock();
       
        PrintProbability("a pair", rulesPair);
        PrintProbability("two pair", rulesTwoPair);
        PrintProbability("three of a kind", rulesThree);
        PrintProbability("a straight", rulesStraight);
        PrintProbability("a flush", rulesFlush);
        PrintProbability("a full house", rulesHouse);
        PrintProbability("four of a kind", rulesFour);
        PrintProbability("a straight flush", rulesStraightFlush);
        PrintProbability("a royal flush", rulesRoyal);
       
        printf("\nTada!\n");
       
        clock_t clockTaken = clock() - clockStart;

        double timeTaken = (double)clockTaken / (double)CLOCKS_PER_SEC;
        PrintTimeTaken(timeTaken);
       
        system("PAUSE");
        return EXIT_SUCCESS;
    }

     

  • 06-04-2007 9:29 PM In reply to

    Re: Speed Challenge 24: Fun N' Games #2

    too_many_usernames has an interesting solution (very difficult to compile though), but it doesn't work.  It incorrectly excludes 2 pair, 3 of a kind, full house and 4 of a kind when counting hands that satisfy the requirements for pair.

    ComputerForumUser's didn't take user input, but the rules were clearly defined and easy to edit.  It was finished with 3 of a kind when I sat down for dinned, and finished four of a kind shortly after the dishes were cleared (83 minutes from start to completion).  Oddly enough for a brute-force program it doesn't get all the answers correct either.  It reports 0 instances of straight and royal flushes (it tests for same suit & rank not same suit and next rank).

    Faxmachinen has an very "...what?" solution and it runs pretty fast even at the higher accuracy I used (I would have thought a regex would take a lot longer to run through 2MB, especially one with the feedback) though it can take a long time to solve the pair case.  Unfortunately it doesn't get the right answer, (The result for 4 of a kind is off by an order of magnitude, and due to the behavior of $# the probability of getting a straight-flush is -.00038%, I assume that means even if you stack the deck you can't draw one).  I'd like to combine this with the electronic locks thread, build the shortest string with every possibly hand, and test that.  Now if only I could fit an extra 2GB of RAM in my computer.

    ComputerForumUser, you're up.  That last minute bug fix wins it.
  • 06-04-2007 9:44 PM In reply to

    Re: Speed Challenge 24: Fun N' Games #2

    Congratulations to ComputerForumUser!

     
    Hey, doesn't the success of my, uh, "algorithm" depend on the quality of the search?  *grin*

    Anyway, I managed to avoid doing the "correct" solution which you can do without an exhaustive search. It's actually a fairly straightforward combinations / permutations problem, with a bit of bookkeeping. You can actually do this determination in O(1)...  For the curious, the third result from a Google search on "poker hand probability" does pretty good at explaining the math, and you can also get useful stuff from mathworld.wolfram.com regarding combinations and permutations.

  • 06-05-2007 1:55 PM In reply to

    Re: Speed Challenge 25: Fun N' Games #3

    For the record I would've taken more than 83 minutes longer to code the proper approach. (Which is about the running time I got here too.) All I can think of as a challenge is what my brute forcer was aimed at but never completed, which was to solve the number puzzle from Countdown. Basically a random integer between 1 and 999 inclusive is picked as the target number. Then you get six working integers, which you can add / subtract / multiply / divide in any combination. You need to get as close as possible to the target. Human contestants get 30 seconds of thinking time. The 'working' numbers are usually randomly picked from numbers below 10, or from 25, 50, 75 and I think 100 also. I hope this is ok. Is there usually a time limit? Will 24 hours as of this post do?
  • 06-05-2007 2:49 PM In reply to

    Re: Speed Challenge 25: Fun N' Games #3

    Oops, had to rush away at the end of that post and didn't know that without scripts enabled none of the newlines are processed.
  • 06-05-2007 2:49 PM In reply to

    Re: Speed Challenge 25: Fun N' Games #3

    ComputerForumUser:
    For the record I would've taken more than 83 minutes longer to code the proper approach. (Which is about the running time I got here too.) All I can think of as a challenge is what my brute forcer was aimed at but never completed, which was to solve the number puzzle from Countdown. Basically a random integer between 1 and 999 inclusive is picked as the target number. Then you get six working integers, which you can add / subtract / multiply / divide in any combination. You need to get as close as possible to the target. Human contestants get 30 seconds of thinking time. The 'working' numbers are usually randomly picked from numbers below 10, or from 25, 50, 75 and I think 100 also. I hope this is ok. Is there usually a time limit? Will 24 hours as of this post do?

    Just some clarification because I'm not familiar with the "Countdown puzzle"...

    So you're saying there's a random number in the range [1,999], you get 6 random integers, and can combine those in various primitive math functions to try and arrive at the guess number.  Is there any feedback at each step (e.g., "higher, lower") that you get at each stage, or are you limited to just pick some numbers and hope you're correct? 

     Is the goal to get the target in the fewest number of guesses?
     

  • 06-05-2007 4:53 PM In reply to

    Re: Speed Challenge 25: Fun N' Games #3

    To clarify, you know the target number already. The goal is to produce a calculation involving one or more of the 6 numbers, which gets closer to the target number than anybody else.

    And now I've now just stumbled across a java solution, so I don't know if this one still stands. And my hayfever is kicking in which makes it hard to concentrate...

    hmm....................................................

    Actually, if it's not too late to change my mind, I'd like a program that generates pretty pictures, in ascii, either to screen or text file, with no input except a random seed.
  • 06-05-2007 7:33 PM In reply to

    Re: Speed Challenge 25: Fun N' Games #3

    I like this challenge.
     
     
     
    # -*- coding: cp1252 -*-
    # equirend.py
    
    import math, random
    
    ascii = r"#@W8SGo&%+?:,-^'´ "
    width, height = 70, 30
    
    def pixel(value):
        value = min((max((value, 0.0)), 0.999))
        return ascii[int(value * len(ascii))]
    
    def dist(a, b):
        return math.sqrt((a[0] - b[0])**2 + (a[1] - b[1])**2)
    
    def equidistance(point, anchors):
        dists = [dist(point, a) for a in anchors]
        avgdist = sum(dists) / len(dists)
        distproduct = 1.0
        for d in dists:
            distproduct *= d / avgdist
        return distproduct
    
    if __name__ == "__main__":
        random.seed(raw_input("Random seed?\n"))
    
        anchors = []
        for i in range(random.randint(2, 12)):
            anchors.append([random.randint(0, width), random.randint(0, height)])
    
        print "\nRendering...\n"
    
        # Raytrace
        for y in range(height):
            line = []
            for x in range(width):
                line.append(pixel(equidistance([x, y], anchors)))
            print "".join(line)
    
    rpar PROTON all
  • 06-07-2007 8:08 AM In reply to

    Re: Speed Challenge 25: Fun N' Games #3

    More interesting render functions:


    def closest2(point, anchors):
        dists = [dist(point, a) for a in anchors]
        dists.sort()
        return abs(dists[0] - dists[1]) / dists[1]
    
    
    def rings(point, anchors):
        result = []
        for anchor in anchors:
            d = dist(anchor, point)
            radius = width / 5.0
            result.append(abs(radius - d) / radius)
        return min(result)
    rpar PROTON all
  • 06-12-2007 12:14 PM In reply to

    Re: Speed Challenge 25: Fun N' Games #3

    I think we should just declare Faxmachinen the winner here and move on to a new challenge :-)  I don't want to step on any toes (and perhaps there is a vacation or something involved) but it's been over a week since the last challenge....
  • 06-12-2007 6:13 PM In reply to

    Re: Speed Challenge 25: Fun N' Games #3

    too_many_usernames:
    I think we should just declare Faxmachinen the winner here and move on to a new challenge :-)  I don't want to step on any toes (and perhaps there is a vacation or something involved) but it's been over a week since the last challenge....

    Seconded. Nice solution, Faxmachinen.
  • 06-13-2007 6:38 AM In reply to

    Re: Speed Challenge 25: Fun N' Games #3

Page 1 of 1 (20 items)
Powered by Community Server (Non-Commercial Edition), by Telligent Systems