
<?php |
/** |
* FizzBuzz问题: |
* |
* The aim of the test is to discover the shortest sequence of consecutive numbers, which when they are run through the fizzbuzz algorithm produce the required output. |
* |
* For example, the shortest sequence that produces fizz is 3 |
* |
* When looking for the shortest sequence for |
* |
* fizz buzz |
* |
* one sequence that produces that output is |
* |
* 3, 4, 5 |
* |
* However, this isn't the shortest. The shortest sequence is 9, 10 |
* |
* In our case, we are only interested in the numbers between 1 and 100, so be sure you limit your calculations to that range, otherwise you are likely to exceed timeout limits. |
* |
* InverseFizzBuzz |
* |
* @author 剑锋 |
* @qq 1421560459 |
* |
*/ |
class InverseFizzBuzz { |
private $list; |
private $max = 100; //扫描最大值 |
public function __construct($list) { |
$this->list = $list; |
} |
/** |
* 查找序列 |
* 思路:遍历1-max,分别遍历字符数组,找到fizz或buzz,放到散列结果中保存;补全散列结果得到连续结果序列;找到结果长度最短的 |
* Enter description here ... |
*/ |
public function sequence() { |
$resultList = array(); //结果集 |
//遍历1-max |
for($i = 1; $i <= $this->max; $i++){ |
$resultHash = array(); //结果散列 |
$result = array(); //结果序列之一 |
$last = $i; //上一个扫描结果 |
$isFull = true; //标记是否找到完整序列 |
//查找fizz或buzz |
foreach($this->list as $k => $v){ |
$index = $i; //索引 |
switch($v){ |
case 'fizz':{ |
$index = $this->_scanNextFizz($last); |
if ($index){ //找到fizz |
array_push($resultHash, $index); |
$last = $index; |
}else{ //未找到fizz |
$isFull = false; |
$last++; |
} |
break; |
} |
case 'buzz':{ |
$index = $this->_scanNextBuzz($last); |
|
if ($index){ //找到buzz |
array_push($resultHash, $index); |
$last = $index; |
}else{ //未找到buzz |
$isFull = false; |
$last++; |
} |
break; |
} |
default:{ |
break; |
} |
} |
} |
//填充数字间隔,不完整序列不填充 |
if ($resultHash && $isFull){ |
$time = count($resultHash) - 1; //循环终止下标 |
for($j = $resultHash[0]; $j <= $resultHash[$time]; $j++){ |
array_push($result, $j); |
} |
array_push($resultList, $result); |
} |
} |
//判断是否存在结果(例如 buzz fizz buzz) |
if (count($resultList) == 0){ |
return null; |
} |
//查找最短结果 |
$count = $this->max; |
foreach ($resultList as $v){ |
$length = count($v); |
if ($length < $count){ |
$count = $length; |
$result = $v; |
} |
} |
return $result; |
} |
/** |
* 查找下一个Fizz |
* |
* Enter description here ... |
* @param unknown_type $current |
*/ |
private function _scanNextFizz($current){ |
for($i = $current + 1; $i <= $this->max; $i++){ |
if($i % 5 == 0){ //上次结果与今次结果之间不能有buzz |
return 0; |
} |
if($i % 3 == 0){ |
return $i; |
} |
} |
return 0; |
} |
/** |
* 查找下一个Buzz |
* |
* Enter description here ... |
* @param unknown_type $current |
*/ |
private function _scanNextBuzz($current){ |
for($i = $current + 1; $i <= $this->max; $i++){ |
if($i % 3 == 0){ //上次结果与今次结果之间不能有fizz |
return 0; |
} |
if($i % 5 == 0){ |
return $i; |
} |
} |
return 0; |
} |
} |
//测试 |
$inverse = new InverseFizzBuzz(array('fizz', 'buzz', 'fizz')); //3 4 5 6 |
var_dump($inverse->sequence()); |
?> |



