【问题标题】:Java FizzBuzz 1 LineJava FizzBu​​zz 1 行
【发布时间】:2019-10-06 17:35:59
【问题描述】:

如何仅用一个 return 语句完成FizzBuzz 练习在 Codingbat 中

我上次用来解决问题的代码是:

public String[] fizzBuzz(int start, int end) {
  String[] a = new String[end - start];
  for(int i = start; i < end; i++) a[i - start] = i % 15 == 0 ? "FizzBuzz" : i % 3 == 0 ? "Fizz" : i % 5 == 0 ? "Buzz" : String.valueOf(i);
  return a;
}

我的目标是编写如下所示的代码:

public String[] fizzBuzz(int start, int end) {
  return foo;
}

问题

这是著名的 FizzBu​​zz 问题的稍微困难的版本,有时作为求职面试的第一个问题。 (另请参阅:FizzBuzz Code。)考虑从 start 开始到但不包括 end 的一系列数字,例如 start=1 和 end=5给出系列 1、2、3、4。返回一个新的 String[] 数组,其中包含这些数字的字符串形式,除了 3 的倍数,使用“Fizz”代替数字,对于 5 的倍数使用“Buzz”,对于 3 和 5 的倍数,请使用“FizzBu​​zz”。在 Java 中,String.valueOf(xxx) 将使 String 形式为 int 或其他类型。这个版本比通常的版本稍微复杂一点,因为你必须分配和索引到一个数组中而不是仅仅打印,我们改变开始/结束而不是总是做 1..100。


测试用例

fizzBuzz(1, 6) → ["1", "2", "Fizz", "4", "Buzz"]
fizzBuzz(1, 8) → ["1", "2", "Fizz", "4", "Buzz", "Fizz", "7"]
fizzBuzz(1, 11) → ["1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz"]
fizzBuzz(1, 16) → ["1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", "13", "14", "FizzBuzz"]
fizzBuzz(1, 4) → ["1", "2", "Fizz"]
fizzBuzz(1, 2) → ["1"]
fizzBuzz(50, 56) → ["Buzz", "Fizz", "52", "53", "Fizz", "Buzz"]
fizzBuzz(15, 17) → ["FizzBuzz", "16"]
fizzBuzz(30, 36) → ["FizzBuzz", "31", "32", "Fizz", "34", "Buzz"]
fizzBuzz(1000, 1006) → ["Buzz", "1001", "Fizz", "1003", "1004", "FizzBuzz"]
fizzBuzz(99, 102) → ["Fizz", "Buzz", "101"]
fizzBuzz(14, 20) → ["14", "FizzBuzz", "16", "17", "Fizz", "19"]

【问题讨论】:

标签: java fizzbuzz


【解决方案1】:

不确定为什么要在单个 return 语句中执行此操作,但仍然可以这样做:

return IntStream.range(start, end)
                .mapToObj(i -> i % 15 == 0 ? "FizzBuzz" : 
                          i % 3 == 0 ? "Fizz" : i % 5 == 0 ? "Buzz" : String.valueOf(i))
                .toArray(String[]::new);
  1. IntStream.range 以 1 的增量步长返回从 start(含)到 end(不含)的顺序排序的 IntStream,这完全符合您的命令式方法的方式。
  2. mapToObj 使我们能够将 IntStream 转换为 Stream&lt;String&gt;
  3. toArray 使我们能够将 Stream&lt;String&gt; 转换为 String[] 以返回。

您可以阅读有关IntStream API here 的更多信息。

【讨论】:

  • 我使用了一些非常接近的东西来寻求答案。唯一的问题是在 Codingbat 中,这会报错:cannot find symbol IntStream
  • @pythx 似乎codebat 不允许您使用jdk8 的功能。在JDK8 之前,没有其他方法可以将您的代码放入单个return 语句至少据我所知
【解决方案2】:

在没有任何 Java 8 特性的情况下,我能想象的唯一方法是将数组转换为字符串,以及将字符串数组的字符串转换为带有一些非常实用的正则表达式的字符串数组。但我想解决方案无论如何都不应该是漂亮的。但是,它通过了所有测试用例,因此它实现了通过测试驱动开发可以实现的所有目标...

永远不要写任何与现实生活中相似的东西!

import java.util.Arrays;

public class OneLineFizzBuzz
{
    public static void main(String[] args)
    {
        OneLineFizzBuzz f = new OneLineFizzBuzz();
        String[] result = f.fizzBuzz(1000, 1006);
        System.out.println(Arrays.toString(result));

        check(f.fizzBuzz(1, 6), new String[]{"1", "2", "Fizz", "4", "Buzz"});
        check(f.fizzBuzz(1, 8), new String[]{"1", "2", "Fizz", "4", "Buzz", "Fizz", "7"});
        check(f.fizzBuzz(1, 11), new String[]{"1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz"});
        check(f.fizzBuzz(1, 16), new String[]{"1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", "13", "14", "FizzBuzz"});
        check(f.fizzBuzz(1, 4), new String[]{"1", "2", "Fizz"});
        check(f.fizzBuzz(1, 2), new String[]{"1"});
        check(f.fizzBuzz(50, 56), new String[]{"Buzz", "Fizz", "52", "53", "Fizz", "Buzz"});
        check(f.fizzBuzz(15, 17), new String[]{"FizzBuzz", "16"});
        check(f.fizzBuzz(30, 36), new String[]{"FizzBuzz", "31", "32", "Fizz", "34", "Buzz"});
        check(f.fizzBuzz(1000, 1006), new String[]{"Buzz", "1001", "Fizz", "1003", "1004", "FizzBuzz"});
        check(f.fizzBuzz(99, 102), new String[]{"Fizz", "Buzz", "101"});
        check(f.fizzBuzz(14, 20), new String[]{"14", "FizzBuzz", "16", "17", "Fizz", "19"});        
    }
    private static void check(String[] fizzBuzz, String[] strings)
    {
        boolean passed = Arrays.equals(fizzBuzz, strings);
        System.out.println(Arrays.toString(fizzBuzz) + " passed? " + passed);
        if (!passed)
        {
            System.out.println("Whoopsie...");
        }
    }

    public String[] fizzBuzz(int start, int end)
    {
        return (start == end ? ""
            : (start % 15 == 0 ? "FizzBuzz"
                : start % 3 == 0 ? "Fizz"
                    : start % 5 == 0 ? "Buzz" : String.valueOf(start))
                + Arrays.toString(fizzBuzz(start + 1, end)))
                    .replaceAll("\\]", "").split("\\[|,\\s*");
    }
}

【讨论】:

  • 不幸的是,在 Codingbat 中,这给出了一个错误:Bad codeCommon problems: code should not use println or class or static or exceptions
  • @pythx 不确定你做了什么,但我只是将我的答案中的代码复制到 CodingBat 的输入字段中,按下“Go”,它会显示一个包含测试用例的表格,全部通过。
【解决方案3】:
  1. 确保您有 JDK 8(否则此代码将不起作用)

  2. 使用 IntStream.range 可以生成整数。一旦你有了一堆数字,你就必须相应地映射它们。 (在这种情况下,我们必须将它们映射到 String [] 并检查多个 3、多个 5 以及多个 3 和 5) 现在,对于其余的数字,我们可以使用 String.valueof() 将它们添加到数组中。

注意:确保将 FIZZBUZZ 放在顶部,因为它是一个 if 语句,只有其中一个被执行。

    public static String[] foo(int start, int end) {
        return IntStream.range(start, end).mapToObj(i-> ( 
        i%5==0 && i%3==0 ) ? "FIZZBUZZ": 
        i%3==0 ? "FIZZ":
        i%5==0 ? "BUZZ": 
        String.valueOf(i)).toArray(String[]::new);
}

【讨论】:

  • 这应该正常工作,但不幸的是,Codingbat 不支持 IntStream。
  • @pythx 是的,它没有,如果您在 codingbat 中看到了这个问题,他们不会要求单行代码。这就是你提出的挑战。干杯队友!
猜你喜欢
  • 2016-01-15
  • 1970-01-01
  • 2012-02-21
  • 2018-07-18
  • 2012-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-13
相关资源
最近更新 更多