很久没发表过文章了,今天看到一篇文章 最难面试的IT公司之ThoughtWorks代码挑战——FizzBuzzWhizz游戏(C#解法)

看到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<int, string> SpecialDictionary { get; set; } public Rule(Dictionary<int, string> specialDictionary)
{
this.SpecialDictionary = specialDictionary;
} public bool ParseNum(int num, ref string result)
{
if ((SpecialDictionary != null) && (SpecialDictionary.Count > ))
{
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<int, string> specialDictionary)
: base(specialDictionary)
{
} public override int Priority
{
get { return ; }
} protected override bool ParseNumCore(int num, ref string result)
{
foreach (var special in SpecialDictionary)
{
if (num % special.Key == )
{
result = special.Value;
return true;
}
} return false;
}
}

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

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

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

class Rule5 : Rule
{
public Rule5(Dictionary<int, string> specialDictionary)
: base(specialDictionary)
{
} public override int Priority
{
get { return ; }
} protected override bool ParseNumCore(int num, ref string result)
{
if (SpecialDictionary.Count > )
{
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<int, string> special = new Dictionary<int, string>();
special.Add(Int32.Parse(inputNums[]), "Fizz");
special.Add(Int32.Parse(inputNums[]), "Buzz");
special.Add(Int32.Parse(inputNums[]), "Whizz"); // get students nums.
int studentsCount = ;
var studentNums = Enumerable.Range(, studentsCount); // create rules to parse.
var rules = new List<Rule>()
{
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 == )
{
return specialInputs.All(input =>
{
int num = ;
return Int32.TryParse(input, out num) && (num > ) && (num < );
});
} return result;
}

一些后续思考:

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

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

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

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

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

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

ThoughtWorks代码挑战——FizzBuzzWhizz的更多相关文章

  1. ThoughtWorks代码挑战——FizzBuzzWhizz游戏 通用高速版(C/C++ & C#)

    最早看到这个题目是从@ 程序媛想事儿(Alexia) 的 最难面试的IT公司之ThoughtWorks代码挑战——FizzBuzzWhizz游戏 开始的,然后这几天陆陆续续有N个小伙伴发表了自己的文章 ...

  2. 最难面试的IT公司之ThoughtWorks代码挑战——FizzBuzzWhizz游戏

    最近互联网招聘平台拉勾网在五一期间推出个“最难面试的IT公司”代码挑战活动,评选出了5个最难面试的IT公司,即:ThoughtWorks.Google.Unisys.Rackspace.Cypress ...

  3. 最艰难的采访IT公司ThoughtWorks代码挑战——FizzBuzzWhizz游戏

    最近的互联网招聘平台拉勾网在五月推出了"最艰难的采访IT公司"码挑战活动,评选出了5个最难面试的IT公司,即:ThoughtWorks.Google.Unisys.Rackspac ...

  4. 最难面试的IT公司之ThoughtWorks代码挑战——FizzBuzzWhizz游戏(C#解法)

    原题 看到那么多人看到前面这么糟粕的代码各种不忍直视后,楼主还是把最终实现放在页首吧.             Console.WriteLine("说出三个不同的特殊数,用','隔开 &q ...

  5. 原生js代码挑战之动态添加双色球

    var ballArr = []; //存放已有的红球,用来排除重复和排序window.onload = function(){ var btn = document.createElement(&q ...

  6. 关于今天很热的--FizzBuzzWhizz

    今天早上到现在看到了3篇关于FizzBuzzWhizz的问题,第一篇是@程序媛想事儿(Alexia)[最难面试的IT公司之ThoughtWorks代码挑战--FizzBuzzWhizz游戏]其实题目不 ...

  7. 2014年5月份第1周51Aspx源码发布详情

    郑州某高校学生考评系统源码  2014-5-5 [VS2008]功能介绍:   1.用户角色有部主任.教师.学生等.   2.可添加班级考评项目.学生考评项目.   3.可指定学生对班级.学生某考评项 ...

  8. 编译器是如何实现32位整型的常量整数除法优化的?[C/C++]

    引子 在我之前的一篇文章[ ThoughtWorks代码挑战——FizzBuzzWhizz游戏 通用高速版(C/C++ & C#) ]里曾经提到过编译器在处理除数为常数的除法时,是有优化的,今 ...

  9. ThoughtWorks 面试备忘录

    ThoughtWorks 面试备忘录 前言 前段时间 ThoughtWorks 在网上和拉勾网合作搞了一次网络招聘,名为抛弃简历!让代码说话!,可谓赚足了眼球,很多程序猿纷纷摩拳擦掌.踊跃提交代码,在 ...

随机推荐

  1. 【Java EE 学习 70 下】【数据采集系统第二天】【Action中User注入】【设计调查页面】【Action中模型赋值问题】【编辑调查】

    一.Action中User注入问题 Action中可能会经常用到已经登陆的User对象,如果每次都从Session中拿会显得非常繁琐.可以想一种方法,当Action想要获取User对象的时候直接使用, ...

  2. 剑指Offer-【面试题05:从头到尾打印链表】

    package com.cxz.question5; import java.util.Stack; /* * 输入个链表的头结点,从尾到头反过来打印出每个结点的值. * */ public clas ...

  3. Windows下用tree命令生成目录树

    有时候我们想为某个目录制作一个文档结构图,在Windows上,我们知道是使用tree命令. 但是,默认情况下tree只显示子目录名,而不显示子目录里的文件名,需要加上/F参数才能显示完整的文件名.   ...

  4. 开发常用技巧之css字体编码

    简介: 当我们写css时,通常需要设置字体名称,我们可以直接写中文,这样没错,但是文件编码为GB2312.UTF-8等不匹配将会出现乱码.因此将中文字体名称转为unicode编码来避免出现这些错误. ...

  5. Maven 命令

    win7环境下,Maven跳过测试编译项目的命令: 首先,在cmd环境下执行cd命令移动到需要编译的项目的home目录,然后执行命令:mvn    install -Dmaven.test.skip= ...

  6. Xcode 突然有部分文件不显示

    今天突然Xcode抽风了,突然我的项目中的文件好多不显示出来,本地文件夹都有,见鬼了..... 真心坑死了,于是乎就找度娘了,果然被我发现了 看见这个蓝色小时钟没呀,就是他在捣鬼,我点击一下变成灰色就 ...

  7. ODAC (odp.net) 从开发到部署

    2013-09-30 16:08 4097人阅读 评论(0) 收藏 举报  分类: Oracle(10)  版权声明:本文为博主原创文章,未经博主允许不得转载. 1. 确定你开发机和服务器的操作系统是 ...

  8. SOAPUI使用教程-REST Service Mocking

    REST服务模拟 REST服务模拟功能允许您创建一个REST服务模拟器-MockService . 好处 RESTMockServices可用于例如: Web服务的原型 ——几秒内从请求生成一个完整的 ...

  9. 【转】Oracle 执行计划(Explain Plan) 说明

    转自:http://blog.chinaunix.net/uid-21187846-id-3022916.html       如果要分析某条SQL的性能问题,通常我们要先看SQL的执行计划,看看SQ ...

  10. linux kernel elv_queue_empty野指针访问内核故障定位与解决

    1. 故障描述 故障操作步骤: 单板上插了一个U盘,出问题前正在通过FTP往单板上拷贝文件,拷贝的过程中单板自动重启. 故障现象: Entering kdb (current=0xc000000594 ...