codes-poker.pl


#! perl
#
use v5.036;
use String::LCSS "lcss";
# no longer need use experimental  'signatures';


## To test whether 6 digit confirm codes are likely to have a pattern
#

my $N = 1000;

my @Samples=(  ## calibration samples
    [1, 2, 3, 4, 5, 5],
    [1, 2, 3, 1, 2, 3],
    [1, 2, 3, 4, 5, 6],
    [2, 4, 6, 8, 9, 0],
    [2, 4, 6, 8, 7, 0],
    [1, 5, 2, 5, 9, 5],  # not sequence, not treble, just repeat 5
    [3, 4, 5, 6, 5, 5],  # analogous to J555+5 his nobs Cribbage 29
                         # imperfect as should get 3×5 and Seq:4 either way?
    [3, 4, 5, 5, 5, 6],  # analogous to J555+5 his nobs Cribbage 29
     );
 
push @Samples, random_code() for 0..($N - (1+ scalar @Samples));
say scalar @Samples;

my $nothings=0;

for my $sample (@Samples){
    # say $sample->@*;
    my $hand = hand($sample);
    say $sample->@*, " = $hand ;";
    $nothings ++ if $hand eq 'nothing';
}

say "$nothings nothings; ", $nothings/$N ;


sub hand($aref){
    my %Names=(2=>'pair',3=>'three',4=>'four',5=>'five',6=>'six',0=>'nought',1=>'single',);

    my $String = join q(), $aref->@*;
    my @Cards = sort $aref->@*;
    my @Scores;


    # repeat of ..xxx.. or xy..xyp
    my ($one, $two, $three) = ($String =~ m{ ((\d)\g{2}+) | (\d{2,}).*\g{3}  }xism  ); 
    #                    say "## '$String' : (($two)$one) | ($three) "; # debug
    my $rep = $one || $two || $three || '';
    push @Scores, "rep:@{[length $rep]}:$rep" if $rep;

    my $seq = longest_seq($String);
    push @Scores, "seq:$seq" if $seq;

    my %Count;
    $Count{$_}++ for @Cards;
    # say  grep {$_ ne 1} values %Count;
    push @Scores, $_ for map { $Names{$_} } grep {$_ ne 1} values %Count;

    return 'nothing' unless @Scores;

    return join q(,), @Scores;

}

# find longest sequence
sub longest_seq ($string){
    # prefers ascending sequence to a longer descending or arithmetic skip seq
    # although neither Poker nor Cribbage allows sequence of TWO, 
    # nor arithmetic skips of 2,3,4,
    # optionally allowed those here as they're human patterns.
    #
    # Allowing descending, skip, length 2 nearly obliterates nothings!
    # (from 1 nothing in ~8, to 1 nothing in ~50)
    my $MIN_SEQ   = 2;
    my $ALLOW_ALT = 1;
    my $main_sequence = '0123456789012345'; # master; allow for around-the-corner seqs
    my ($longest,$iLeft,$iRight) = lcss($main_sequence, $string);

    return length($longest).":$longest"
        if  $longest
        and length($longest) >= $MIN_SEQ ;

    return unless $ALLOW_ALT;

    my $alt_sequence = '9876543210 024680 13579 0369 048';
    ($longest,$iLeft,$iRight) = lcss($alt_sequence, $string);
    return length($longest).":$longest"
        if  $longest
        and length($longest) >= $MIN_SEQ ;


    return ;
}

## Pick a random 6 digit code, draw with replacement
sub random_code (){
   return [ map {random_int_between(0,9)} 1..6 ] ;
}

# from perlfaq4, modified for signatures
sub random_int_between ($min, $max) {
    # Assumes that the two arguments are integers themselves!
    return $min if $min == $max;
    ($min, $max) = ($max, $min)  if  $min > $max;
    return $min + int rand(1 + $max - $min);
}