Countdown array isn't working

Tell us what’s happening:
I’m trying to create a countdown function, but the countdown code isn’t working. I expect my code to work as, for any value for n function should return an array pushing number n through 1

  **Your code so far**

// Only change code below this line
function countdown(n) {
let a = [];
if (n < 1) { return [] }
else if (n == 1) { a.push(n) }
else { a.shift(n); countdown(n - 1) }
return a

}
// Only change code above this line
  **Your browser information:**

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36

Challenge: Use Recursion to Create a Countdown

Link to the challenge:

function countdown(n) {
  let a = [];
  // a gets re declared every single time you
  // call your function, effectively erasing any
  // previous values
  // This won't work
  if (n < 1) {
    return []
  } else if (n == 1) {
    a.push(n)
  } else {
    a.shift(n);
    countdown(n - 1)
    // You never do anything with the output
    // of the recursive call. You need to use
    // and modify the result of the recursive call
  }
  return a
}
1 Like

thank u very much U r the most active on the forum but can u please help me with my profile lockup err in a bit more detail??

Do you have questions about the comments I added in my last post?

can u describe those comments, please?

It isn’n working even after using let

// Only change code below this line

function countdown(n) {

    let a = [];

    if (n < 1) { return a }

    else if (n == 1) {

            a.push(n);

            return a

    }

    else {

            a.push(n);

            countdown(n - 1)

    }

}

// Only change code above this line

Using let won’t change the problems I commented on.

What part of the comments I added do you understand? It’s hard for me to know what to say unless I understand what you do and don’t know.

how to modify the recursive call?

Are you asking me to do it for you? I most certainly will not do that.


You haven’t told me what you do know, so I am going to assume you do not know anything.


Variable Declaration:

In JavaScript, information is stored in variables. These variables must be declared (at least in the freeCodeCamp editor - there are ways to get JavaScript to automatically declare variables, but they are not ‘best practices’).

To simplify this initial discussion, I will stick to just using let (const is pretty similar and I will mention the differences in due time. var is a mess, so I will not mention it further.).

You declare a variable with let (or const).

let myVariable;

Often, we also set the variable to an initial value at the same time, and this is called variable definition.

let myVariable = 42;

Variable types:

Broadly speaking, JavaScript has two big types of variables you can declare, primitive variables, and objects.

There are 7 primitive types:

// Primitive data types
let myNumber = 5;             // number
let myBigInt = BigInt(5);     // bigint
let myBoolean = true;         // boolean
let myUndefined = undefined;  // undefined
let myNull = null;            // null
let myString = "Hello";       // string
let mySymbol = Symbol("key"); // symbol

Everything else is an object:

// *Some* object data types
let myObject = {name: "Bob"}; // objects
let myArray = [1, 2, 3];      // arrays

Using let vs const:

Everything we will say about let is the same for const, except for mutability, which means if and how we can change the contents of the variable.

If we declare a variable with let, the contents can be freely changed.

let myNumber = 5;
// This is permitted
myNumber = 42;

If we declare a variable with const and define it to hold a primitive value, then we cannot change that primitive value.

const myNumber = 5;
// This is *not* permitted
myNumber = 42;

If we declare a variable with const and the variable holds a reference to a non-primitive value, then we can modify the non-primitive value, but we cannot change which non-primitive value the variable refers to.

const myArray = [1, 2, 4];
// This is permitted
myArray[2] = 3;
// This is *not* permitted
myArray = [0, 0, 0, 0];

Functions:

Next, we need to understand what a function is. A function is a small piece of repeatable code.

function addTwo(arr) {
  // Add two to the end of the array
  return [...arr, 2];
}

// Test the function
let myArray = [1, 2, 3];
const myResult = addTwo(myArray);
console.log(myResult);

There are a few important things to note here:

  • We passed external into the function by using arguments. In this case, we had a single function argument, arr.
  • We passed information outside of the function by using the return keyword. In this case we passed out a new array with the contents of arr but with a 2 added to the end of the array.
  • We stored the information returned (passed out) from the function into a new variable, myResult. We need to save the return value if we want to use it later.

Variable Scope:

Now, we have to use the return keyword to pass information from inside our function to outside of our function because of variable scope.

Variables declared with let or const are only in scope (valid) within the nearest set of enclosing {}s.

for (let i=0; i<3; i++) {
  // myNumber is *in scope* here
  let myNumber = i + 10;
  console.log("myNumber = ", myNumber);
}

// myNumber is *out of scope* here
console.log("myNumber = ", myNumber);

The same thing with functions:

function addTwo(num) {
  const myNumber = num + 2;
  return myNumber;
}

const myResult = addTwo(3);
// myResult is *in scope*
console.log(myResult);
// myNumber is *out of scope*
console.log(myNumber);

Function Calls:

Now, each time we call, or invoke, or function, the function call has its own scope.

function addTwo(arr) {
  // Add two to the end of the array
  const arrWithTwo = [...arr, 2];
  console.log("Inside the function!");
  console.log("arrWithTwo = ", arrWithTwo);
  return arrWithTwo;
}

// First function call
let myArray = [1, 2, 3];
const myResult = addTwo(myArray);
console.log(myResult);

// Second function call
const mySecondResult = addTwo(myArray);
console.log(mySecondResult);

Note that each time we called the function, the contents of arrWithTwo were only based on the data from the current function call. Each function call has its own scope, so no information can be transferred between function calls without using return statements.


Your Redeclaration Problem:

You re-declare a each time you call countdown(). This means that every function call to countdown() has a brand new, empty copy of a in its scope.


Your Uncaptured return Value Problem:

You never capture the output of your function call here. This means that you are throwing away and ignoring the result of calling this function.


Path Ahead:

You should only declare the array to hold the countdown numbers once.

You should capture and use the result of your recursive function calls.

Before you can attempt to implement recursive functions, you need to be comfortable with “regular” functions. Are you comfortable with defining and calling a function? Are you comfortable defining a function that calls another function?

It is a common tendency for people to try “how about this?” random debugging. Try using different variable names, adding parentheses here, using different methods, etc. etc., without really knowing what is going on. People should stop doing this. If you don’t understand the cause of the problem, it means there’s misconception or lack of understanding.

When you post a question, it is most beneficial to the poster if the poster explains as fully as possible. Don’t just ask “why my code is not working?” Explain what you’re trying to achieve, e.g., I’m calling a function here and expecting to get the return value of such and such, and I’m trying to add x to it. But somehow, I couldn’t add x to it. I say beneficial to the poster because trying to explain oneself is a very good learning experience and the explanation from the poster allows those who reply to answer precisely and concisely.

I’m not sure at this point if it helps, but it might. So here’s the illustration on how the flow (sequence of function calls and return values) of the recursive function. If you want the answer to be [n, n-1, . . . , 1], then instead of concat in Step 2, use unshift to add a value to the front of returned array.

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.