CodingNic

Practical Challenges

Intermediate Challenges

Practical Challenges 50 min read

Intermediate Challenges

Objectives

This chapter introduces no new concepts. Each challenge below needs two or three techniques from earlier in the course working together, not just one.

Challenge 1: Two Sum

Write a function twoSum(nums, target) that finds two numbers in nums that add up to target, and returns them as a two-item array. Assume exactly one such pair exists.

Example:

javascript
twoSum([2, 7, 11, 15], 9);              // [2, 7]
twoSum([3, 5, -4, 8, 11, 1, -1, 6], 10); // [11, -1]

Hint: a pair means two different positions in the array. A loop inside a loop, checking every combination, works fine here, this isn’t about the fastest possible solution.

Challenge 2: Group by Property

Write a function groupBy(items, key) that takes an array of objects and a property name, and returns an object where each key is one of the values that property took, and each value is an array of the items that had it.

Example:

javascript
const tasks = [
  { title: "Write report", priority: "high" },
  { title: "Water plants", priority: "low" },
  { title: "Fix bug", priority: "high" },
  { title: "Read book", priority: "low" }
];

groupBy(tasks, "priority");
// {
//   high: [{ title: "Write report", priority: "high" }, { title: "Fix bug", priority: "high" }],
//   low: [{ title: "Water plants", priority: "low" }, { title: "Read book", priority: "low" }]
// }

Hint: .reduce() fits this well. The accumulator is the object you’re building up, and for each item you check whether its key already exists on the accumulator before pushing onto it.

Challenge 3: Flatten a Nested Array

Write a function flatten(arr) that takes an array which may contain other arrays, nested to any depth, and returns a single flat array with every value in order.

Example:

javascript
flatten([1, [2, [3, 4], 5], [[6]]]); // [1, 2, 3, 4, 5, 6]

Constraint: don’t reach for a built-in method that does this in one call. Solve it with recursion.

Hint: for each item, if it’s an array (Array.isArray() checks this), you need to flatten it too before adding its contents to your result. If it isn’t, add it directly. That’s the entire recursive case and base case.

Challenge 4: Run Once

Write a higher-order function once(fn) that returns a new function which only actually calls fn the first time it’s invoked. Every call after that returns the same result fn produced the first time, without calling fn again.

Example:

javascript
let callCount = 0;
function expensiveCalc(n) {
  callCount++;
  return n * n;
}

const onceCalc = once(expensiveCalc);
onceCalc(5); // 25
onceCalc(9); // 25, still, even though 9 was passed
callCount;   // 1

Hint: this is a closure problem. once needs to remember, across calls, whether fn has already run and what it returned. That “remembering across calls” is exactly what a closure gives you.

Challenge 5: Validate a Password

Write a function validatePassword(password) that checks three rules: at least 8 characters, contains at least one digit, and contains at least one uppercase letter. If all three pass, return true. Otherwise, return an array of strings describing which rules failed.

Example:

javascript
validatePassword("short1A");     // ["must be at least 8 characters"]
validatePassword("longenough1A"); // true
validatePassword("nouppercase1"); // ["must contain an uppercase letter"]

Hint: .test() on a regular expression returns true or false for whether a pattern appears anywhere in a string, you don’t need .match() here.

Recap

Five problems, each requiring you to combine techniques rather than apply one directly. If you got through these without checking a hint, the advanced challenges next are ready for you.

Next lesson: advanced challenges, combining classes, closures, recursion, and error handling in a single program.