ThoughtWorks代码挑战——FizzBuzzWhizz
很久沒發表過文章了,今天看到一篇文章?最難面試的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 > 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<int, string> 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<int, string> specialDictionary): base(specialDictionary){}public override int Priority{get { return 4; }}protected override bool ParseNumCore(int num, ref string result){List<string> matches = new List<string>();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<int, string> 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<int, string> special = new Dictionary<int, string>();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<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 == 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:如果輸入不是數字,而是字符串,應該如何處理?
本文轉自LoveJenny博客園博客,原文鏈接:http://www.cnblogs.com/LoveJenny/p/3706459.html,如需轉載請自行聯系原作者 與50位技術專家面對面20年技術見證,附贈技術全景圖
總結
以上是生活随笔為你收集整理的ThoughtWorks代码挑战——FizzBuzzWhizz的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Varnish加速Web
- 下一篇: LeakCanary: 让内存泄露无所遁