问题
I just came home from a job interview, and the interviewer asked me to write a program:
It should, count from 1 to 100, and print...
If it was multiple of 3, "ping"
If it was multiple of 5, "pong"
Else, print the number.
If it was multiple of 3 AND 5 (like 15), it should print "ping" and "pong".
I chose Javascript, and came up with this:
for (x=1; x <= 100; x++){
if( x % 3 == 0 ){
write("ping")
}
if( x % 5 == 0 ){
write("pong")
}
if( ( x % 3 != 0 ) && ( x % 5 != 0 ) ){
write(x)
}
}
Actualy, I left very unhappy with my solution, but I can't figure out a better one.
Does anyone knows a better way to do that? It's checking twice, I didn't like it. I ran some tests here at home, without success, this is the only one that returns the correct answer...
回答1:
Your solution is quite satisfactory IMHO. Tough, as half numbers are not multiple of 3 nor 5, I'd start the other way around:
for (var x=1; x <= 100; x++){
if( x % 3 && x % 5 ) {
document.write(x);
} else {
if( x % 3 == 0 ) {
document.write("ping");
}
if( x % 5 == 0 ) {
document.write("pong");
}
}
document.write('<br>'); //line breaks to enhance output readability
}
Fiddle
Also, note that any number other than 0
and NaN
are truthy values, so I've removed the unnecessary != 0
and some pairs of parenthesis.
Here's another version, it doesn't make the same modulus operation twice but needs to store a variable:
for (var x=1; x <= 100; x++) {
var skip = 0;
if (x % 3 == 0) {
document.write('ping');
skip = 1;
}
if (x % 5 == 0) {
document.write('pong');
skip = 1;
}
if (!skip) {
document.write(x);
}
document.write('<br>'); //line breaks to enhance output readability
}
Fiddle
回答2:
Here's my one-liner:
for(var x=1;x<101;x++)document.write((((x%3?'':'ping')+(x%5?'':'pong'))||x)+'<br>');
I'm using ternary operators to return either an empty string or 'ping'/'pong'
, concatenating the result of these operators, then doing an OR (if the number is neither divisible by 3 or 5, the result of the concatenation is ''
which is FALSEY in javascript). When both cases are true, the result of the concatenation is 'pingpong'
.
So basically it comes down to
'' || x // returns x
'ping' || x // returns 'ping'
'pong' || x // returns 'pong'
'pingpong' || x // returns 'pingpong'
回答3:
The best solution I came up with is this one:
for (var i = 1; i <= 100; i++) {
var message = '';
if (i%3 === 0) message += 'ping';
if (i%5 === 0) message += 'pong';
console.log(message || i);
}
回答4:
Here's a solution which allows for a dynamic list of multiples without adding more conditionals.
// List of outputs
var outputs = [
{mult: 3, str: 'ping'},
{mult: 5, str: 'pong'}
// {mult: 10, str: 'play'} ex: [30] => 'pingpongplay'
];
// Loop 100 times
for (var i = 1, j = 100; i <= j; i += 1) {
// Set empty vars
var result, string = '';
// Loop through the listed output objects
outputs.forEach(function (output) {
// If listed multiple, concat string
if (i % output.mult === 0) {
string += output.str;
}
});
// Set result
if (string.length) {
result = string;
} else {
result = i;
}
// print result
document.body.innerHTML += result + '<br>';
}
And as a function which passes jslint:
/*jslint browser: true */
var printOutputs = function (array, iterations) {
'use strict';
var i = 1;
var outputResults = function (arr, idx) {
var result;
var str = '';
arr.forEach(function (item) {
if (idx % item.mult === 0) {
str += item.str;
}
});
if (str.length) {
result = str;
} else {
result = idx;
}
return result;
};
while (i < iterations) {
document.body.innerHTML += outputResults(array, i) + '<br>';
i += 1;
}
};
var outputs = [
{mult: 3, str: 'ping'},
{mult: 5, str: 'pong'}
];
printOutputs(outputs, 100);
And for fun, a minified ES6 version:
const pO=(arr,itr)=>{let i=1,o=(a,idx)=>{let r,s='';a.map(v=>{if(idx%v.mult===0)s+=v.str});s.length?r=s:r=idx;return r};while(i<itr){document.body.innerHTML+=`${o(arr,i)}<br>`;i++}};
pO([{mult:3,str:'ping'},{mult:5,str:'pong'}], 100);
回答5:
I wrote a few variations on this (using fizz
and buzz
) as a benchmark to consider different ways of iterating over conditional logic.
while
won again:
// Iterate using a recursive function
// firing a callback once per iteration
function f(s,n) {
if(++n >= 102) return;
s === '' ? console.log(n-1) : console.log(s);
!!(n % 3)
? !!(n % 5)
? f('',n) : f('Buzz',n)
: !!(n % 5)
? f('Fizz',n) : f('FizzBuzz',n);
}
// Iterate using a `while` loop
// firing a callback after satisfying a condition
function b(n) {
var i = n;
$:
while(++i) {
if(i % 3)
if(i % 5)
console.log(i);
else
console.log('Buzz');
else if(i % 5)
console.log('Fizz');
else
console.log('FizzBuzz');
if(i >= 100)
break $;
}
return;
}
// Iterate using a `for` loop
// firing a callback once per iteration
function F(n) {
var i = n, f = 'Fizz', b = 'Buzz', o = '';
for (; i <= 100; i++) {
o = !(i % 3)
? !(i % 5)
? f + b : f
: !(i % 5)
? b : i;
console.log(o);
}
return;
}
// Iterate using a `for` loop
// firing a callback after satisfying a condition
function B(n) {
var i = n;
var fiz = 'Fizz';
var buz = 'Buzz';
for(; i <= 100; i++)
if(!(i % 3))
if(!(i % 5))
console.log(fiz + buz);
else
console.log(fiz);
else if(!(i % 5))
console.log(buz);
else
console.log(i);
return;
}
f('', 1); // recursive
b(0); // `while`
F(1); // `for`
B(1); // `for
Benchmark: http://jsperf.com/fizzbuzz-mod
回答6:
//create a for loop to count from 0 to 100
for (let num = 0; num <= 100; num++){
/**As the count increments, if the number is divisible by 3 and divisible by 5
print FizzBuzz, I have concatenated the number with FizzBuzz for clarity.
Use % instead of \ to ensure it returns an int instead of float.**/
if ((0 == num % 3) && (0 == num % 5)){
console.log ("FizzBuzz" + " " + num);
//otherwise, if the number is divisible by 5 print Buzz
} else if (0 == num % 5) {
console.log("Buzz" + " " + num);
//Also, if the number is divisible by 3 print Fizz
} else if (0 == num % 3){
console.log("fizz" + " " + num);
} else {
//meanwhile, still print all the numbers that don't satisfy the conditions above
console.log (num);
}
}
回答7:
for( int number = 1 ; number < 100 ; number++ )
{
boolean shouldPrintNumber = true;
System.out.println("\n");
if( (number%3) == 0 )
{
System.out.print("ping");
shouldPrintNumber = false;
}
if( (number%5) == 0 )
{
System.out.print("pong");
shouldPrintNumber = false;
}
if( shouldPrintNumber )
{
System.out.print( number );
}
}
回答8:
for var a = 1; a <= 100 ; a++
{
if a % 3 == 0 && a % 5 == 0
{
println("Fizzbuzz")
continue
}
if a % 5 == 0
{
println("Buzz")
continue
}
if a % 3 == 0
{
println("Fizz")
continue
}
else
{
println(a)
}
}
回答9:
To get rid of the last condition you might use continue
:
for (x=1; x <= 100; x++){
if( x % 3 == 0 ){
write("ping")
continue
}
if( x % 5 == 0 ){
write("pong")
continue
}
write(x)
}
来源:https://stackoverflow.com/questions/13845437/from-1-to-100-print-ping-if-multiple-of-3-pong-if-multiple-of-5-or-else-p