challenge n人中m人が当選するくじ

n人の中から公平にm人を選ぶ、くじ引きプログラムを作ってください。

Posted feedbacks - Perl

これでどうだ!
1
2
3
4
5
6
7
8
sub lot {
    my ($n, $m) = @_;
    my @list = map { $_->[0] } 
               sort { $a->[1] <=> $b->[1] } 
               map { [$_, rand] } 
                 (1 .. $n);
    splice(@list, 0, $m);
}

つい書いてしまった。
1
2
3
4
5
sub lot {
    my ($n, $m) = @_;
    my @a = 0..$n-1;
    map { splice @a, int rand scalar @a, 1 } 1..$m;
}

てか m 人が常に連続でも題意は満たしてるよね。ということで1ステートメントに。
1
2
3
4
sub lot {
    my ($n, $m) = @_;
    splice @{[ 0..$n-1, 0..$n-1 ]}, int rand $n, $m;
}

一応O(nm)になってるかな?
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/local/bin/perl

use strict;
use warnings;

use Data::Dumper;

my $nmax = shift;
my $mmax = shift;

my @winner;

#warn "selecting $nmax from $mmax\n";
for my $n ( 0 .. $nmax - 1 ) {
        my $count = 0;
        for my $m ( 1 .. $mmax ) {
                next if grep { defined $_ and $_ == $m } @winner;
                if ( rand( $count ) < 1 ) {
                        $winner[$n] = $m;
                }
                $count++;
        }
}

print join( "\n", @winner) , "\n";

進捗表示と範囲チェックを追加。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/local/bin/perl

use strict;
use warnings;

use Data::Dumper;

my $nmax = shift;
my $mmax = shift;

if ( $nmax >= $mmax ) {
        print "$_\n" for ( 1 .. $mmax );
        exit;
}

my @winner;

#warn "selecting $nmax from $mmax\n";
for my $n ( 0 .. $nmax - 1 ) {
        print STDERR '.';
        my $count = 0;
        for my $m ( 1 .. $mmax ) {
                next if grep { defined $_ and $_ == $m } @winner;
                if ( rand( $count ) < 1 ) {
                        $winner[$n] = $m;
                }
                $count++;
        }
}

print STDERR "\n";
print join( "\n", @winner) , "\n";


	
1
2
use List::Util qw/shuffle/;
sub lot {($n,$m)= @_; (shuffle(1..$n))[1..$m];}

動作環境 Fedora7 Perl5.8.8

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/usr/bin/perl
use strict;

exit main();

sub main{
        if(@ARGV != 2){
                print "usage: perl 3360.pl <total-number> <target-number>\n";
                return 1;
        }

        my $rtn = 0;

        if($rtn = is_num($ARGV[0])){
                print "$ARGV[0] not integer\n";
                return $rtn;
        }

        if($rtn = is_num($ARGV[1])){
                print "$ARGV[1] not integer\n";
                return $rtn;
        }

        if($ARGV[0] <= $ARGV[1]){
                print "$ARGV[0] isn't greater than $ARGV[1]\n";
                return 3;
        }

        my $total = $ARGV[0];
        my $target = $ARGV[1];

        my $rand_numbers = get_rand_number($total,$target);

        print join "\n", @$rand_numbers;

        return 0;
}

sub is_num{
        my ($num) = shift;

        if($num !~ / [0-9]+$/){
                return 2;
        }

        return 0;
}

sub get_rand_number{
        my ($total,$target) = @_;

        my $numbers = [];
        my $rand = undef;

        for(my $i=0; $i<$target; $i++){
                $rand = int(rand($total))+1;

                if(!grep { /^$rand$/ } @$numbers){
                        push @$numbers, $rand;
                }
                else{
                        redo;
                }
        }

        return $numbers;
}

Index

Feed

Other

Link

Pathtraq

loading...