From 1 to 100, print “ping” if multiple of 3, “pon

2019-02-01 13:54发布

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...

9条回答
该账号已被封号
2楼-- · 2019-02-01 14:10

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楼-- · 2019-02-01 14:13

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

查看更多
Explosion°爆炸
4楼-- · 2019-02-01 14:14

//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);
         }
      }

查看更多
放我归山
5楼-- · 2019-02-01 14:17

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);
查看更多
虎瘦雄心在
6楼-- · 2019-02-01 14:17

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)
}
查看更多
Ridiculous、
7楼-- · 2019-02-01 14:21

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

查看更多
登录 后发表回答