A while back, someone asked me in an interview to print "Hello World" in the console 50 times without using a loop.
The answer, was obviously, with recursion.
But was that the only answer?
Afterward, I start pondering... let's find out?
If you want to check it out: https://github.com/Noriller/js-console.log
I've made a repository and used jest to test if everything was working, I've also used this auxiliary function:
function Log() {
console.log("Hello World!");
}
Most were just variations of the same thing... but I did manage to make it work in some unexpected ways.
Brute forcing!
Because... why not?
Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log(); Log();
Using Loops
Ok, the interviewer said no loops, but here we can use...
// The classic For Loop
for (let i = 0; i < 50; i++) {
Log();
}
// Do While Loop
let i = 0;
do {
Log();
i++;
} while (i < 50);
// While Loop
let i = 0;
while (i < 50) {
Log();
i++;
}
// For Of
const arr = Array(50).fill(Log);
for (let x of arr) {
x();
}
// For In
const arr = Array(50).fill(Log);
const obj = Object.assign({}, arr);
for (let x in obj) {
obj[x]();
}
Using Javascript Array Functions
const arr = Array(50).fill(Log);
// Multiple Array Funcions
// Basically the same way...
arr.forEach(el => el());
arr.map(el => el());
arr.filter(el => el());
arr.find(el => el());
arr.findIndex(el => el());
arr.reduce((acc, el) => el(), {});
arr.reduceRight((acc, el) => el(), {});
arr.every(el => !el());
arr.some(el => el());
Going a little crazy on the Array methods:
// Array From (basically a map)
Array.from(
Array(50).fill(Log),
x => x()
);
const arr = Array(50).fill(Log);
// Pop
while (arr.length > 0) {
arr.pop()();
}
// Shift
while (arr.length > 0) {
arr.shift()();
}
// Splice
while (arr.length > 0) {
arr.splice(0, 1)[0]();
}
Using Recursion
// Classic Recursion
function Log50(num = 1) {
if (num > 50) return;
Log();
Log50(num + 1);
}
Log50();
Using Time?
// Set Interval (basically a loop)
let i = 1;
const interval = setInterval(() => {
if (i > 50) return clearInterval(interval);
i++;
Log();
}, 1000);
// Set Timeout (basically recursion)
let i = 1;
function timers() {
const timeout = setTimeout(() => {
if (i > 50) return;
i++;
Log();
clearTimeout(timeout);
timers();
}, 1000);
}
timers();
// Set Immediate (same as timeout)
let i = 1;
function timers() {
const immediate = setImmediate(() => {
if (i > 50) return;
i++;
Log();
clearImmediate(immediate);
timers();
});
}
timers();
Try...catch?
class CustomError extends Error {
constructor(...args) {
super(...args);
this.Log50();
}
Log50(num = 1) {
if (num > 50) return;
Log();
this.Log50(num + 1);
}
}
try {
throw new CustomError();
} catch (error) {
}
Spread Operator?
function* generator(num = 0) {
while (num < 50) {
num++;
yield Log();
}
}
[...generator()];
You see... the basis ends up being either a loop or a recursion... it's mostly how you call it...
But hey... can you think of another way of doing it?
If you can... leave a comment or send a PR maybe?
Cover Photo by Markus Spiske on Unsplash