Chapter 4 - Exercises

Hi @daz3d,

Great stuff :+1:

I think it just depends on whether you need to use the return value or not, or leave yourself the option to use it in future development (although it would be just as easy, and probably more straightforward to add it in later if you need it). I think it’s probably a personal thing too. Personally, I don’t like to leave any loose ends, and I also think it’s clearer to another developer reading my code if the return statement isn’t there when I’m not using a return value from that function.

Some functions which generate side effects simply don’t return any value (I think :thinking:)… and having had another quick look at your doIt() function, I suspect that this may be the case here. If the function doesn’t return any value, then I think it’s pointless to include the return statement, although I’m definitely prepared to hear other points of view on this :slightly_smiling_face:

I’ve tested this, and your latest version seems to work for me with all scenarios: all negative numbers, mix of negative and positive, reverse ranges etc etc…

Anyway, the point I’d make here is that it’s always good to test as many different scenarios as possible to avoid problems and bugs later on…and then also remain open to others being found which you may need to update and adapt your program for.

1 Like

Hi @Christophe_H & @daz3d,

Good idea, and normally you’d be spot on, but in this particular program a default step parameter of step = 1 won’t work. Always test your ideas to see if they do actually work, as you’d be surprised how many exceptions there can often be depending on other program functionality :wink:

In this case, it won’t work, because if no step value is entered by the user, the doIt() function still converts that undefined value to a number using Number(). This passes a step value of NaN to the function range(), and so a default step parameter of step = 1 will never be triggered (it’s only triggered by undefined).

However, the condition !step solves this because !NaN evaluates to true.

1 Like

very insightful. am learning so much on this course. thank you.

1 Like

Test reverse array

function reverseArrayInPlace(arrValue) {
let final = arrValue.length - 1;
for (let i = 0; i < final / 2; i++) {
let x = arrValue[i];
let y = arrValue[final - i];
arrValue[i] = y;
arrValue[final - i] = x;
}
}

1 Like

@jon_m @Mauro This explanation really helped visualize what the code is functionally doing, this style with some graphic animations like people on a bus would be amazing to help conceptualize these more abstract logic for us plebs and dreamers :upside_down_face: :partying_face:

  1. Iterate backwards ( i-- ) from the last element of orginalArray ( let i = array.length -1; ) using the .push() array method to push the value of the last element to the BACK of newArray (the first element pushed to the back will end up in the front after all the other elements have been pushed to the back one by one as well).
    OR
  2. Iterate forwards ( i++ ) from the first element of orginalArray ( let i = 0; ) using the .unshift() array method to push the value of the first element to the FRONT of newArray (the first element pushed to the front will end up at the end after all the other elements have been pushed to the front one by one as well).
1 Like

I modified the first program a bit for the sake of experimentation, but I don’t understand my own modification. The program does what I wanted it to do, but the input type “number” doesn’t seem to work. I tried many things to make it work, and I also searched the internet far and wide, but my unsatisfactory conclusion is that the value type that the html input function produces is always a string—regardless of whether I specify the type to be “number” or “text”. In order to convert the input into an actual number, I multiplied by 1. It works fine, but why is the type specification not sufficient to produce an integer input value? This seems odd to me.

<html>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js">
  </script>
  <body>
      <h3> Enter the Summation Parameters </h3>
      <input id="lowerLimitID" type="number" placeholder="enter lower limit"/>
      <br>
      <input id="numberOfValuesID" type="number" placeholder="enter number of values"/>
      <br>
      <input id="summationStepID" type="number" placeholder="enter step value"/>
      <br>
      <button onclick="sumOverRange()">Submit</button>
      <script>
          function sumOverRange(){
             var lowerLimit=1*$("#lowerLimitID").val();
             var numberOfValues=1*$("#numberOfValuesID").val();
             var summationStep=1*$("#summationStepID").val();
             var sumString="";
             var sum=0;
             function formSum(lowerL,numberOfV,summationS){
                var upperLimit=lowerL+(numberOfV-1)*summationS;
                for(n=lowerL; n<=upperLimit; n+=summationS){
                   sum+=n;
                   if(n==upperLimit)
                      sumString+=n;
                   else
                      sumString+=n+"+";
                 }
              }
              formSum(lowerLimit,numberOfValues,summationStep);
              document.write(sumString+" = "+sum);
           }
       </script>
    </body>
 </html>

And here is my array-reversal program (with user input for practice):

<html>
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js">
   </script>
   <body>
      <h3>Reversing an Array</h3>
      <input id="arraySizeID" type="number" placeholder="number of array elements"/>
      <button onclick="setArraySize()">Submit</button>
      <nput id="arrayElementID" type="text" placeholder="array element with index 0"/>
      <button onclick="inputAndReverse()">Submit</button>
      <script>
         var count=0;
         var a=[];
         var b=[];
         var arraySize=0;
         function setArraySize(){
            arraySize=1*$("#arraySizeID").val();
         }
         function inputAndReverse(){
            count++;
            if(count<=arraySize){
               a.push($("#arrayElementID").val());
               $("#arrayElementID").val("");
               $("#arrayElementID").attr("placeholder","array element with index "+count);
            }
            if(count==arraySize){
               document.write("a=["+a+"] <br>");
               function reverseA( c){
                   for(n=0;n<=Math.floor(arraySize/2-1);n++){
                      var saveElement=c[n];
                      c[n]=c[arraySize-1-n];
                      c[arraySize-1-n]=saveElement;
                    }
                    return c;
                 }
                 document.write("reversal of a=["+reverseA(a)+"] <br>");
                 function createB( c){
                    for(n=0;n<=arraySize-1;n++)
                       b[n]=c[arraySize-1-n];
                     return c;
                 }
                 document.write("b=["+createB(a)+"]");
             }
          }
      </script>
   </body>
</html>

thank you very much for the help again, I appreciate it a lot :grin:

1 Like

Hi @Christophe_H,

Sorry for the delay in providing you with some feedback.

You’ve made an excellent attempt at this, and I can see that you’ve really thought hard about your alternative method :+1:

Here are a few comments…

  • Always include your initial function call in the code you post, so that if you’ve used a different approach to the suggested one in the exercise, it is easier for us to run your program to test it. For example, as a result of the additional console.log statements you’ve included in your functions, it took me a while to work out that we need to execute your program with just…
    // these are just example function calls to test different scenarios
    range(1, 10);       // => 55
    range(3, 16, 3);    // => 45
    range(5, 2);        // => 14
    range(5, 2, -1);    // => 14
    range(39, 11, -9);  // => 102

    // instead of

    console.log(range(1, 10));
    console.log(sum(range(1, 10)));        

    console.log(range(3, 16, 3));
    console.log(sum(range(3, 16, 3)));     

    console.log(range(5, 2));
    console.log(sum(range(5, 2)));          
    
    // etc.
  • You can remove the  return ans   statement at the end of your sum function, because it doesn’t do anything.

  • Your program currently handles all scenarios successfully except for descending ranges with a negative step greater than -1
    For example, when calling range() with:  range(39, 11, -9);  you should obtain an output of:

// range => [39, 30, 21, 12]        sum => 102

In your range function, you need to change your second for loop (within the else statement) from…

for (let i = end; i < start + 1; i += Math.abs(step)) {
   arr.unshift(i);
 }
// program outputs:     range => [38, 29, 20, 11]        sum => 98

to…

for (let i = start; i > end - 1; i -= Math.abs(step)) {
   arr.push(i);
 }
// program outputs:     range => [39, 30, 21, 12]        sum => 102

But really well done on getting so close! :muscle:

1 Like

Hi @Li_Sun,

Sorry for the delay in providing you with some feedback on your solutions to these exercises.

The Sum of a Range

That’s a great, and very original, solution you’ve come up with for this exercise :+1:

I’m not sure if you realised, but there are some more stages to this exercise, and it would be great to see how your alternative method can handle those as well:

  • You need to add functionality so that the sum of your descending ranges is calculated too. The exercise suggests having two separate functions: one for generating the array with the range, and another which takes in this array as its parameter, and then calculates the sum. However, if you want to perform the sum calculation all within the same function like you did with the first part (ascending ranges with increments of +1 only) then that’s absolutely fine. Although it is good practice to not overload individual functions, and try to keep different types of computations to separate functions.

  • Finally, you need to add functionality so that, if the step argument is left undefined in the function call, the function will activate a default step parameter of either 1 or -1, depending on whether it is going to generate an ascending or descending range.

Have a look again at the exercise instructions for more details, and let me know if you have any questions.

Reversing an Array

These execute perfectly :ok_hand: Again, your solution for the first part (returning a new array which is a mirror image of the original) is an original one. Your solution to the second part (reversing the original array in place) looks remarkably like the model answer :wink: … which is fine if you needed some help after giving it a good go yourself first, as long as you understand how the code in the model answer achieves the desired output.

1 Like

Hi @alex.k,

Sorry for the delay in giving you some feedback on your solution to the exercise The Sum of a Range.

You’ve made an excellent start with this, and I can see that you’ve really thought hard about how to approach it. You’re almost there! :muscle:

Your code executes successfully if we only make one function call. So, now let’s add the finishing touches:

  1. By declaring the variables…
    var NewArray = []; and
    var toPrint = 0;
    … in global scope (outside of the functions) their values won’t be reset if we want to perform multiple calculations with multiple function calls. With each successive function call, the array will keep adding the new range to all of the previous ones, and the sum will be cumulative, rather than just for the current array being generated. This can easily be fixed by doing the following:
    (a) Move both of variables to within their respective functions, at the beginning of each function body.
 // (b)

    document.write(NewArray + "<br><br>");
    return NewArray;   /* In your range() function, add this below your
                          document.write statement to return the output array to
                          the function call. This is now necessary because the
                          array can no longer be accessed from global scope */

 /* (c) Instead of calling range() and sum() separately, call one within the other
        at the end of the program. You can now do this multiple times e.g. */
        sum(range(4, 7));
        sum(range(1, 10));
        sum(range(5, 2, -1));
        sum(range(1, 10, 2));
        sum(range(3, 16, 3));
        sum(range(5, 2));
        sum(range(39, 11, -9));

(d) You will probably also want to add some line breaks to your document.write statement in your sum function, now that we will be displaying multiple lines.

  1. Your current program deals with all scenarios except for those represented by the last two function calls in the list above i.e.
    (i) Descending ranges where the step is left undefined (needs a default of -1)
    (ii) Descending ranges where the step is defined as anything larger than -1
    Can you now add this additional functionality to your program?

Just let us know if you have any questions.

Good luck!.. you’re making great progress! :muscle:

2 Likes

The Sum of a Range

function range(a, b, step = a < b ? 1 : -1) {
        var rangeArray = [];

        if(step > 0) {
          for(var i = a; i <= b; i += step) rangeArray.push(i);
        } else {
          for(var i = a; i >= b; i += step) rangeArray.push(i);
        }
      return rangeArray;
      }

function sum(array){
        return array.reduce((a, b) => a + b, 0);
      }

Reversing an Array

function reverseArray(array) {
        var newArray = [];
        var length = array.length;

        for(var i = 0; i < length; i++) {
            newArray.push(array.pop());
        }
      return newArray;
      }

function reverseArrayInPlace(array) {

        for(i = 0; i < Math.floor(array.length / 2); i++) {
            var temp = array[i];
            array[i] = array[array.length - 1 - i];
            array[array.length - 1 - i] = temp;
        }
      return array;
      }

Not sure about the last question, but since the reverseArrayInPlace needs few iterations to get the same result and don’t need to create another variable to store the final array, it seems more eficient than the reverseArray.

1 Like

Hi again, @alex.k,

Here’s your feedback for Reversing an Array :

Once again, this is a really good effort, and a great attempt to come up with your own solutions :ok_hand:

Your solution for the second part (reversing the original array in place) works perfectly :+1:

Here are my comments to help you add the finishing touches to the first part (creating a new array which is the reverse of the original) :

At first, your code appears to work, but you’ve cheated. Your following line of code…

new_array.push(array.length-[i]);

…will always produce an array of numbers which descend by decrements of -1 from the total number of elements to 1 e.g.

var start_array = [1, 2, 3, 4, 5];
// => [5, 4, 3, 2, 1]

var start_array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// => [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

And so, as long as we always input arrays that start with 1 and rise by increments of +1 (whatever their length), this code appears to work. However, as soon as we try to reverse arrays such as the following, the code no longer produces the correct result:

var start_array = [5, 7, 9, 11];
// => [4, 3, 2, 1]

var start_array = ['A', 'B', 'C', 'D'];
// => [4, 3, 2, 1 ]

In order to get your code to always produce an array that’s the reverse of the input array, you need to change this line of code to something like the following:

new_array.push(array[array.length-1-i]);
1 Like

Hi @FunkyGrass,

Sorry for the delay in providing you with feedback for your solutions to these exercises.

You’ve written some excellent code that handles most situations :+1:
Here are some comments, which will help you address a couple of small issues and add the finishing touches.

Sum of a Range

Your current program deals with all scenarios except for descending ranges where the step is left undefined (needs a default of -1)  e.g.

/* function calls */
console.log(range(5, 2));
console.log(sum(range(5, 2)));   

Can you now add this additional functionality to your program?

Your assignment of start to current seems unnecessary to me…

var current = start; 

…and I think you can just access start directly, wherever you currently have current — unless I’m missing something?

Reversing an Array

Your solution for the first part (creating a new array which is the reverse of the original) works perfectly :+1:

Your solution to the second part (reversing the original array in place) works for odd-numbered arrays (although it swaps the middle element with itself, which is unnecessary). However, it doesn’t work for even-numbered arrays: the middle two elements are reversed twice, therefore returning both to their original unreversed positions. To resolve this you need to take another look at your for loop condition   i <= reverseArray.length / 2;   and work out how to reduce the number of iterations by 1 for both even- and odd-numbered arrays.

Good luck!

Keep on learning!.. you’re making great progress! :muscle:

Hi @Wevlin,

I’m glad you found my attempt at a breakdown of what’s really going on helpful :grinning:

Thanks for letting us know, because it helps to know which explanations are particularly helpful for students (and not just me rambling away to myself :wink:) so we can use them again :+1:

I’ll have a word with @Mauro and see if we can develop those accompanying “people-on-a-bus” graphic animations you mention :bus: :oncoming_bus: :aerial_tramway: :smile:

1 Like
/* Exercise 4.2 Reversing an Array.  I got the first part of this after about
15 - 20 minutes.  I'm not sure I understand the concepts of the
reverseArrayInPlace function. Will research and tackle that at a later stage.
This is the reverseArray function of the exercse....
*/


function reverseArray(array){
  	let newArray = [];
  	for (let i = array.length - 1; i >= 0; i--){
    	newArray.push(array[i]);

    }
  return newArray;
}

/* This is the reverseArrayInPlace part of this exercise -
quite a challenge to wrap my head around this as I have not used Math.floor,
nor have I used a variable to swap it with another variable....
Anyways, got it after an hour and a half (which included reading up on
concepts that I hadn't used before).
*/

function reverseArrayInPlace(numbers){

    for(a = 0; a <= Math.floor(numbers.length / 2); a++){
      	let z = numbers.length - 1 - a
      	let swapped = numbers[a];
      	numbers[a] = numbers[z];
      	numbers[z] = swapped;
    }

}

console.log(reverseArray(["A", "B", "C"]));
// → ["C", "B", "A"];
let arrayValue = [1, 2, 3, 4, 5];
reverseArrayInPlace(arrayValue);
console.log(arrayValue);
// → [5, 4, 3, 2, 1]
1 Like

Oops, forgot to add this one when I added the Reversing an Array exercise.

function range(a,b,c){
    let myArray = [];

    if (a < b) {

        if (c === undefined){
        	c = 1;
        }

        for (i = a; i <= b; i += c){
        	myArray.push(i);
        }

    return myArray;

    } else if (a > b) {

        if (c === undefined){
        	c = -1;
        }

        for (i = a; i >= b; i+=c){
        	myArray.push(i);
        }

    }
  	return myArray;
}

// This is the sum function part (below).

function sum(numbers){
	var total = 0;
	for(i = 0; i < numbers.length; i++){
  		total += numbers[i];
    }
  	return total;
}


/*I added a few extra console.log ranges to make sure I was achieving
default increment/decrements and defined increment/decrements. All work, winning!!
*/

console.log(range(1, 10));
// → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(range(1, 10, 2));
// → [1, 3, 5, 7, 9,]
console.log(range(5, 2));
// → [5, 4, 3, 2]
console.log(range(8, 5, -1));
// → [8, 7, 6, 5]
console.log(range(9, 2, -2));
// → [9, 7, 5, 3]
console.log(sum(range(1, 10)));
// → 55
1 Like

Hi @natanieldp,

Sorry for the delay in providing you with feedback on your solutions to these exercises.

Sum of a Range

You’ve made an excellent start with this, and I can see that you’ve really thought hard about how to approach it. You’re almost there! :muscle:

Here are some comments to help you add the finishing touches:

  1. Your if statement to handle undefined step parameters doesn’t work:
    // you need to change the condition from
    step == ''
    // to
    step === undefined
  1. You then need to change step to b in the following if statements, otherwise any function calls with an undefined step parameter will not be handled. We can also improve the control flow of our conditional execution by changing the second if statement to an else statement, resulting in a clearer if...else
    // change to ...               from ...

    if (b >= 1) {...}          //  if (step >= 1) {...}
    else {...}                 //  if (step < 0) {...}    
  1. Don’t assign the value returned from a function call to a variable with the same name as the function!
    /* change to something like ...            from ...    */

    let total = sum(array);                //  sum = sum(array);
    console.log(total);                    //  console.log(sum); 
  1. After you’ve made the above amendments, your program will successfully handle all scenarios, except for descending ranges where the step is left undefined (needs a default of -1) e.g.
    /* function calls */
    console.log(range(5, 2));
    console.log(sum(range(5, 2)));   

Can you now add this additional functionality to your program as well?

Reversing an Array

Your solutions to both parts of this exercise work perfectly :+1:

However, there is some redundant code that you can remove, because it doesn’t add anything:

  • In both functions, the additional “counter” variable index isn’t needed, as the iterator variable var a in the for loop already serves the same purpose. Therefore, the following lines of code can be removed from both functions:
    var index = 0;
    // and
    index++;

    … and all references to index should then be changed to   a

  • In the  reverseArrayInPlace  function there is no need to declare the variable temp outside of the for loop first. You can declare it directly within the for loop as follows:
    var temp = array[a]; 
  • I’m not sure why you have two Bitwise NOT operators (~~) in the  reverseArrayInPlace  function’s for loop condition… is this a keyboard slip, or formatting error?.. they cancel each other out anyway, and have no impact if deleted.

Keep on learning! … you’re making great progress!

Hi @jon_m, thanks for your input. Really appreaciate that.
Yes I was confused to define the ‘undefine’.

as for ’ ~~’ , i google it and it said that its the shortcut for 'Math.floor()`

1 Like

console.log(sum(range(1,10))

  <script>
      function range(start, end, skip=1){
        let Return = [];
        for (let count=start; count<=end; count+= skip){
          Return.push(count);
        }
        return Return;
      }

      function sum(number){
        let result = 0;
        for (let element of number){
          result+=element;
        }
        return result;
      }

      console.log(sum(range(1,10)));

    </script>
1 Like

reversing the list

<script>

      function reverseArray(array){
        let newArray = [];
        for (let value of array){
          newArray.unshift(value);
        }
        return newArray;
      }

      function reverseArrayInPlace(array){
        lengthOfArray = array.length;
        maxIndex = lengthOfArray-1;
        for (let count = 0; count<parseInt(lengthOfArray/2); count++){
          temp = array[count];
          array[count] = array[maxIndex-count];
          array[maxIndex-count] = temp;
        }
        return array;
      }


    console.log(reverseArray(range(1,10)));  
    console.log(reverseArrayInPlace(range(1,10)));
</script>
1 Like