博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ThoughtWorks代码挑战——FizzBuzzWhizz
阅读量:6679 次
发布时间:2019-06-25

本文共 7394 字,大约阅读时间需要 24 分钟。

很久没发表过文章了,今天看到一篇文章

看到LZ的2B青年代码,实在是惨不忍睹,故写篇文章来探讨下这类问题的一般思考。

原题:

FizzBuzzWhizz

你是一名体育老师,在某次课距离下课还有五分钟时,你决定搞一个游戏。此时有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, if , else if , if , for, [0] [1] [2]….

我们来理解下这道题:

1. 你首先说出三个不同的特殊数,要求必须是个位数,比如3、5、7。

不同的三个数,必须是个位数,这些都是验证条件,你注意到了吗?

2. 让所有学生拍成一队,然后按顺序报数。

生成顺序的数字。

3. 学生报数时,如果所报数字是第一个特殊数(3)的倍数,那么不能说该数字,而要说Fizz;如果所报数字是第二个特殊数(5)的倍数,那么要说Buzz;如果所报数字是第三个特殊数(7)的倍数,那么要说Whizz。

规则:如果是某个特殊数的倍数,输出对应的值,否则输出数字。

4. 学生报数时,如果所报数字同时是两个特殊数的倍数情况下,也要特殊处理,比如第一个特殊数和第二个特殊数的倍数,那么不能说该数字,而是要说FizzBuzz, 以此类推。如果同时是三个特殊数的倍数,那么要说FizzBuzzWhizz。

规则:如果是多个特殊数的倍数,输出所有的对应值。

5. 学生报数时,如果所报数字包含了第一个特殊数,那么也不能说该数字,而是要说相应的单词,比如本例中第一个特殊数是3,那么要报13的同学应该说Fizz。如果数字中包含了第一个特殊数,那么忽略规则3和规则4,比如要报35的同学只报Fizz,不报BuzzWhizz。

规则:如果包含第一个特殊数字,则只输出第一个特殊数字所对应的值。

 

OK,思考下我们该怎样做?。。

 

我们来抽象的理解下题目: “给你输入一堆数字,然后你根据一定的规则进行parse,然后输出parse 的结果。”

所以这道题目想考察的是你如何定义这些规则,如何应用这些规则,该如何parse呢?

 

让我们看下规则Rule

Rule,有优先级,然后可以对输入进行Parse,然后Parse又需要一个对应的字典。

所以Rule 像这样:

abstract class Rule    {        public abstract int Priority { get; }        public Dictionary
SpecialDictionary { get; set; } public Rule(Dictionary
specialDictionary) { this.SpecialDictionary = specialDictionary; } public bool ParseNum(int num, ref string result) { if ((SpecialDictionary != null) && (SpecialDictionary.Count > 0)) { return ParseNumCore(num, ref result); } else { return false; } } protected abstract bool ParseNumCore(int num, ref string result); }

 

接着Rule3: 如果是某个特殊数的倍数,输出对应的值,否则输出数字,输出数字我放到最外层去处理了,当然如果需要也可以写个Rule2.

class Rule3 : Rule    {        public Rule3(Dictionary
specialDictionary) : base(specialDictionary) { } public override int Priority { get { return 3; } } protected override bool ParseNumCore(int num, ref string result) { foreach (var special in SpecialDictionary) { if (num % special.Key == 0) { result = special.Value; return true; } } return false; } }

 

Rule4:如果是多个特殊数的倍数,输出所有的对应值。

class Rule4 : Rule    {        public Rule4(Dictionary
specialDictionary) : base(specialDictionary) { } public override int Priority { get { return 4; } } protected override bool ParseNumCore(int num, ref string result) { List
matches = new List
(); foreach (var special in SpecialDictionary) { if (num % special.Key == 0) { matches.Add(special.Value); } } if (matches.Count > 1) { result = string.Join("", matches); return true; } else { return false; } } }

 

Rule5:如果包含第一个特殊数字,则只输出第一个特殊数字所对应的值。

class Rule5 : Rule    {        public Rule5(Dictionary
specialDictionary) : base(specialDictionary) { } public override int Priority { get { return 5; } } protected override bool ParseNumCore(int num, ref string result) { if (SpecialDictionary.Count > 0) { var firstSpecial = SpecialDictionary.First(); if (num.ToString().Contains(firstSpecial.Key.ToString())) { result = firstSpecial.Value; return true; } } return false; } }

 

接下来:最重要的就是Parse 逻辑了,想一想应该怎样调用这些Rule呢(visitor ?):

foreach (var student in studentNums)                    {                        string parseResult = student.ToString();                        foreach (Rule rule in rules)                        {                            if (rule.ParseNum(student, ref parseResult))                            {                                break;                            }                        }                        Console.WriteLine(parseResult);                    }

 

下面是完整的代码:

private static void FizzBuzz()        {            bool isValidInput = false;            do            {                Console.WriteLine("please input three numbers which is units digit, use ',' division ");                string[] inputNums = Console.ReadLine().Split(',');                if (ValidSpecialInput(inputNums))                {                    isValidInput = true;                    // create special dictionary to parse the students nums.                    Dictionary
special = new Dictionary
(); special.Add(Int32.Parse(inputNums[0]), "Fizz"); special.Add(Int32.Parse(inputNums[1]), "Buzz"); special.Add(Int32.Parse(inputNums[2]), "Whizz"); // get students nums. int studentsCount = 100; var studentNums = Enumerable.Range(1, studentsCount); // create rules to parse. var rules = new List
() { new Rule5(special), new Rule4(special), new Rule3(special), }.OrderByDescending(r => r.Priority); // parse logic. foreach (var student in studentNums) { string parseResult = student.ToString(); foreach (Rule rule in rules) { if (rule.ParseNum(student, ref parseResult)) { break; } } Console.WriteLine(parseResult); } Console.ReadLine(); } else { Console.WriteLine("the input is not valid."); } } while (isValidInput == false); } private static bool ValidSpecialInput(string[] specialInputs) { bool result = false; if (specialInputs.Length == 3) { return specialInputs.All(input => { int num = 0; return Int32.TryParse(input, out num) && (num > 0) && (num < 10); }); } return result; }

 

一些后续思考:

1:如果输入的不是三个,而是4个,5个 special, 应该怎么改?

2:如果学生数量不是100个,是1000个?

3:如果有限考虑Rule3,然后是Rule4,Rule5,应该怎么改?

4:如果还有另一个限制条件:比如如果数字是素数,把对应的值按反序输出,如何处理?

5:如果输入不是数字,而是字符串,应该如何处理?

 

完整源码下载:http://files.cnblogs.com/LoveJenny/FizzBuzz.7z

转载地址:http://uhnao.baihongyu.com/

你可能感兴趣的文章
我的软考之路(八)——三大原则学会数据流图
查看>>
Grails开发环境的高速搭建
查看>>
jQuery Ajax遍历表格,填充数据,将表格中的数据一条一条拼成Jason数组
查看>>
Redis为什么这么快
查看>>
js获取宽度设置thickbox百分比
查看>>
检测输入框字数的变化 注意onpropertychange oninput onchange onkeyup区别
查看>>
arm_GPIO_简单编程例题
查看>>
codves1282 约瑟夫问题 链表 会 T
查看>>
接口调用的跨域问题
查看>>
关于乌班图18.04安装mysql不提示设置密码解决方案
查看>>
php数据类型以及运算
查看>>
npm命令
查看>>
关于实现(大)系统的一些小体会
查看>>
如何使用github创建仓库并且与本地连接
查看>>
除法(简单枚举)
查看>>
System.Web.Caching
查看>>
linux常用命令 2
查看>>
jquery中prop和attr的区别
查看>>
2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) Problem K Tournament Wins
查看>>
台州学院we are without brain 训练 计算几何
查看>>