简体   繁体   中英

How to generate unique number with 3 digits and no double numbers in each digit in PHP

I want to generate 3 digits numbers in 120 pairs No duplication and repeat numbers Example: 012 , 013, 132 is valid 011,333, 022,202, 210 is invalid note: 012 and 210 is redundancy digits both appears therefore it is invalid

I am using PHP Version 5.6.28 Apache/2.4.23 (Win32) OpenSSL/1.0.2h PHP/5.6.28 this is what I tried so far but no luck.

number count: 120 027 028 029 036 038 046 069 074 079 093 105 106 109 123 143 145 149 152 153 162 167 175 182 195 198 204 208 213 216 217 219 235 243 275 287 294 301 302 310 327 341 342 347 352 357 358 365 369 376 378 380 384 392 402 408 415 423 428 431 453 465 467 468 490 493 496 506 509 510 512 524 537 541 561 573 591 597 598 609 629 631 634 639 647 689 691 694 697 703 719 723 743 745 750 752 759 761 813 819 820 824 829 840 865 875 890 905 907 912 916 917 921 930 941 945 947 963 965 973 984

Note here 537 and 573 is invalid

/*----Numbers.php----*/

class Numbers{
    private $num_set = array();//get 3 digit
    private $num_basket = array(); //container
    public $codeNum = "0123456789";


    public function get_basket(){
        return $this->num_basket;
    }
    public function put_basket($num){
        $this->num_basket[] = $num;
    }

    public function is_exist($num_taken){
        if(in_array($num_taken, $this->num_basket)){
            return true;
        }else{
            return false;
        }        
    }

    public function generate_num(){
        while(count($this->num_set) < 3){
            $get_one_digit = $this->getToken(1);
            if(!in_array($get_one_digit, $this->num_set)){
                $this->num_set[] = $get_one_digit;

            }
        }
        $three_digit = implode($this->num_set);
        $this->num_set = array();
        return $three_digit;
    }

    protected function getToken($length)
    {
        $token = "";

        $max = strlen($this->codeNum); // edited

        for ($i=0; $i < $length; $i++) {
            $token .= $this->codeNum[$this->crypto_rand_secure(0, $max-1)];
        }   
        return $token;
    }

    //generate code
    protected function crypto_rand_secure($min, $max)
    {
        $range = $max - $min;
        if ($range < 1) return $min; // not so random...
        $log = ceil(log($range, 2));
        $bytes = (int) ($log / 8) + 1; // length in bytes
        $bits = (int) $log + 1; // length in bits
        $filter = (int) (1 << $bits) - 1; // set all lower bits to 1
        do {
            $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
            $rnd = $rnd & $filter; // discard irrelevant bits
        } while ($rnd > $range);
        return $min + $rnd;
    }
}

/*----- index.php ---*/

include("Numbers.php");
$num = New Numbers;

for($i=0;$i<120;$i++){
    $num_item = $num->generate_num();
    while($num->is_exist($num_item) == true){
        $num_item = $num->generate_num();
    }

    $num->put_basket($num_item);
}

$num_basket = $num->get_basket();
if(!empty($num_basket)){
    print "number count: ".count($num_basket)."<br>";
    sort($num_basket);
    foreach($num_basket as $item){
        print $item[0].$item[1].$item[2]." ";
    }

}

the code works fine and display no error but does not display expected result. I really need help. I will greatly appreciate any help.

I've rewritten the code as I think there is too much combination of the class and the code outside the class which creates to much of a dependency (IMHO).

In this code, you create a class and say how many numbers you want to generate, then calling the generate() method does all of the work for you.

To check if the numbers have been used before, I encode the number to a bit field and store this (the encode() method just adds binary numbers according to the digits used). If this same pattern happens again, it just tries another one.

class NumberGenerator{
    private $numbersUsed = [];
    private $basket = [];
    private $numbersToGenerate = 0;

    public function __construct( int $numbersToGenerate )   {
        $this->numbersToGenerate = $numbersToGenerate;
    }

    public function generate(){
        $numbers = range(0,9);
        for ( $i = 0; $i < $this->numbersToGenerate; $i++ ) {
            do    {
                shuffle($numbers);
                $number = array_slice($numbers, 0,3);
                $encoded = $this->encode($number);
            }
            while ( in_array($encoded, $this->numbersUsed) );
            $this->basket[] = implode($number);
            $this->numbersUsed[] = $encoded;
        }

        return $this->basket;
    }

    protected  function encode(array $num)  {
        $numbers = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512];
        $sum = 0;
        foreach ( $num as $digit )  {
            $sum += $numbers[$digit];
        }
        return $sum;
    }
}

$generator = new NumberGenerator(120);
print_r($generator->generate());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM