#!/usr/bin/perl

use 5.034;

$|++;

use Memoize qw(memoize);

memoize 'mean';

my $DEBUG = 1;
my $DEBUG_2 = 0;

my $limit = 50;         # number of swaps per clone

my $coin = $ARGV[0];
die "Usage: $0 <filecoin>\n" unless (defined $ARGV[0]);
die "Error: File does not exists" unless -e $coin;
die "Error: File does not seems my type of coins" unless ($coin =~ /coin/);

open my $f, '<', $coin or die $!;
my @file = <$f>;
close $f;

my @byte;
@byte = chr($_) for (0 .. 255);

my @list;
my $c = 0;
for my $l (@file){
    $c++;
    print "\r$c";
    for my $c (split //, $l){
	for my $i (0..255){
	    if (ord($c) == $i){
		$list[$i]++;
	    }
	}
    }
}

say "\nList of $0 at ", scalar localtime();
my $serial = "";
for my $i (0..255){
    say "extended ASCII 8 bit: ", $i,")     $list[$i]      ", "·" x int(($list[$i]-mean(@list))/10) if $DEBUG;
    $serial .= "$list[$i]";
    if ($i != 255){ 
	$serial .= "_"; 
    }
}
say "\nserial stringfy\n$serial\n";


##########################################################

for my $i (1 .. 10){
    @list = clonecoin (@list);
    $serial = "";
    for my $ch ( sort {$a <=> $b} 0 .. scalar(@list)-1 ){
	$serial .= "$list[$ch]";
	if ($ch != 255) { 
	    $serial .= "_"; 
	}
    }
    say "Clone number $i: $serial\n";
}

exit 2;


sub mean {
    my @list = @_;
    my $sum = 0;
    for my $i (@list){
	$sum += $i;
    }
    return $sum / scalar(@list);
}
    

sub clonecoin {
    my @l = @_;
    my $n = 0;
    my ($tmp, $i, $j);
    
swap:    
      $tmp = scalar(@l);
    $i = int($tmp * rand());
    $j = int($tmp * rand());    
    $tmp = $l[$i];
    $l[$i] = $l[$j];
    $l[$j] = $tmp;
    
    if (++$n <= $limit){
	goto swap;
    }	
    
    my $s = "";
    $s .= "$_ " for (@l);
    say $s if $DEBUG_2;
    
    return @l;
}

