level 4 - Expert (Concurrency, Scheduling, System Patterns) Flashcards

Focus: data structures, scheduling, parallelism (5 cards)

1
Q

TaskScheduler with Concurrency Limit

Description
Implement a TaskScheduler class that allows you to schedule asynchronous tasks with a concurrency limit. The scheduler should ensure that no more than limit tasks run at the same time.

Each task is a function that returns a Promise. Tasks can complete at different times, and the scheduler should ensure new tasks start only after one of the current ones completes, while preserving order of task insertion.

๐Ÿ“˜ Example Usage

const scheduler = new TaskScheduler(2);

const delay = (ms, val) => () => new Promise(res => setTimeout(() => res(val), ms));

scheduler.add(delay(1000, "A")).then(console.log); // resolves at t=1000ms
scheduler.add(delay(500, "B")).then(console.log);  // resolves at t=1000ms
scheduler.add(delay(300, "C")).then(console.log);  // resolves at t=1300ms
scheduler.add(delay(400, "D")).then(console.log);  // resolves at t=1500ms

// Expected order of output
// A
// B
// C
// D

Code

// ๐Ÿšง Stubbed Implementation
class TaskScheduler {
  constructor(limit) {
    this.limit = limit;
    // TODO: Initialize necessary queues and state variables
  }

  add(taskFn) {
    // TODO: Return a Promise and schedule task respecting concurrency
  }
}

๐Ÿงช Test Suite

// ๐Ÿ”’ Enforcement: Disallow forbidden patterns
(function enforceSchedulerConstraints() {
  const source = TaskScheduler?.toString?.() || "";
  const forbidden = ["eval", "Function", ".toString", "window", "globalThis"];
  forbidden.forEach(term => {
    if (source.includes(term)) {
      throw new Error(`โŒ Forbidden pattern used in TaskScheduler(): "${term}" is not allowed.`);
    }
  });
})();

function runTaskSchedulerTests() {
  console.log("๐Ÿ” Running TaskScheduler Tests...");

  const delay = (ms, val) => () =>
    new Promise((res) => setTimeout(() => {
      results.push(val);
      res(val);
    }, ms));

  const results = [];
  const scheduler = new TaskScheduler(2);

  const start = Date.now();
  const logTime = () => Math.round(Date.now() - start);

  const tasks = [
    scheduler.add(delay(100, "A")),
    scheduler.add(delay(100, "B")),
    scheduler.add(delay(50, "C")),
    scheduler.add(delay(30, "D")),
  ];

  Promise.all(tasks).then((values) => {
    console.log("โœ… All tasks completed");
    console.log("๐Ÿงพ Results Order:", results.join(", "));
    if (results.join("") !== "ABCD") {
      console.error("โŒ Task order incorrect.");
    }
    console.log("โฑ๏ธ Total Time:", logTime(), "ms");
  });
}

// โœ… Run Tests
runTaskSchedulerTests();
A
class TaskScheduler {
  constructor(limit) {
    this.limit = limit;
    this.running = 0;
    this.queue = [];
  }

  add(taskFn) {
    return new Promise((resolve, reject) => {
      const run = () => {
        this.running++;
        taskFn()
          .then(resolve)
          .catch(reject)
          .finally(() => {
            this.running--;
            if (this.queue.length) {
              const next = this.queue.shift();
              next();
            }
          });
      };

      if (this.running < this.limit) {
        run();
      } else {
        this.queue.push(run);
      }
    });
  }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

LazyEvaluator โ€“ Chainable Utility for Deferred Evaluation

Description
Implement a utility called LazyEvaluator that supports chained method calls like map, filter, and take, but defers execution until .evaluate() is explicitly called.

Requirements:
Initialize with an array: new LazyEvaluator([1, 2, 3, 4])
Chain operations:
* map(fn)
* .filter(fn)
* .take(n) โ†’ takes first n results from the processed stream
Call .evaluate() to execute all queued operations and return the final array.

Example:

const lazy = new LazyEvaluator([1, 2, 3, 4, 5])
  .map(x => x * 2)
  .filter(x => x > 5)
  .take(2)
  .evaluate(); // โ†’ [6, 8]

๐Ÿ”’ Constraints:
The implementation must not use any of the following:
* eval
* Function constructor
* .toString()
* Global variables (window, globalThis)
* Built-in utility libraries (like Lodash, etc.)

Code

// ๐Ÿงฑ Stubbed Implementation
class LazyEvaluator {
  constructor(array) {
    this.array = array;
    // TODO: Store chain of operations without executing them
  }

  map(fn) {
    // TODO: Queue a map operation
    return this;
  }

  filter(fn) {
    // TODO: Queue a filter operation
    return this;
  }

  take(n) {
    // TODO: Queue a take operation
    return this;
  }

  evaluate() {
    // TODO: Apply queued operations in order, return final array
  }
}

๐Ÿงช Test Suite

// ๐Ÿ”’ Enforcement for forbidden patterns
(function enforceLazyEvaluatorConstraints() {
  const source = LazyEvaluator?.toString?.();
  const forbidden = ["eval", "Function", ".toString", "window", "globalThis"];
  forbidden.forEach(term => {
    if (source?.includes(term)) {
      throw new Error(`โŒ Forbidden pattern used in LazyEvaluator: "${term}"`);
    }
  });
})();

function runLazyEvaluatorTests() {
  const assertDeepEqual = (desc, actual, expected) => {
    const pass = JSON.stringify(actual) === JSON.stringify(expected);
    console.log(`${pass ? "โœ…" : "โŒ"} ${desc}`);
    if (!pass) {
      console.log(`   Expected: ${JSON.stringify(expected)}, but got: ${JSON.stringify(actual)}`);
    }
  };

  const lazy1 = new LazyEvaluator([1, 2, 3, 4, 5])
    .map(x => x * 2)
    .filter(x => x > 5)
    .take(2)
    .evaluate();
  assertDeepEqual("Chained lazy evaluation works", lazy1, [6, 8]);

  const lazy2 = new LazyEvaluator([10, 20, 30, 40])
    .filter(x => x >= 20)
    .map(x => x / 10)
    .evaluate();
  assertDeepEqual("Filter before map", lazy2, [2, 3, 4]);

  const lazy3 = new LazyEvaluator([1, 2, 3, 4])
    .take(2)
    .map(x => x * 3)
    .evaluate();
  assertDeepEqual("Take before map", lazy3, [3, 6]);

  const lazy4 = new LazyEvaluator([])
    .map(x => x + 1)
    .filter(x => x > 0)
    .evaluate();
  assertDeepEqual("Empty array returns empty", lazy4, []);
}

runLazyEvaluatorTests();
A
class LazyEvaluator {
  constructor(array) {
    this.array = array;
    this.operations = [];
  }

  map(fn) {
    this.operations.push(arr => arr.map(fn));
    return this;
  }

  filter(fn) {
    this.operations.push(arr => arr.filter(fn));
    return this;
  }

  take(n) {
    this.operations.push(arr => arr.slice(0, n));
    return this;
  }

  evaluate() {
    return this.operations.reduce((acc, op) => op(acc), this.array);
  }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Safe JSON.parse

Description
Implement a function safeJsonParse(jsonString, fallback) that attempts to parse a given JSON string. If parsing fails due to invalid JSON, it must return the provided fallback value instead of throwing an error.

Requirements
Accept two arguments:
* jsonString: a string that might represent a JSON value.
* fallback: a fallback value to return in case parsing fails.
Must not throw an error for invalid JSON input.
Must return parsed object on success, or fallback on failure.

Examples

safeJsonParse('{"name":"Alice"}', {});        // โ†’ { name: "Alice" }
safeJsonParse('invalid JSON', { error: true }); // โ†’ { error: true }
safeJsonParse('[1,2,3]', [])                  // โ†’ [1, 2, 3]
safeJsonParse('42', 0)                        // โ†’ 42

๐Ÿ”’ Constraints
You must not use:
* eval
* Function constructor
* .toString()
* Global variables (window, globalThis)
* Third-party libraries (e.g., Lodash)

Code:

// ๐Ÿงฑ Stubbed Implementation
function safeJsonParse(jsonString, fallback) {
  // TODO: Try parsing jsonString using JSON.parse
  // If parsing fails, return the fallback value
}
// ๐Ÿ”’ Constraint Enforcement
(function enforceSafeJsonParseConstraints() {
  const source = safeJsonParse?.toString?.();
  const forbidden = ["eval", "Function", ".toString", "window", "globalThis"];
  forbidden.forEach(term => {
    if (source?.includes(term)) {
      throw new Error(`โŒ Forbidden pattern used in safeJsonParse(): "${term}" is not allowed.`);
    }
  });
})();

function runSafeJsonParseTests() {
  const assertDeepEqual = (desc, actual, expected) => {
    const pass = JSON.stringify(actual) === JSON.stringify(expected);
    console.log(`${pass ? "โœ…" : "โŒ"} ${desc}`);
    if (!pass) {
      console.log(`   Expected: ${JSON.stringify(expected)}, but got: ${JSON.stringify(actual)}`);
    }
  };

  assertDeepEqual(
    "Parses valid JSON object",
    safeJsonParse('{"x":10}', {}),
    { x: 10 }
  );

  assertDeepEqual(
    "Parses valid JSON array",
    safeJsonParse('[1,2,3]', []),
    [1, 2, 3]
  );

  assertDeepEqual(
    "Returns fallback for invalid JSON",
    safeJsonParse('not-json', { error: true }),
    { error: true }
  );

  assertDeepEqual(
    "Returns number if valid JSON number",
    safeJsonParse('42', 0),
    42
  );

  assertDeepEqual(
    "Returns null for JSON 'null'",
    safeJsonParse('null', 'default'),
    null
  );
}

runSafeJsonParseTests();
A
function safeJsonParse(jsonString, fallback) {
  try {
    return JSON.parse(jsonString);
  } catch (e) {
    return fallback;
  }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Reimplement setTimeout and setInterval

Description:
Your task is to implement:
* customSetTimeout(callback, delay) using only setInterval.
* customSetInterval(callback, delay) using only setTimeout.
You must not use setTimeout when implementing customSetTimeout, and likewise must not use setInterval when implementing customSetInterval.

โš ๏ธ Constraints:
Your implementation must not use any of the following:
* eval, Function, or .toString
* Any global/shared state across invocations

Code

// ๐Ÿ” Reimplement setTimeout using setInterval
function customSetTimeout(callback, delay) {
  // TODO: Use setInterval to trigger the callback only once after the delay
}

// ๐Ÿ” Reimplement setInterval using setTimeout
function customSetInterval(callback, delay) {
  // TODO: Use setTimeout to call the callback repeatedly every delay ms
}

๐Ÿงช Test Suite

// ๐Ÿ”’ Enforcements
(function enforceConstraints() {
  const forbidden = ["eval", "Function", ".toString"];
  const timeoutSource = customSetTimeout.toString();
  const intervalSource = customSetInterval.toString();

  forbidden.forEach(term => {
    if (timeoutSource.includes(term)) {
      throw new Error(`โŒ Forbidden pattern in customSetTimeout(): "${term}"`);
    }
    if (intervalSource.includes(term)) {
      throw new Error(`โŒ Forbidden pattern in customSetInterval(): "${term}"`);
    }
  });

  if (timeoutSource.includes("setTimeout")) {
    throw new Error(`โŒ Do not use setTimeout inside customSetTimeout`);
  }
  if (intervalSource.includes("setInterval")) {
    throw new Error(`โŒ Do not use setInterval inside customSetInterval`);
  }
})();

// โœ… Tests
function runTests() {
  console.log("โ–ถ๏ธ Running timing tests...");

  const assertApproximately = (desc, actual, expected, threshold = 50) => {
    const diff = Math.abs(actual - expected);
    const passed = diff <= threshold;
    console.log(`${passed ? "โœ…" : "โŒ"} ${desc}`);
    if (!passed) {
      console.log(`   Expected ~${expected}ms, but got ${actual}ms`);
    }
  };

  // Test customSetTimeout
  const t1Start = Date.now();
  customSetTimeout(() => {
    const elapsed = Date.now() - t1Start;
    assertApproximately("customSetTimeout executes after ~1000ms", elapsed, 1000);
  }, 1000);

  // Test customSetInterval
  let counter = 0;
  const t2Start = Date.now();
  const cancel = customSetInterval(() => {
    counter++;
    const elapsed = Date.now() - t2Start;
    if (counter === 3) {
      assertApproximately("customSetInterval 3rd tick ~2000ms", elapsed, 2000);
      cancel(); // stop future intervals
    }
  }, 1000);
}

runTests();
A
function customSetTimeout(callback, delay) {
  const id = setInterval(() => {
    clearInterval(id);
    callback();
  }, delay);
}

function customSetInterval(callback, delay) {
  let active = true;

  function loop() {
    if (!active) return;
    callback();
    timeoutId = setTimeout(loop, delay);
  }

  let timeoutId = setTimeout(loop, delay);

  return () => {
    active = false;
    clearTimeout(timeoutId);
  };
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

FileSystem Simulation

Description
Design and implement a FileSystem class that simulates a simplified file system with a hierarchical directory structure.

๐Ÿ› ๏ธ Your FileSystem should support:
* mkdir(path: string)
Create directories based on an absolute or relative path.
Intermediate directories should be created if they do not exist.
* ls(path?: string)
List contents of the given path, sorted lexicographically. If path is a file, return just the filename. If not provided, list contents of current directory.
* cd(path: string)
Change the current working directory to the target path. Paths can be absolute (start with /) or relative (like .., ., folder).

๐Ÿ”’ Constraints
You must not use:
* eval
* Function constructor
* .toString (on functions or objects)
* You must simulate file system behavior in memory.
* Treat all entries as directories (no file content handling required for now).
* The root directory is โ€˜/โ€™.

Code

class FileSystem {
  constructor() {
    // TODO: Initialize root and current directory
  }

  mkdir(path) {
    // TODO: Create directory at given path
  }

  ls(path = ".") {
    // TODO: Return sorted list of items in path
  }

  cd(path) {
    // TODO: Change current working directory
  }
}

๐Ÿงช Test Suite

(function enforceConstraints() {
  const source = FileSystem.toString();
  const forbidden = ["eval", "Function", ".toString"];
  forbidden.forEach(term => {
    if (source.includes(term)) {
      throw new Error(`โŒ Forbidden pattern detected: "${term}" is not allowed.`);
    }
  });
})();

function runFileSystemTests() {
  const assert = (desc, actual, expected) => {
    const pass = JSON.stringify(actual) === JSON.stringify(expected);
    console.log(`${pass ? "โœ…" : "โŒ"} ${desc}`);
    if (!pass) {
      console.log(`   Expected: ${JSON.stringify(expected)}`);
      console.log(`   Got     : ${JSON.stringify(actual)}`);
    }
  };

  const fs = new FileSystem();

  fs.mkdir('/a/b/c');
  assert("mkdir should create nested directories", fs.ls('/a/b'), ['c']);

  fs.cd('/a/b/c');
  fs.mkdir('x');
  fs.mkdir('y');
  assert("ls in current path shows created dirs", fs.ls(), ['x', 'y']);

  fs.cd('..');
  assert("cd('..') moves up one level", fs.ls(), ['c']);

  fs.cd('/');
  assert("cd('/') returns to root", fs.ls(), ['a']);

  fs.cd('a/b');
  assert("cd supports relative paths", fs.ls(), ['c']);

  fs.cd('../../a');
  assert("cd supports '../' navigation", fs.ls(), ['b']);

  fs.cd('/');
  fs.mkdir('z');
  assert("mkdir creates directories at root", fs.ls('/'), ['a', 'z']);
}

runFileSystemTests();
A
class FileSystem {
  constructor() {
    this.root = {};
    this.cwd = this.root;
    this.cwdPath = ['/'];
  }

  _resolve(path) {
    const parts = path.split('/').filter(Boolean);
    const absolute = path.startsWith('/');
    let node = absolute ? this.root : this.cwd;
    const trail = absolute ? ['/'] : [...this.cwdPath];

    for (const part of parts) {
      if (part === '.') continue;
      else if (part === '..') {
        if (trail.length > 1) {
          trail.pop();
          node = this._getNodeFromPath(trail);
        }
      } else {
        if (!node[part]) {
          node[part] = {};
        }
        node = node[part];
        trail.push(part);
      }
    }

    return { node, trail };
  }

  _getNodeFromPath(pathArray) {
    let node = this.root;
    for (let i = 1; i < pathArray.length; i++) {
      node = node[pathArray[i]];
    }
    return node;
  }

  mkdir(path) {
    this._resolve(path); // Just resolve and create intermediate directories
  }

  ls(path = '.') {
    const { node } = this._resolve(path);
    return Object.keys(node).sort();
  }

  cd(path) {
    const { node, trail } = this._resolve(path);
    this.cwd = node;
    this.cwdPath = trail;
  }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly