PE-CN / pe-cn-comments

2 stars 0 forks source link

Problem 54 | Project Euler | #56

Open sx349 opened 4 years ago

sx349 commented 4 years ago

https://pe-cn.github.io/54/

Problem 54 Poker hands In the card game poker, a hand consists of five cards and are ranked, from lowest to highest, in the following way: High Card: Highest value card. One Pair: Two cards of the s

p-gp commented 2 years ago
#include <stdio.h>
#include <ctype.h>

int cd[21];

int vs(void);
int vs2(int *arr1, int *arr2, int x);
int num(int x);

int main()
{
    FILE *fp = NULL; 
    fp = fopen("e54.txt", "r");
    if (!fp) {
        printf("can't fine file!");
        return 1;
    }

    int c , cnt = 0, win = 0;
    while (++cnt <= 1000) {
        for (int i = 0; i < 20; ++i) {                
            while (isspace(c = fgetc(fp)))
                ;
            cd[i] = num(c);
        }
        if (vs())
            ++win;
    }
    printf("%d\n", win);
    fclose(fp);

    return 0;
}

int vs(void)
{
    int sc1[25] = {0}, sc2[25] = {0}, s, cnt;

    for (int i = 0; i < 10; i += 2) {
        ++sc1[cd[i]];
    }
    for (int i = 1; i<= 14; ++i) {
        switch (sc1[i]) {
            case 2:
                sc1[0] += 3;
                break;
            case 3:
                sc1[0] += 7;
                sc1[21] = i;    //三条
                break;
            case 4:
                sc1[0] += 11;
                sc1[17] = i;    //四条
                break;
        }            
    }

    for (int i = 10; i < 21; i += 2) {
        ++sc2[cd[i]];
    }
    for (int i = 1; i<= 14; ++i) {
        switch (sc2[i]) {
            case 2:
                sc2[0] += 3;
                break;
            case 3:
                sc2[0] += 7;
                sc2[21] = i;    //三条
                break;
            case 4:
                sc2[0] += 11;
                sc2[17] = i;    //四条
                break;
        }            
    }

    //同花
    if ((cd[1]==cd[3]) && (cd[3]==cd[5]) && (cd[5]==cd[7]) && (cd[7]==cd[9])) {
        s = 0;
        for (int i = 1; i <= 14; ++i) {
            if (sc1[i]) {
                if (i > s)
                    s = i;
            }
        }
        sc1[19] = s;
        sc1[0] = 9;
    }
    if ((cd[11]==cd[13]) && (cd[13]==cd[15]) && (cd[15]==cd[17]) && (cd[17]==cd[19])) {
        s = 0;
        for (int i = 1; i <= 14; ++i) {
            if (sc2[i]) {
                if (i > s)
                    s = i;
            }            
        }
        sc2[19] = s;
        sc2[0] = 9;
    }

    //顺子
    cnt = 0, s = 0;
    for (int i = 1; i <= 14; ++i) {
        if (sc1[i]) {
            ++cnt;
            s = i;
            if (cnt == 5) 
                sc1[20] = s; //顺子
        }
        else{
            cnt = 0;
        }
    }
    sc1[0] = 8;

    cnt = 0, s = 0;
    for (int i = 1; i <= 14; ++i) {
        if (sc2[i]) {
            ++cnt;
            s = i;
            if (cnt == 5) 
                sc2[20] = s; //顺子
        }
        else{
            cnt = 0;
        }
    }
    sc2[0] = 8;

    //大同花顺
    if (sc1[19] && sc1[10] && sc1[11] && sc1[12] && sc1[13] && sc1[14]) {
        sc1[0] = 12;
        sc1[15] = 1;
    }

    if (sc2[19] && sc2[10] && sc2[11] && sc2[12] && sc2[13] && sc2[14]) {
        sc2[0] = 12;
        sc2[15] = 1;
    }
    //同花顺
    if (sc1[19] && sc1[20]) {
        sc1[16] = sc1[19];
        sc1[0] = 11;
    }
    if (sc2[19] && sc2[20]) {
        sc2[16] = sc2[19];
        sc2[0] = 11;
    }
    //对子
    if (sc1[0] = 3)
        for (int i = 1; i <= 14; ++i) {
            if (sc1[i] > sc1[23])
                sc1[23] = sc1[i];
        }
    if (sc2[0] = 3)
        for (int i = 1; i <= 14; ++i) {
            if (sc2[i] > sc2[23])
                sc2[23] = sc2[i];
        }
    //单张
    if (!sc1[0])
        for (int i = 1; i <= 14; ++i) {
            if (sc1[i] == 1)
                sc1[24] = i;
        }            
    if (!sc2[0])
        for (int i = 1; i <= 14; ++i) {
            if (sc2[i] == 1)
                sc2[24] = i;
        }
    //葫芦
    if (sc1[0] == 10)
        sc1[18] = sc1[21] * 16 + sc1[22];
    if (sc2[0] == 10)
        sc2[18] = sc2[21] * 16 + sc2[22];
    //两对
    if (sc1[0] == 6) {
        int v1 = 0, v2 = 0;
        for (int i = 1; i <= 14; ++i) {
            if (sc1[i] == 2)
                if (i > v1)
                    v1 = i;
                else
                    v2 = i;
        }
        sc1[22] = v1 * 16 + v1;
    }
    if (sc2[0] == 6) {
        int v1 = 0, v2 = 0;
        for (int i = 1; i <= 14; ++i) {
            if (sc2[i] == 2)
                if (i > v1)
                    v1 = i;
                else
                    v2 = i;
        }
        sc2[22] = v1 * 16 + v1;
    }
    if (sc1[0] > sc2[0])
        return 1;
    else if (sc1[0] < sc2[0])
        return 0;
    else
        return vs2(sc1, sc2, 16);
}

int num(int x)
{
    switch (x) {
        case 'T':
            return 10;
        case 'J':
            return 11;
        case 'Q':
            return 12;
        case 'K':
            return 13;
        case 'A':
            return 14;    
        default :
            return (x - '0');
    }
}

int vs2(int *arr1, int *arr2, int x)
{
    if (arr1[x] > arr2[x])
        return 1;
    else if (arr1[x] < arr2[x])
        return 0;
    else
        return vs2(arr1, arr2, x - 1);
}

...................................................................................................

432

Jin-bao commented 9 months ago

楼上什么玩意儿,答案是 376🤣

yuandi42 commented 2 months ago

感觉这题就是写个处理表格的程序,跟数论不太沾边。这个 10% 难度不太有含金量。

use v5.38;
use List::Util qw(zip);

my %ranks = (
    # note that full house = pair + 3kind;
    # pair + pair = 2pairs;
    # straight flush = straight + flush
    "high" => 0,
    "pair" => 1,
    "2pairs" => 2,
    "3kind" => 3.5,
    "straight" => 4,
    "flush" => 4.25,
    "fullh" => 4.5,
    "4kind" => 7,
    "sflush" => 8.25,
);

sub card_info($card) {
    my($val, $suit)=(split "", $card);
    if ($val =~ /[A-Z]/) {
        if ($val eq "T") {
            $val = 10;
        } elsif ($val eq "J") {
            $val = 11;
        } elsif ($val eq "Q") {
            $val = 12;
        } elsif ($val eq "K") {
            $val = 13;
        } elsif ($val eq "A") {
            $val = 14;
        }
    }
    [$val, $suit];
}

sub get_hand_vals($hand) {
    #sort numerically ascending:
    [ sort {$a <=> $b} map { $_->[0] } @$hand ];
}

sub get_hand_suits($hand) {
    [ map { $_->[1] } @$hand ];
}

sub is_flush($suits) {
    my $suit = shift @{$suits};
    for (@{$suits}) {
        return 0 unless $_ eq $suit;
    }
    return 1;
}

sub is_straight($vals) {
    # vals should get sorted ascending previously.
    my $n = $vals->[0];
    foreach (@$vals[1..4]) {
        return 0 unless $_ == $n+1;
        $n = $_;
    }
    return 1;
}

sub hand_info($hand) {
    # hand: [ [$val, $suit] x5 ]
    my ( $rank, $vals, $suits ) = ( 0, get_hand_vals($hand), get_hand_suits($hand) );
    my ( $rank_vals, $high_vals ) = ( [], [] );
    if (is_flush($suits)) {
        $rank += $ranks{"flush"};
        push @$rank_vals, reverse @$vals;
    }
    if (is_straight($vals)) {
        $rank += $ranks{"straight"};
        push @$rank_vals, $vals->[-1] unless 0 != scalar @$rank_vals;
    } elsif($rank != $ranks{"flush"}) {
        my %vals_hash = ();
        foreach my $val (@$vals) {
            if (exists $vals_hash{$val}) {
                $vals_hash{$val} ++;
            } else {
                $vals_hash{$val} = 1;
            }
        }
        foreach my $key_val (sort  {$b<=>$a} keys %vals_hash) {
            my $val_count = $vals_hash{$key_val};
            if (4 == $val_count) {
                $rank += $ranks{"4kind"};
                unshift @$rank_vals, $key_val;
            } elsif (3 == $val_count) {
                $rank += $ranks{"3kind"};
                unshift @$rank_vals, $key_val;
            } elsif (2 == $val_count) {
                $rank += $ranks{"pair"};
                push @$rank_vals, $key_val;
            } else {
                push @$high_vals, $key_val;
            }
        }
    }
    # vals should be sorted from high to low correctly.
    [ $rank, @$rank_vals, sort {$b<=>$a} @$high_vals ];
}

sub parse($cards) {
    foreach (@{$cards}) {
        $_ = card_info($_);
    }
    my $p1hands = hand_info [@{$cards}[0..4]];
    my $p2hands = hand_info [@{$cards}[5..9]];
    #pxhands: [ rank, rank val, high cards' val ]
    [ $p1hands, $p2hands ];
}

sub who_will_win ($two_hands) {
    #p1p2: [ [rank1, rank2] [rank_val1, rank_val2] ... ]
    foreach my $p1p2 (zip $two_hands->[0], $two_hands->[1]) {
        for ($p1p2->[0] <=> $p1p2->[1]) {
            return 1 if $_ == 1;
            return 2 if $_ == -1;
        }
    }
    die "You shouldn't get here.\n" . join " ", map { ("HAND:", @$_ , ";") } @$two_hands;
}

my $count = 0;
# read the file line by line.
while(<>) {
    chop;
    $count++ if 1 == who_will_win(parse([split " ", $_]));
}

say $count;