Skip to content
21 changes: 17 additions & 4 deletions Sprint-1/fix/median.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,22 @@
// or 'list' has mixed values (the function is expected to sort only numbers).

function calculateMedian(list) {
const middleIndex = Math.floor(list.length / 2);
const median = list.splice(middleIndex, 1)[0];
return median;
if (!Array.isArray(list) || list.length === 0) {
return null;
}

const numbers = list.filter(n => typeof n === "number" && !Number.isNaN(n));

if (numbers.length === 0) {
return null;
}

const sorted = numbers.sort((a, b) => a - b);
const mid = Math.floor(sorted.length / 2);

return sorted.length % 2
? sorted[mid]
: (sorted[mid - 1] + sorted[mid]) / 2;
}

module.exports = calculateMedian;
module.exports = calculateMedian;
7 changes: 6 additions & 1 deletion Sprint-1/implement/dedupe.js
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
function dedupe() {}
function dedupe(arr) {
if (!Array.isArray(arr)) return [];
return [...new Set(arr)];
}

module.exports = dedupe;
32 changes: 24 additions & 8 deletions Sprint-1/implement/dedupe.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,29 @@ E.g. dedupe([1, 2, 1]) returns [1, 2]
// Given an empty array
// When passed to the dedupe function
// Then it should return an empty array
test.todo("given an empty array, it returns an empty array");
//test.todo("given an empty array, it returns an empty array");

// Given an array with no duplicates
// When passed to the dedupe function
// Then it should return a copy of the original array
describe("dedupejs", () => {
test.each([
{ input: [""], expected: [""] },

// Given an array of strings or numbers
// When passed to the dedupe function
// Then it should return a new array with duplicates removed while preserving the
// first occurrence of each element from the original array.
// Given an array with no duplicates
// When passed to the dedupe function
// Then it should return a copy of the original array

{ input: [1, 2, 3], expected: [1, 2, 3] },

// Given an array of strings or numbers
// When passed to the dedupe function
// Then it should return a new array with duplicates removed while preserving the
// first occurrence of each element from the original array.

{ input: [1, 2, 2, 3], expected: [1, 2, 3] },
{ input: [1, "a", 2, "a"], expected: [1, "a", 2] },
{ input: ["b", "c", "d", "e"], expected: ["b", "c", "d", "e"] },
])("removes duplicates from $input", ({ input, expected }) => {
const result = dedupe(input); // stores the result in a variable called result
expect(result).toEqual(expected); // Check that the result matches the expected output
expect(result).not.toBe(input); // Check that it's a new array (not the original)
});
});
22 changes: 22 additions & 0 deletions Sprint-1/implement/max.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
function findMax(elements) {
//find largest number in an array
if (!Array.isArray(elements)) {
throw new Error("Input must be an array"); //checks input is an array if not throws error
}

let max = -Infinity; //starts at -Infinity so any number will be bigger
let foundValid = false; //starts at false and will become true if valid number found

for (const val of elements) {
if (!Number.isFinite(val)) continue; //skips non-numeric values

foundValid = true; //sets to true if a valid number is found
if (val > max) {
max = val; //updates max if current value is greater
}
}
if (!foundValid) {
//if no valid numbers found, returns"-Inifinity" this includes invalid data and empty arrays
return -Infinity;
}
Comment on lines +18 to +21
Copy link
Copy Markdown
Contributor

@cjyuan cjyuan Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If foundValid remains false, then max would remain unchanged. So even without using foundValid and without this if statement and, the function would still return -Infinity.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you for explaining


return max; //returns the largest number found
}

module.exports = findMax;
66 changes: 47 additions & 19 deletions Sprint-1/implement/max.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,56 @@ const findMax = require("./max.js");
// When passed to the max function
// Then it should return -Infinity
// Delete this test.todo and replace it with a test.
test.todo("given an empty array, returns -Infinity");
describe("findMax.js", () => {
test.each([
Comment on lines +19 to +20
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should you need to classify test data into different categories, you can write:

describe("findMax -- description of category 1", () => {
  test.each(
    ...
  );
});

describe("findMax -- description of category 2", () => {
  test.each(
    ...
  );
});
...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you

{ input: [], expected: -Infinity },
// Given an array with one number
// When passed to the max function
// Then it should return that number

// Given an array with one number
// When passed to the max function
// Then it should return that number
{ input: [1], expected: 1 },

// Given an array with both positive and negative numbers
// When passed to the max function
// Then it should return the largest number overall
// Given an array with both positive and negative numbers
// When passed to the max function
// Then it should return the largest number overall

// Given an array with just negative numbers
// When passed to the max function
// Then it should return the closest one to zero
{ input: [1, 2, -3], expected: 2 },

// Given an array with decimal numbers
// When passed to the max function
// Then it should return the largest decimal number
// Given an array with just negative numbers
// When passed to the max function
// Then it should return the closest one to zero

// Given an array with non-number values
// When passed to the max function
// Then it should return the max and ignore non-numeric values
{ input: [-6, -2, -3], expected: -2 },

// Given an array with only non-number values
// When passed to the max function
// Then it should return the least surprising value given how it behaves for all other inputs
// Given an array with decimal numbers
// When passed to the max function
// Then it should return the largest decimal number

{ input: [3.5, 2.9, 6.3], expected: 6.3 },

// Given an array with non-number values
// When passed to the max function
// Then it should return the max and ignore non-numeric values

{ input: ["a", 2, 3], expected: 3 },

// Given an array with only non-number values
// When passed to the max function
// Then it should return the least surprising value given how it behaves for all other inputs
// It will return -Infinity as it ignores all non-numeric values and returns -Infinity if no valid numbers found

{ input: ["a", "!", "x"], expected: -Infinity },

// Given an array contains a number string it will ignore the string and return the max number

{ input: ["5", 2, 3], expected: 3 },


// Given an array contains only number strings it will rerturn -Infinity

{ input: ["5", "2", "3"], expected: -Infinity },

])("returns correct max for %o", ({ input, expected }) => {
expect(findMax(input)).toBe(expected);
});
});
19 changes: 18 additions & 1 deletion Sprint-1/implement/sum.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
function sum(elements) {
}
// adds numbers and ignores non-numbers unless there are no valid numbers then throws error

if (!Array.isArray(elements)) {
throw new Error("Input must be an array"); //checks input is an array if not throws error
}

if (elements.length === 0) return 0; // <-- empty array returns 0

let total = 0;
let foundValid = false; //starts at false and will become true if valid number found

for (const val of elements) {
if (!Number.isFinite(val)) continue;
foundValid = true; // loops and checks if input valid and if valid changes foundValid to true
total += val; //adds number to sum
}

return foundValid ? total : "Invalid Input"; // if at least one valid value is found return sum if no valid number is found return Invalid Input
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about designing the function to support this behavior?
sum(["A"]) + sum([2]) == sum(["A", 2])

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what it is you want me to do. The idea of the function is to add numbers together and ignore everything else so I am not sure why you are asking me to do this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sum(array1) + sum(array2) == sum(array1.concat(array2))

Both sides are two different ways to compute "sum of all the elements in array1 and array2".
Normal expectation is that the equality should hold.

However, if array1 is ["A"] and sum(array1) returns "Invalid Input" instead of 0, then the equality would break.

As a result, in my opinion, 0 is a more appropriate value to return when an array contains only non-numeric values.

}
module.exports = sum;
67 changes: 47 additions & 20 deletions Sprint-1/implement/sum.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,57 @@ E.g. sum(['hey', 10, 'hi', 60, 10]), target output: 80 (ignore any non-numerical
*/

const sum = require("./sum.js");
describe("sum.js", () => {
test.each([
// Acceptance Criteria:

// Acceptance Criteria:
// Given an empty array
// When passed to the sum function
// Then it should return 0

// Given an empty array
// When passed to the sum function
// Then it should return 0
test.todo("given an empty array, returns 0")
{ input: [], expected: 0 },

// Given an array with just one number
// When passed to the sum function
// Then it should return that number
// Given an array with just one number
// When passed to the sum function
// Then it should return that number

// Given an array containing negative numbers
// When passed to the sum function
// Then it should still return the correct total sum
{ input: [1], expected: 1 },

// Given an array with decimal/float numbers
// When passed to the sum function
// Then it should return the correct total sum
// Given an array containing negative numbers
// When passed to the sum function
// Then it should still return the correct total sum

// Given an array containing non-number values
// When passed to the sum function
// Then it should ignore the non-numerical values and return the sum of the numerical elements
{ input: [-2, 3, 4, -6], expected: -1 },
{ input: [4, -2], expected: 2 },

// Given an array with only non-number values
// When passed to the sum function
// Then it should return the least surprising value given how it behaves for all other inputs
// Given an array with decimal/float numbers
// When passed to the sum function
// Then it should return the correct total sum

{ input: [2.3, 4.2, 3.5], expected: 10 },
{ input: [4, 1.5], expected: 5.5 },

// Given an array containing non-number values
// When passed to the sum function
// Then it should ignore the non-numerical values and return the sum of the numerical elements

{ input: ["a", 2, 5, "b"], expected: 7 },

// Given an array with only non-number values
// When passed to the sum function
// Then it should return the least surprising value given how it behaves for all other inputs

{ input: ["a", "n", "p"], expected: "Invalid Input" },
])(
"sums all numbers from $input and expects $expected",
({ input, expected }) => {
const result = sum(input);

if (typeof expected === "number") {
expect(Math.abs(result - expected)).toBeLessThan(1e-10); // for special cases of decimals to avoid precision issues
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also use expect(result).toBeCloseTo(expected).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you, that is useful to know

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: They are not entirely equivalent though.

expect(result).toBeCloseTo(expected, 10) is closer to (Math.abs(result - expected)).toBeLessThan(0.5e-10)

The default value of the second parameter is 2 (surprisingly). So

expect(result).toBeCloseTo(expected) is closer to (Math.abs(result - expected)).toBeLessThan(0.005)
(Note: 0.5e-2 = 0.5 * 10**-2 = 0.5 * 0.01 = 0.005)

} else {
expect(result).toEqual(expected); // for non-numeric expected values, check for exact match
}
}
);
});
5 changes: 2 additions & 3 deletions Sprint-1/refactor/includes.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// Refactor the implementation of includes to use a for...of loop

function includes(list, target) {
for (let index = 0; index < list.length; index++) {
const element = list[index];
for (const element of list)
if (element === target) {
return true;
}
}

return false;
}

Expand Down
Loading