Java FizzBuzz 1 行
Java FizzBuzz 1 Line
如何仅用 return 语句完成 Codingbat 中的 FizzBuzz 练习 ?
我上次使用的解决问题的代码是:
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;
}
问题
This is slightly more difficult version of the famous FizzBuzz problem which is sometimes given as a first problem for job interviews. (See also: FizzBuzz Code.) Consider the series of numbers beginning at start and running up to but not including end, so for example start=1 and end=5 gives the series 1, 2, 3, 4. Return a new String[]
array containing the string form of these numbers, except for multiples of 3, use "Fizz" instead of the number, for multiples of 5 use "Buzz", and for multiples of both 3 and 5 use "FizzBuzz". In Java, String.valueOf(xxx)
will make the String form of an int or other type. This version is a little more complicated than the usual version since you have to allocate and index into an array instead of just printing, and we vary the start/end instead of just always doing 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"]
不确定为什么要在单个 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);
IntStream.range
returns 从 start
(含)到 end
(不含)的顺序 IntStream
,递增步长为 1,正好符合以您命令式的方式。
mapToObj
使我们能够将 IntStream
转换为 Stream<String>
.
toArray
使我们能够将 Stream<String>
转换为 String[]
for return.
您可以阅读有关 IntStream
API here 的更多信息。
确保你有 JDK 8(否则此代码将无法运行)
使用IntStream.range你可以生成整数。一旦你有了一堆数字,你就必须相应地映射它们。 (在这种情况下,我们必须将它们映射到 String [] 并检查多个 3、多个 5 以及多个 3 & 5)
现在,对于其余的数字,我们可以使用 String.valueof() 将它们添加到数组中。
N.B:确保将 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);
}
在没有任何 Java8 功能的情况下,我能想到的唯一方法涉及一些丑陋的数组到字符串的转换,以及字符串数组的字符串到字符串数组的一些非常...实用的正则表达式。但我想这个解决方案无论如何都不应该是完美的。但是,它通过了所有测试用例,因此它实现了测试驱动开发可以实现的所有目标...
永远不要在现实生活中写任何类似的东西!
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*");
}
}
如何仅用 return 语句完成 Codingbat 中的 FizzBuzz 练习 ?
我上次使用的解决问题的代码是:
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;
}
问题
This is slightly more difficult version of the famous FizzBuzz problem which is sometimes given as a first problem for job interviews. (See also: FizzBuzz Code.) Consider the series of numbers beginning at start and running up to but not including end, so for example start=1 and end=5 gives the series 1, 2, 3, 4. Return a new
String[]
array containing the string form of these numbers, except for multiples of 3, use "Fizz" instead of the number, for multiples of 5 use "Buzz", and for multiples of both 3 and 5 use "FizzBuzz". In Java,String.valueOf(xxx)
will make the String form of an int or other type. This version is a little more complicated than the usual version since you have to allocate and index into an array instead of just printing, and we vary the start/end instead of just always doing 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"]
不确定为什么要在单个 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);
IntStream.range
returns 从start
(含)到end
(不含)的顺序IntStream
,递增步长为 1,正好符合以您命令式的方式。mapToObj
使我们能够将IntStream
转换为Stream<String>
.toArray
使我们能够将Stream<String>
转换为String[]
for return.
您可以阅读有关 IntStream
API here 的更多信息。
确保你有 JDK 8(否则此代码将无法运行)
使用IntStream.range你可以生成整数。一旦你有了一堆数字,你就必须相应地映射它们。 (在这种情况下,我们必须将它们映射到 String [] 并检查多个 3、多个 5 以及多个 3 & 5) 现在,对于其余的数字,我们可以使用 String.valueof() 将它们添加到数组中。
N.B:确保将 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);
}
在没有任何 Java8 功能的情况下,我能想到的唯一方法涉及一些丑陋的数组到字符串的转换,以及字符串数组的字符串到字符串数组的一些非常...实用的正则表达式。但我想这个解决方案无论如何都不应该是完美的。但是,它通过了所有测试用例,因此它实现了测试驱动开发可以实现的所有目标...
永远不要在现实生活中写任何类似的东西!
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*");
}
}