php - 如何在PHP中生成具有3位数字且每个数字中没有双数字的唯一数字
问题描述
我想在 120 对中生成 3 位数字 没有重复和重复的数字 示例:012
013、132 是有效的 011,333、022,202210
是无效的 注意:012
并且210
是冗余数字都出现因此它是无效的
我正在使用 PHP 版本 5.6.28 Apache/2.4.23 (Win32) OpenSSL/1.0.2h PHP/5.6.28 这是我迄今为止尝试过的,但没有运气。
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
注意这里537
是573
无效的
/*----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]." ";
}
}
代码工作正常,不显示错误,但不显示预期结果。我真的需要帮助。我将不胜感激任何帮助。
解决方案
我重写了代码,因为我认为类和类之外的代码组合太多,这会产生很多依赖(恕我直言)。
在这段代码中,您创建一个类并说出您想要生成多少个数字,然后调用该generate()
方法为您完成所有工作。
为了检查之前是否使用过这些数字,我将数字编码到一个位字段并存储它(该encode()
方法只是根据使用的数字添加二进制数字)。如果同样的模式再次发生,它只会尝试另一个模式。
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());
推荐阅读
- dll - VSTS 构建 - 在构建的测试执行期间找不到编码的 UI 测试
- python - KeyError 问题:0
- javascript - 如何使用 Amplify with Javascript 返回 AWS 用户池中的用户状态?
- android - 从未使用过的观察者方法
- reactjs - 向 StatelessComponent 添加属性
- mysql - 外键创建了一个额外的列 mySQL
- sql-server - 我使用“INTERSECT”作为关键字搜索了 SQL Server 问题,但没有找到任何帮助
- hyperledger-fabric - Hyperledger - 构建您的第一个网络错误
- r - 减少cowplot中的空白边距
- php - eclipse/PHP:导入 Tracy\Debugger 无法解析