问题描述

FizzBuzz问题:一个大于0的自然数能整除3,将输出“Fizz”;能整除5,将输出“Buzz”;能整除3和5,将输出“FizzBuzz”;否则输出自己。

逆FizzBuzz问题最短序列:已知一个FizzBuzz问题的非数字输出序列,求能获得该序列的最短连续数字序列。如“Fizz”的最短序列是“3”,“Fizz Buzz”的最短序列是“9 10”,而不是“3 4 5”。

编程实现

 <?php

 /**
* @author cenze
*
* 反FizzBuzz问题求最短序列
*
* $inverseFizzBuzz = new InverseFizzBuzz([
* 'fizz',
* 'fizz',
* 'buzz',
* ]);
* $inverseFizzBuzz->sequence():
* Array ( [0] => 6 [1] => 7 [2] => 8 [3] => 9 [4] => 10 )
*/
class InverseFizzBuzz
{
// FizzBuzz问题赋值
const FizzBuzz = [
'fizz' => 3,
'buzz' => 5,
'fizzbuzz' => 15
]; // 预定义问题区间
private $range = [
1,
100
]; // 待求序列
private $list = []; // 待求序列包含项数统计
private $listItemsCount = 0; public function __construct($list = [], $range = [])
{
$this->init($list, $range);
} /**
* 待求序列、区间初始化
*
* @param array $list
* 待求序列
* @param array $range
* 问题区间
* @param bool $check
* 是否检查属性已完成初始化
*
* @return void
*/
private function init($list = [], $range = [], $check = false)
{
if ($list) {
$this->list = $this->inverseList($list);
$this->listItemsCount = count($this->list);
if (! $this->listItemsCount) {
exit('Invalid list.');
}
} if ($range) {
$this->range = $range;
} if ($check) {
if (! $this->list) {
exit('Property list uninitialized.');
}
}
} /**
* 将待求解序列反转
*
* @param array $list
* 待求解序列
*
* @return mixed
*/
private function inverseList($list)
{
$inverseList = [];
foreach ($list as $item) {
if (! array_key_exists($item, self::FizzBuzz)) {
return null;
}
$inverseList[] = self::FizzBuzz[
$item
];
} return $inverseList;
} /**
* 搜索最短序列是否存在
*
* @param array $list
* 待求序列
* @param array $range
* 问题区间
*
*
* @return mixed
*/
public function sequence($list = [], $range = [])
{
$this->init($list, $range, true); $sequences = $this->findSequences();
if (! $sequences) {
return 'Found no sequences.';
} $sequence = $this->findShortestSequence($sequences);
// 将最短序列序列化后返回
return range($sequence[0], $sequence[$this->listItemsCount - 1]);
} /**
* 搜索最短序列(未序列化)
*
* @param array $sequences
* 序列集合,包含最短序列
*
* @return array
*/
private function findShortestSequence($sequences)
{
// 默认第一条为最短
$shortestSequence = $sequences[0];
// 把每一个序列看做一条路径,都有对应的长度。记录最短的序列长度
$shortestSequenceLength = $sequences[0][$this->listItemsCount - 1] - $sequences[0][0];
// 为array_reduce()定义一个callback,用来搜索最短序列
$findShortestSequence = function ($shortestSequence, $currentSequence) use(&$shortestSequenceLength) {
$currentSequenceLength = $currentSequence[$this->listItemsCount - 1] - $currentSequence[0];
if ($currentSequenceLength < $shortestSequenceLength) {
$shortestSequenceLength = $currentSequenceLength;
return $currentSequence;
} else {
return $shortestSequence;
}
}; return array_reduce($sequences, $findShortestSequence, $shortestSequence);
} /**
* 从指定位置开始搜索指定项目的序列
*
* @param int $item
* 指定项目
* @param int $start
* 起始搜索位置
*
* @return int
*/
private function findItemSequenceFromPosition($item, $start)
{
if ($start % $item == 0) {
return $start;
} return $start + ($item - $start % $item);
} /**
* 从指定位置开始搜索首个序列
*
* @param int $start
* 起始搜索位置
*
* @return mixed
*/
private function findSequenceFromPosition($start)
{
$listSequence = [];
for ($i = 0; $i < $this->listItemsCount; $i ++) {
$itemSequence = $this->findItemSequenceFromPosition($this->list[$i], $start);
if ($itemSequence > $this->range[1]) {
return null;
} else {
$listSequence[] = $itemSequence;
$start = $itemSequence + 1;
}
} return $listSequence;
} /**
* 找到多个序列,其中包括最短序列
*
* @return void
*/
private function findSequences()
{
$sequences = [];
// 以第一个项为初始搜索位置在预定区间中搜索,且以第一个项为递增步长向后逐步搜索
for ($start = $this->list[0]; $start <= $this->range[1]; $start += $this->list[0]) {
// 只需找到指定位置开始的第一个序列即可
if ($sequence = $this->findSequenceFromPosition($start)) {
$sequences[] = $sequence;
}
} return $sequences;
}
}

逆FizzBuzz问题求最短序列的更多相关文章

  1. hdu 1394 zoj 1484 求旋转序列的逆序数(并归排序)

    题意:给出一序列,你可以循环移动它(就是把后面的一段移动到前面),问可以移动的并产生的最小逆序数. 求逆序可以用并归排序,复杂度为O(nlogn),但是如果每移动一次就求一次的话肯定会超时,网上题解都 ...

  2. hdu 1394 Minimum Inversion Number (裸树状数组 求逆序数 && 归并排序求逆序数)

    题目链接 题意: 给一个n个数的序列a1, a2, ..., an ,这些数的范围是0-n-1, 可以把前面m个数移动到后面去,形成新序列:a1, a2, ..., an-1, an (where m ...

  3. 动态规划求一个序列的最长回文子序列(Longest Palindromic Substring )

    1.问题描述 给定一个字符串(序列),求该序列的最长的回文子序列. 2.分析 需要理解的几个概念: ---回文 ---子序列 ---子串 http://www.cnblogs.com/LCCRNblo ...

  4. [zz]求一维序列的信息熵(香浓熵)的matlab程序实例

    对于一个二维信号,比如灰度图像,灰度值的范围是0-255,因此只要根据像素灰度值(0-255)出现的概率,就可以计算出信息熵.    但是,对于一个一维信号,比如说心电信号,数据值的范围并不是确定的, ...

  5. poj 2001:Shortest Prefixes(字典树,经典题,求最短唯一前缀)

    Shortest Prefixes Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 12731   Accepted: 544 ...

  6. 39. 求分数序列前N项和

    求分数序列前N项和 #include <stdio.h> int main() { int i, n; double numerator, denominator, item, sum, ...

  7. 20. 求阶乘序列前N项和

    求阶乘序列前N项和 #include <stdio.h> double fact(int n); int main() { int i, n; double item, sum; whil ...

  8. 19. 求平方根序列前N项和

    求平方根序列前N项和 #include <stdio.h> #include <math.h> int main() { int i, n; double item, sum; ...

  9. OpenJudge计算概论-求分数序列和

    /*======================================================================== 求分数序列和 总时间限制: 1000ms 内存限制 ...

随机推荐

  1. Odoo:全球第一免费开源ERP库龄表的简单实现方法(无需二开)

    问题背景 希望查看库龄超过30天的货物,该如何实现?此种简单数据查询需要二开吗? 解决方案 方法一:Stock Quant列表视图增加过滤器 <filter string="库龄超30 ...

  2. 图像的膨胀与腐蚀——OpenCV与C++的具体实现

    目录 1. 膨胀与腐蚀的原理 2. 膨胀的具体实现 1) OpenCV实现 2) C/C++实现 3) 验证与结果 3. 腐蚀的具体实现 1. 膨胀与腐蚀的原理 膨胀与腐蚀是数学形态学在图像处理中最基 ...

  3. NET4.6下的UTC时间转换

    int UTCSecond = (int)((DateTimeOffset)DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)).ToUnix ...

  4. 一个字符带下滑线的EditText

    效果样式: 这个比较特别的editText是公司的一个新的需求,我也是在网上找了一下,然后看到了一篇博客然后修改成自己需要的样式.这种一般的思路就是在onDraw()方法绘制editText的特别的样 ...

  5. Java日期的一些基本处理

    今天工作中用到一些日期的处理.这里做一点浅显的整理. 1.日期的加减: 日期加减一般用到Calendar这个类比较好.这样不用处理12月加一个月和28.30.31.加一天等问题 String last ...

  6. SQL Server含逗号分隔的数据匹配维表

    日常有时候导出数据需求时,数据列会遇到带有分隔符的ID,但又需要匹配维表(如下图所示)将ID变成名称. 这种情况可以采用“分隔-匹配-合并”的方法 具体代码为: -- 准备工作1:创建事实表数据 CR ...

  7. c/c++ 右值引用,forward关键字

    c++ forward关键字 forward的由来:模板函数中的推导类型,作为另一函数的参数时,不管实参是什么类型,作为另一个参数的实参时,都变成了左值.因为C++里规定函数的形参就是左值,不过调用侧 ...

  8. 初步了解PE分析

    尝试编写代码获取PE文件的信息. 首先使用 CreateFile打开一个PE文件并返回一个用于访问该对象的handle. HANDLE CreateFile( LPCTSTR lpFileName, ...

  9. 我的第一个python web开发框架(40)——后台日志与异常处理

    后台权限和底层框架的改造终于完成了,小白也终于可以放下紧悬着的心,可以轻松一下了.这不他为了感谢老菜,又找老菜聊了起来. 小白:多谢老大的帮忙,系统终于改造完成了,可以好好放松一下了. 老菜:呵呵,对 ...

  10. css display和vertical-align 属性

    display 定义和用法 display 属性规定元素应该生成的框的类型. 实例 <html> <head> <style type="text/css&qu ...