3

嗨,我正在尝试构建一个函数,它将遍历所有可能的数字序列并将序列传递给函数,如果它返回 true,则停止。

这是标记:

function sequences($smallest, $biggest, $long, $func) {
   $seq = array(); // Will have $long values 
   /*
    * generates the sequence
   */

   if (call_user_func($functions[$func])) {
      return $seq;
   } else {
      //generate next sequence.
   }

} 

生成的序列将具有整数到整数之间的$long 唯一值,并且必须进行排序示例:$smallest$biggest

/* $long = 4; $smallest = 5, $biggest = 10;
 * 
 * 5,6,7,8
 * 5,6,7,9
 * 5,6,7,10
 * 5,6,8,9
 * 5,6,8,10
 * ...
 * 7,8,9,10
 *
 *
 * $long = 4; $smallest = 15, $biggest = 60;
 *
 * ...
 * 15,41,49,56
 * ...
 * 37,39,53,60
 * ...
 */

我一直无法理解它,到目前为止,我实现这一目标的唯一方法是随机生成数字,而不是每次对数组进行排序。这显然不是最好的方法。

其他编程语言也会很棒(c++、C#、js、java)。

笔记

  • 它不是里程表,不允许在序列中重复数字,并且每个索引的值可以大于9。
  • 根据某些条件测试序列并返回 True 或 False 的函数无关紧要,实际问题是一个接一个地生成没有重复的序列。
4

1 回答 1

1

生成您指定的序列是一个有趣的挑战。

下面的代码应该做你想做的(我认为)。或者至少你应该能够修改它以满足你的需要。我不确定您是否希望该sequences()函数仅返回测试函数$functions[$func]返回的第一个序列true,或者到目前为止的所有序列。在此示例中,仅返回第一个“匹配项”(或者null如果未找到匹配项)。

此代码需要 PHP 5.5+,因为它使用生成器函数(以及 PHP 5.4+ 中可用的短数组语法)。我在 PHP 5.5.12 上对此进行了测试,它似乎按预期工作。如果需要,可以修改代码以在较旧的 PHP 版本上工作(只是避免使用生成器/产量)。实际上这是我第一次编写 PHP 生成器函数。

sequenceGenerator()是一个递归生成器函数,您可以使用foreach.

我还编写了一个echoSequences()用于测试序列生成的函数,它使用 echo 按顺序输出所有生成的序列。

function sequenceGenerator(array $items, $long = null, $level = 1, $path = null) {
    $itemCount = count($items);
    if (empty($long)) $long = $itemCount;
    if ($path == null) $path = [];

    if ($itemCount > 1) {
        foreach ($items as $item) {
            $subPath = $path;
            $subPath[] = $item;
            if ($level == $long) {
                yield $subPath;
                continue;
            }

            if (count($subPath) + count($items) > $long) {
                $items = array_values(array_diff($items, [$item]));
                $iteration = sequenceGenerator($items, $long, $level + 1, $subPath);
                foreach ($iteration as $value) yield $value;
            }
        }
    } elseif ($itemCount == 1) {
        $path[] = $items[0];
        yield $path;
    }
}

// Function for testing sequence generation
function echoSequences($smallest, $biggest, $long) {
    $items = range($smallest, $biggest);
    foreach (sequenceGenerator($items, $long) as $sequence) {
        echo implode(',', $sequence)."<br>\n";
    }
}

function sequences($smallest, $biggest, $long, $func) {
    global $functions;
    $items = range($smallest, $biggest);
    foreach (sequenceGenerator($items, $long) as $sequence) {
        if (call_user_func($functions[$func], $sequence)) {
            return $sequence;
        }
    }
    return null; // Return null when $func didn't return true for any sequence
}

//echoSequences(5, 10, 4); // Test sequence generation

$functions = array(
    // This test function returns true only for the sequence [5,6,8,10]
    'testfunc' => function($sequence) { return ($sequence == [5,6,8,10]); }
);

$sequence = sequences(5, 10, 4, 'testfunc'); // Find the first sequence that 'testfunc' will return true for (or null)
if (!empty($sequence)) {
    echo 'Found match: '.implode(',', $sequence);
} else {
    echo 'Match not found';
}
于 2015-05-06T16:51:21.463 回答