关于Thoughtworks在拉勾的那个面试题

题目内容:

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。
 
现在,我们需要你完成一个程序来模拟这个游戏,它首先接受3个特殊数,然后输出100名学生应该报数的数或单词。比如,
 
输入
3,5,7
输出(片段)

1
2
Fizz
4
Buzz
Fizz
Whizz
8
Fizz
Buzz
11
Fizz
Fizz
Whizz
FizzBuzz
16
17
Fizz
19
Buzz 
一直到100


5.1节前,在部门内部安排大伙写了一下,很多童鞋子也写了,感觉用JAVA写出来的,没有比较理想的。后来就借这个题叫大伙坐一起,一起写了一下。代码都属临场发挥,没过多细想,应该还有很多重构空间,因为一来本来没有投简历意向,二来时间也不是很足够,所以,在此就不追求极致了。与大伙分享一下,重在思想,欢迎指正。


拿一个问题,我们首先分析问题的本质,本题的本质就是处理数字,OK.那我们就先定义一个接口:

public interface NumberHandler {

    String doHandler(Integer num);
}

我们继续分析,其实有2种处理数据的方式,一种是倍数,一种是包含关系,所以我们定义了2个具体实现类:ContainHandler,MutipluHandler。

经过简单重构以后,提取出了一个DefaultHandler。代码如下:


public abstract class DefaultHandler implements NumberHandler {
   /**输入值*/
    protected Integer value;
    /**输出单词*/
    protected String  word;

    public DefaultHandler(Integer value, String word) {
        this.value = value;
        this.word = word;
    }


    public abstract String doHandler(Integer num);
}



public class MutipluHandler extends DefaultHandler{


    public MutipluHandler(Integer value, String word) {
        super(value, word);
    }

    @Override
    public String doHandler(Integer num) {
        if(num % value==0){
            return word;
        }
        return null;
    }
}

public class ContainHandler extends DefaultHandler implements Dictatorial{


    public ContainHandler(Integer value, String word) {
        super(value, word);
    }

    @Override
    public String doHandler(Integer num) {
        if(num.toString().contains(value.toString())){
            return word;
        }
        return null;
    }


}

你是不是发现了ContainHandler还实现了一个Dictatorial接口,这个其实是后来加上去的,因为一旦满足ContainHandler处理条件,将不会被其它处理器处理,所以他是一个独占式的。因此定义了Dictatorial一个标识接口:

/**
 * Created by Administrator on 2014/5/7.
 * 独断处理,标识接口
 */
public interface Dictatorial {
}


剩下要做的就是需要一个处理器链,来挨个调用处理逻辑:

public class FilterChain {

  private static  LinkedList<NumberHandler> handlerList  = new LinkedList<NumberHandler>();

  public void addHandler(NumberHandler handler){
      if(handler instanceof  Dictatorial){
          handlerList.addFirst(handler);
      }else{
          handlerList.add(handler);
      }

  }


  public void doFilter(Integer num){
        String result  =  "";
        boolean flag = true;
        for(NumberHandler handler: handlerList){
            //独断处理
            if(!flag) break;
            String temp = handler.doHandler(num);
            if(temp != null){
                result+= temp;
                if(handler instanceof  Dictatorial){
                    flag = false;
                }
            }
        }
      System.out.println(result == "" ? num : result);
  }


}


最后就是测试类:

public class TestRunner {

    public static void main(String[] args) {

        //create resource
        FilterChain chain = new FilterChain();

        MutipluHandler h1 = new MutipluHandler(3,"Fizz");
        MutipluHandler h2 = new MutipluHandler(5,"Buzz");
        MutipluHandler h3 = new MutipluHandler(7,"Whizz");

        ContainHandler h4 = new ContainHandler(3,"Fizz");

        chain.addHandler(h4);
        chain.addHandler(h1);
        chain.addHandler(h2);
        chain.addHandler(h3);


        for(int i= 1; i<=100; i++){
            chain.doFilter(i);
        }
    }
}



其实在解决这个问题的时候,大致过程是这样:

1.定义接口

2.给出2个实现类,支持3,5,7

3.重构2个实现类,将3,5,7做到可以灵活配置。

4.定义FilterChain,先满足倍数处理

5.处理包含这种独占式处理器,定义标识接口,重构FilterChain



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Thoughtworks公司面试题——MARS ROVERS问题火星探测器 C# 实现 VS2010工程,带界面展示! 一小队机器人探测器将由NASA送上火星高原,探测器将在这个奇特的矩形高原上行驶。 用它们携带的照相机将周围的全景地势图发回到地球。每个探测器的方向和位置将由一个x,y系坐标图和一个表示地理方向的字母表示出来。为了方便导航,平原将被划分为网格状。位置坐标示例:0,0,N,表示探测器在坐标图的左下角,且面朝北方。为控制探测器,NASA会传送一串简单的字母。可能传送的字母为: 'L ', 'R '和 'M '。 'L ',和 'R '分别表示使探测器向左、向右旋转90度,但不离开他所在地点。 'M ' 表示向前开进一个网格的距离,且保持方向不变。假设以广场(高原)的直北方向为y轴的指向。 输入:首先输入的line是坐标图的右上方,假定左下方顶点的坐标为0,0。剩下的要输入的是被分布好的探测器的信息。每个探测器需要输入wo lines。第一条line 提供探测器的位置,第二条是关于这个探测器怎样进行高原探测的一系列说明。位置是由两个整数和一个区分方向的字母组成,对应了探测器的(x,y)坐标和方向。每个探测器的移动将按序完成,即后一个探测器不能在前一个探测器完成移动之前开始移动。 输出:每个探测器的输出应该为它行进到的最终位置坐标和方向。输入和输出 测试如下: 期待的输入: 5 5 1 2 N LMLMLMLMM 3 3 E MMRMMRMRRM 期待的输出 1 3 N 5 1 E

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值