【问题标题】:PHP combinations of letters and numbers algorithm and start from X positionPHP字母和数字组合算法并从X位置开始
【发布时间】:2013-12-27 12:07:06
【问题描述】:

我一直在使用这个算法,现在输出是这样的字符串:

AAA AAB AAC AAD AAE AAF AAG AAH AAI AAJ AAK AAL AAM AAN AAO AAP AAQ AAR AAS AAT AAU AAV AAW AAX AAY AAZ AA0 AA1 AA2 AA3 AA4 AA5 AA6 AA7 AA8 AA9 (循环结束 1)强> ABA ABB ABC ABD ABE ABF ABG ABH ABI ABJ ABK ABL ABM ABN ABO ABP ABQ ABR ABS ABT ABU ABV ABW ABX ABY ABZ AB0 AB1 AB2 AB3 AB4 AB5 AB6 AB7 AB8 AB9 (END OF 循环 2)

这很有效,但是假设我想从 AB0 位置继续。 X 位置后如何继续?我一直在尝试实现一个位置守卫的代码,但我的想法已经用完了,现在我已经把头发拉出来了。

我的项目所做的是创建一些 text.txt 文件,其中包含以下代码可以执行的所有可能组合,但它会在一个长字符串/回声中回显所有内容,所以,我想要实现的是能够将那些 text.txt 文件分成几部分。

例如,需要 5700 个组合(5700 个循环)、5 个 1000 个组合的 text.txt 和一个剩余 700 个组合的 text.txt 文件。如何在不从头开始的情况下从循环 3000 继续?

这是我正在使用的代码:

<?php
ini_set('memory_limit', '3062M');
/*
Author: Luka Vidaković
Website: http://www.lvidakovic.com
Date: 21.2.2013.
*/
$charSet .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charSet .= '0123456789';

$size = strlen($charSet);
$base = array();
$counter = 0;

$maxLength = 3; // 3 for now to experiment
$baseSize = 3; // min

$loops_to_make = 1; // 0 will loop once. 1 will loop twice and so on...
$loops_done = 0;
$megavar = "";

while($baseSize <= $maxLength)
{
    if($loops_done > $loops_to_make) { break; }
    // Go through all the possible combinations of last character and output $base
    for($i = 0; $i < $size; $i++)
    {
        $base[0] = $i; //echo $i." ";
        for($j=$baseSize-1;$j>=0;$j--)
        {
            $megavar .= $charSet[$base[$j]];
        }
        $megavar .= ' ';    
    }
    // How many $base elements reached their max?
    for($i = 0; $i<$baseSize;$i++)
    {
        if($base[$i] == $size-1) { $counter++; $megavar .= "<br>|(".$j.")|"; }
        else break;
    }
    // Every array element reached max value? Expand array and set values to 0.
    if($counter == $baseSize)
    {
        // Notice <=$baseSize! Initialize 0 values to all existing array elements and ADD 1 more element with that value
        for($i=0;$i<=$baseSize;$i++)
        {
            $base[$i] = 0;
        }
        $baseSize = count($base);
    }
    // Carry one
    else
    {
        $base[$counter]++;
        for($i=0;$i<$counter;$i++) $base[$i] = 0;
    }
    $loops_done++;
    $counter=0;
}
echo $megavar; // Eventually I'll echo this into a txt file
?>

我也愿意接受其他创建相同输出的想法,只要使用 PHP 或更好。 谢谢。

【问题讨论】:

  • 看起来你正在计算base 36的修改版本。所以,我会编写一个可以转换为十进制和从十进制转换的函数。然后,要获得序列中的下 X 个项目,请将字符串转换为十进制,使用普通数学运算获得下 X 个数字,然后将它们中的每一个转换回您的系统。
  • 字符串的长度总是 3?我的意思是这个序列最终会在999结束吗?
  • @Fallen 我写了 3 作为例子,要求是 10 分钟和 10 最大,谢谢。
  • @halfer 我明白你的意思,你能提供一些代码开始吗?感谢您的快速回复
  • 我想现在你已经掌握了一些关于如何处理算法的线索,你可以自己试一试。但是,这将涉及不偷看下面的答案...:)

标签: php algorithm


【解决方案1】:

您的问题是计算给定字符串和给定位置之和的简单案例。唯一的困难是您的数字基数是36,并且数字是自定义的。但这可以通过strtr()base_convert() 组合轻松解决:

function getSeed($string, $positions=1)
{
   $convert = array_combine(
                  array_merge(range('A', 'Z'), range('0', '9')),
                  array_merge(range('0', '9'), range('A', 'Z'))
              );
   //actually, $result can be written as one-liner
   //but that will be horrible whitespacing..
   $result  = base_convert(strtr($string, $convert), 36, 10);
   $result  = strtoupper(base_convert($result+$positions, 10, 36));
   $result  = strtr(str_pad($result, strlen($string), '0', STR_PAD_LEFT), array_flip($convert));
   return $result;
}

所以要使用它,只需调用:

$result = getSeed('AAA', 40);//ABE

因此,您既可以在循环中生成值,也可以通过指定偏移量来恢复循环。请注意,如果您要在循环中使用它,我建议您评估 $convert 外部函数。这样可以节省不必要的开销。

【讨论】:

    【解决方案2】:
    function convertNumber($number, $target_length = 10){
        $digits[]=array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
                        "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
                        "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); // hardcoded to make the answer clearer
        $ret = "";
    
        while((int)$number > 0){
            $remainder = $number % 36;
            $number    /= 36;
            $ret       .= $digits[$remainder];
        }
        while(strlen($ret) < $target_length)
            $ret .= "A"; // appending leading zero('A' is zero in this system)  to fix the size
    
        $ret = strrev($ret);
        return $ret;
    }
    

    您可以在号码x 上运行一个循环,然后打印converNumber(x)。这样就不需要额外的开销。

    警告:代码未经测试

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-20
      • 1970-01-01
      • 2014-07-31
      • 1970-01-01
      • 2011-08-06
      • 1970-01-01
      • 2021-05-03
      相关资源
      最近更新 更多