#!/usr/bin/env perl
#program to generate 6 Million unique codes, Oct 15, 2011.
use strict;
use warnings;
use autodie;
use v5.10; # Just for feature "say"
# Some criteria.
my @digits_used = ( 'a' .. 'z', 3, 4, 6, 7, 9 );
my $string_length = 10;
my $need = 6_000_000;
my $filename = 'testfile.txt';
# Takes a string length, and a list of digits allowed, and returns an
# iterator function that on each call returns a unique string.
sub create_random_string_generator {
# Our bind values:
my $size = shift;
my @contains = @_;
# Our duplicate cache.
my %found;
# Here's where we create an iterator function with bound criteria.
return sub {
my $rand_string;
do{
my @rand_digits;
push @rand_digits,
$contains[ rand @contains ] for 1 .. $size;
$rand_string = join '', @rand_digits;
} while( $found{$rand_string}++ );
return $rand_string;
}
}
# Now we bind our criteria and create a generator iterator function.
my $string_gen =
create_random_string_generator( $string_length, @digits_used );
open my $out_fh, '>', $filename;
for( my $count = 0; $count < $need; $count++ ) {
say $out_fh $string_gen->();
}
close $out_fh;
####
# Verify that there are no duplicates.
perl -nE 'say $_ if $seen{$_}++;' testfile.txt
# We want no output.
# Verify that there are 6000000 lines.
perl -nE '$count++; END{ say $count; }' testfile.txt
# We want 6000000 as the output.
# Verify that we only have digits between a..z and 3, 4, 6, 7, 9.
perl -nE 'say "$. : $_" if m/[^a-z34679\n]/' testfile.txt
# We want no output.
####
package CodeGenerator;
use strict;
use warnings;
sub new {
my $class = shift;
my $self = bless {}, $class;
$self->{string_size} = shift;
$self->{digits_used} = [ @_ ];
$self->{seen} = {}; # Not necessary, but helpful to
# those reading the code.
return $self;
}
sub generate {
my $self = shift;
my $rand_string;
do{
$rand_string = '';
$rand_string .=
$self->{digits_used}[ rand @{$self->{digits_used}} ]
for 1 .. $self->{string_size};
} while( $self->{seen}{$rand_string}++ );
return $rand_string;
}
1;
package main;
use strict;
use warnings;
use autodie;
use v5.10; # For "say".
# Some criteria.
my @digits_used = ( 'a' .. 'z', 3, 4, 6, 7, 9 );
my $string_length = 10;
my $need = 6_000_000;
my $filename = 'testfile.txt';
my $codegen = CodeGenerator->new( $string_length, @digits_used );
open my $out_fh, '>', $filename;
for( my $count = 0; $count < $need; $count++ ) {
say $out_fh $codegen->generate();
}
close $out_fh;