FizzBuzzWhizz试题之悠然版解答

2024-01-03 01:20

本文主要是介绍FizzBuzzWhizz试题之悠然版解答,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

更多内容查看本人网站:www.tinygroup.org

试题

你是一名体育老师,在某次课距离下课还有五分钟时,你决定搞一个游戏。此时有100名学生在上课。游戏的规则是:1. 你首先说出三个不同的特殊数,要求必须是个位数,比如3、5、7。
2. 让所有学生拍成一队,然后按顺序报数。
3. 学生报数时,如果所报数字是第一个特殊数(3)的倍数,那么不能说该数字,而要说Fizz;如果所报数字是第二个特殊数(5)的倍数,那么要说Buzz;如果所报数字是第三个特殊数(7)的倍数,那么要说Whizz。
4. 学生报数时,如果所报数字同时是两个特殊数的倍数情况下,也要特殊处理,比如第一个特殊数和第二个特殊数的倍数,那么不能说该数字,而是要说FizzBuzz, 以此类推。如果同时是三个特殊数的倍数,那么要说FizzBuzzWhizz。
5. 学生报数时,如果所报数字包含了第一个特殊数,那么也不能说该数字,而是要说相应的单词,比如本例中第一个特殊数是3,那么要报13的同学应该说Fizz。如果数字中包含了第一个特殊数,那么忽略规则3和规则4,比如要报35的同学只报Fizz,不报BuzzWhizz。

乱弹

据说是直接用来面试的,呵呵,很明显,写得少不是目标,写得快也不是目标,怎么样优雅的解决此问题还是重点。

如果用一个方法解决了此问题的同学,我可以负责任的说,基本上没有啥戏了。

悠然的方法不是最快的,悠然的方法也不是最小的,因此从这两个方面与悠然比较的,悠然承认落败了。

悠然主要从扩展性及代码的优雅性方面来做一下解答,也顺便普及一下设计方面的一些心得体会,与大家分享。

思路

此题明显是搞了一堆复杂的计算规则,来扰乱程序员的心灵,干扰程序员的思路,弄乱程序员的代码,出题之人是心怀叵测呀。但是抛开现象看本质,它就是让学生报数,然后在报数的时候要遵循一系列的规则。那么,很明显是可以按规则引擎的思路来解决的。(话外音:凡是有大量if语句,case语句的多都可以归到规则引擎范畴)。

简单的分析,可以把试题中的规则进行如下分类:

1.如果是包含第一个特殊数字的,直接读出拉倒

2.如果是能被其中几个特殊数字整除的,则要读出几个特殊的数字对应的文字

3.如果不是上面两种情况,就直接读出数字

OK,原来这么简单,那就开工了

代码

/*** Created by luoguo on 2014/5/6.*/
public interface NumberReader extends Comparable<NumberReader>{/*** 返回处理优先级,优先级越高,越先执行** @return*/int getPriority();/*** 返回排它模式* 如果返回true,则自己执行过之后就结束* 如果返回false,则表示自己执行过之后,同优先级其它处理器还可以接着处理** @return*/boolean isExclusive();/*** 读数字** @param number* @return 如果有读则返回true, 没有读则返回false*/boolean read(int number);
}

设定了3个接口方法,一个返回优先级,一个返回是否是排它的,一个去读数字,如果有读过,则返回true,如果没有读过,就返回false、

另外,之所以继承了Comparable接口,是为了对规则进行排序。

为了避免后续的程序复制,因此搞一个抽象类:

/*** Created by luoguo on 2014/5/6.*/
public abstract class AbstractNumberReader implements NumberReader {private int priority;private boolean exclusive;public AbstractNumberReader(int priority, boolean exclusive) {this.priority = priority;this.exclusive = exclusive;}public int getPriority() {return priority;}public boolean isExclusive() {return exclusive;}public int compareTo(NumberReader numberReader) {if (priority > numberReader.getPriority()) {return -1;}if (priority < numberReader.getPriority()) {return 1;}return 0;}
}

上面的抽象类已经把复制的代码都写完了,接下来看实现类。

public class CommonNumberReader extends AbstractNumberReader {public CommonNumberReader() {super(0, true);}public boolean read(int number) {System.out.print(number);return true;}
}

普通的数字,其优先级为0,属于排它处理,不管3721,只要到我这里,我就一定会处理并返回true。

/*** Created by luoguo on 2014/5/6.*/
public class IncludeNumberReader extends AbstractNumberReader {private String title;private char num;public IncludeNumberReader(int num, String title) {super(2, true);this.num = (char) ('0' + num);this.title = title;}public boolean read(int number) {if (Integer.toString(number).indexOf(num) >= 0) {System.out.print(title);return true;}return false;}
}

包含数字时的处理,设定优先级为2,排它性为true,如果包含了对应的数字才处理。

/*** Created by luoguo on 2014/5/6.*/
public class MultipleNumberReader extends AbstractNumberReader {private String title;private int dividend;public MultipleNumberReader(int dividend, String title) {super(1, false);this.dividend = dividend;this.title = title;}public boolean read(int number) {if (number % dividend == 0) {System.out.print(title);return true;}return false;}
}

倍数处理器,它的优先级是1,是非排它的,只要是指定数的整数倍,就处理。

上面就写完了所有的规则。

下面是规则引擎了,呵呵,由于比较简单,没有抽象接口,直接就实现了。如果是复杂的,可能应该抽象成接口,使得引擎也可以进行调整。

/*** Created by luoguo on 2014/5/6.*/
public final class NumberReaderEngine {private List<NumberReader> numberReaders = new ArrayList<NumberReader>();public void add(NumberReader numberReader) {numberReaders.add(numberReader);}/*** 在调用readNumber之前必须调用sortNumberReader*/public void sortNumberReader() {Collections.sort(numberReaders);}public void readNumber(int number) {executeReadNumber(number);System.out.println();}private void executeReadNumber(int number) {int readPriority = -1;for (NumberReader numberReader : numberReaders) {//如果已经有读过,且当前优先级与已经读过的优先级不同,则结束if (readPriority != -1 && numberReader.getPriority() != readPriority) {return;}boolean isRead = numberReader.read(number);if (isRead) {if (numberReader.isExclusive()) {//如果是独占方式,且已读,则直接返回return;} else {readPriority = numberReader.getPriority();}}}}
}

引擎干的事情,很简单,就是添加规则,对规则进行排序,然后利用引擎对数字进行读出处理。

测试代码

/*** Created by luoguo on 2014/5/6.*/
public class TestClass {public static void main(String[] args) {//简单起见,没有添加输入功能,而是直接在程序里初始化了NumberReaderEngine numberReaderEngine=new NumberReaderEngine();numberReaderEngine.add(new CommonNumberReader());numberReaderEngine.add(new IncludeNumberReader(3,"Fizz"));numberReaderEngine.add(new MultipleNumberReader(3,"Fizz"));numberReaderEngine.add(new MultipleNumberReader(5,"Buzz"));numberReaderEngine.add(new MultipleNumberReader(7,"Whizz"));numberReaderEngine.sortNumberReader();for(int i=1;i<100;i++){numberReaderEngine.readNumber(i);}}
}

测试代码很简单,就是添加一堆规则,然后读数字就好了

运行结果

1
2
Fizz
4
Buzz
Fizz
Whizz
8
Fizz
Buzz
11
Fizz
Fizz
Whizz
FizzBuzz
16
17
Fizz
19
Buzz
FizzWhizz
22
Fizz
Fizz
Buzz
26
Fizz
Whizz
29
Fizz
Fizz
Fizz
Fizz
Fizz
Fizz
Fizz
Fizz
Fizz
Fizz
Buzz
41
FizzWhizz
Fizz
44
FizzBuzz
46
47
Fizz
Whizz
Buzz
Fizz
52
Fizz
Fizz
Buzz
Whizz
Fizz
58
59
FizzBuzz
61
62
Fizz
64
Buzz
Fizz
67
68
Fizz
BuzzWhizz
71
Fizz
Fizz
74
FizzBuzz
76
Whizz
Fizz
79
Buzz
Fizz
82
Fizz
FizzWhizz
Buzz
86
Fizz
88
89
FizzBuzz
Whizz
92
Fizz
94
Buzz
Fizz
97
Whizz
Fizz
Buzz

代码行统计

从上面看到,总共的代码行数是122行,去掉15行测试代码行,7行package声明,刚好100行。

扩展性

从上面的代码可以看到,逻辑是可以方便的自由的增加的,比如,说,不仅是第一个特殊数字,第二个第三个特殊数字,也要用同样的逻辑,只要:

numberReaderEngine.add(new IncludeNumberReader(5,"Buzz"));
numberReaderEngine.add(new IncludeNumberReader(7,"Whizz"));
就可以了,不必修改计算逻辑。当然,也可以继续增加各种各样的逻辑。

总结

对于复杂的问题,要有抽丝剥茧的能力,仔细分析、认真设计,最后可以给出一个易于维护,易于扩展,易于理解,易于维护的解决方案。

想获得源码的同学,请到下面的路径:

osc==>  /tinyframework/FizzBuzzWhizz.git


这篇关于FizzBuzzWhizz试题之悠然版解答的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/564188

相关文章

2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题

题库来源:安全生产模拟考试一点通公众号小程序 2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题是由安全生产模拟考试一点通提供,流动式起重机司机证模拟考试题库是根据流动式起重机司机最新版教材,流动式起重机司机大纲整理而成(含2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题参考答案和部分工种参考解析),掌握本资料和学校方法,考试容易。流动式起重机司机考试技

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

广东省特殊食品生产试题分享

1.食品污染是指在各种条件下,导致有毒有害物质进入到食物中,造成以下哪项发生转变的过程。(D) A.食品的安全性 B.食品的养分性 C.食品的感官性状 D.以上都是 2.食品污染物是指(D) A.生物性污染物 B.化学性污染物 C.物理性污染物 D.以上都是 3.关于菌落总数的表达,错误的选项是(A) A.反映食品对人体安康的危害程度 B.是食品清洁状态的标志 C.推测食品的耐保藏性 D.指1g检

【时时三省】c语言例题----华为机试题< 查找组成一个偶数最接近的两个素数>

山不在高,有仙则名。水不在深,有龙则灵。                                                                         ----CSDN 时时三省 1,题目 HJ60 查找组成一个偶数最接近的两个素数 描述 任意一个偶数(大于2)都可以由2个素数组成,组成偶数的2个素数有很多种情况,本题目要求输出组成指定偶数的两个

十一 面向对象技术(考点篇)试题

A ;D,D。实际答案:C;D,D 考的很偏了。UML 2.0基础结构的设计目标是定义一个元语言的核心 UML 2.0 【InfrastructureLibrary】,通过对此核心的复用,除了可以定义一个自展的UML元模型,也可以 InfrastructureLibrary UML 定义其他元模型,包括 MOF和CWM(Common Warehouse Model,公共仓库模型)。

【时时三省】c语言例题----华为机试题<等差数列>。

目录 1,题目 描述 输入描述: 输出描述: 示例1 示例2 2,代码 山不在高,有仙则名。水不在深,有龙则灵。                                                                         ----CSDN 时时三省 1,题目 HJ100 等差数列 描述 等差数列 2,5,8,11,14。。。。

ARM基础部分解答题

1. 简述ARM发生异常时,ARM核心会自动做哪些事情?从异常返回时,我们要做哪些事情? 当异常产生时, ARM core: 拷贝 CPSR 到 SPSR_<mode> 设置适当的 CPSR 位:  改变处理器状态进入 ARM 状态 改变处理器模式进入相应的异常模式 设置中断禁止位禁止相应中断 (如果需要) 保存返回地址到 LR_<mode> 设置 PC 为相应的异常向量 返回时, 异常处理

特种设备作业气瓶作业试题附答案

1.液化石油气瓶检验完毕后,逐只进行抽真空其主要目的是()。 A、提高气体的纯度 B、防止形成爆鸣气体 C、验证检验质量 D、提高充装速度 答案:B 2.无“()”监督检验钢印标记的气瓶严禁充装。 A、SC B、CC C、TS D、SS 答案:C 3.特种气瓶是指()。 A、盛装液化石油气的钢瓶 B、盛装混合气体的无缝气瓶 C、氧气瓶 D、车用气瓶 答案:D 4.天然气贮气井管不宜建在碎石、

【时时三省】c语言例题----华为机试题<等差数列>

山不在高,有仙则名。水不在深,有龙则灵。                                                                         ----CSDN 时时三省 1,题目 HJ100 等差数列 描述 等差数列 2,5,8,11,14。。。。 (从 2 开始的 3 为公差的等差数列) 输出求等差数列前n项和 数据范围: 1≤n≤

2024年【安全员-B证】新版试题及安全员-B证模拟考试

题库来源:安全生产模拟考试一点通公众号小程序 安全员-B证新版试题根据新安全员-B证考试大纲要求,安全生产模拟考试一点通将安全员-B证模拟考试试题进行汇编,组成一套安全员-B证全真模拟考试试题,学员可通过安全员-B证模拟考试全真模拟,进行安全员-B证自测。 1、【多选题】《中华人民共和国安全生产法》规定:生产经营单位不得因从业人员对本单位安全生产工作提出批评、检举、控告或者拒绝违章指挥