PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates competency in graph algorithms, dependency resolution, stateful scheduling, and robust error handling within the Coding & Algorithms domain.

  • easy
  • Snowflake
  • Coding & Algorithms
  • Software Engineer

Schedule prerequisite classes with retakes

Company: Snowflake

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: easy

Interview Round: Onsite

## Problem You are building a course-taking engine. Each course is represented as an object: - `id` (unique identifier) - `prevCoursesList`: a list of prerequisite course IDs that must be **passed** before this course can be attempted. You are given: - `roots`: a list of **target** course IDs the student ultimately wants to complete. - An API `didPass(courseId) -> bool` that can be called **each time you attempt** a course. If it returns `false`, the student failed that attempt and must retake the course later. ### Rules 1. A course can be **attempted** only after all its prerequisites have been **passed**. 2. When a course is attempted: - If `didPass(id)` returns `true`, mark it as passed. - If it returns `false`, the course must be retaken later (i.e., re-queued for another attempt). 3. The input only provides prerequisite pointers (`course -> prerequisites`). You must first discover all involved courses reachable from `roots` and build any additional relationships you need (e.g., prerequisite → dependent adjacency). ### Task Implement a function that returns the sequence of course IDs in the order they were **attempted** until: - all `roots` have been passed, or - you detect it is impossible (e.g., a prerequisite cycle), or - a course exceeds `maxRetries` failed attempts. ### Output Return: - `attemptOrder`: list of attempted course IDs (including retries), if successful. - Otherwise, return/throw an error indicating the reason (cycle detected or retries exceeded). ### Constraints (reasonable assumptions) - Up to ~1e5 courses and ~2e5 prerequisite edges may be involved after expanding from `roots`. - `maxRetries` is a small integer (e.g., 3–10). ### Edge cases to handle - Shared prerequisites among multiple roots. - Duplicate IDs in `roots`. - Missing prerequisite IDs (treat as invalid input). - Cycles in prerequisite dependencies. - Courses that repeatedly fail and exceed `maxRetries`.

Quick Answer: This question evaluates competency in graph algorithms, dependency resolution, stateful scheduling, and robust error handling within the Coding & Algorithms domain.

You are building a course-taking engine. Each course is identified by an integer ID, and `courses[id]` gives the list of prerequisite course IDs that must be passed before course `id` can be attempted. You are also given `roots`, the target courses the student wants to complete, `attempt_results`, a deterministic replacement for the `didPass` API, and `max_retries`. First, discover every course reachable from `roots` by following prerequisite links. If a root is missing from `courses`, return `('error', 'missing course: X')`. If a reachable prerequisite ID is missing from `courses`, return `('error', 'missing prerequisite: X')`. If the reachable prerequisite graph contains a cycle, return `('error', 'cycle detected')` before making any attempts. Otherwise, simulate attempts using this deterministic policy so the output is unique: 1. Initially enqueue all reachable courses with no prerequisites, in increasing course ID order. 2. Always attempt the course at the front of the queue. 3. If the attempt passes, mark the course as passed forever. Any newly unlocked dependent courses are appended to the back of the queue in increasing course ID order. 4. If the attempt fails, append that same course to the back of the queue, unless this failure makes its failed-attempt count exceed `max_retries`, in which case return `('error', 'max retries exceeded: X')`. `attempt_results[id][k]` is the result of the `(k+1)`-th attempt for course `id`. If a course is missing from `attempt_results`, or it is attempted more times than the list provides, all missing results are treated as `False`. Return `('success', attemptOrder)` when all distinct root courses have been passed. `attemptOrder` must include retries.

Constraints

  • Only the prerequisite subgraph reachable from `roots` matters; unrelated courses should be ignored.
  • Up to 100000 reachable courses and 200000 reachable prerequisite edges.
  • 0 <= max_retries <= 10.
  • Course IDs are integers; `roots` may contain duplicates or be empty.

Examples

Input: ({1: [], 2: [1], 3: [1], 4: [2, 3], 5: [2]}, [4, 5, 4], {1: [True], 2: [False, True], 3: [True], 4: [True], 5: [True]}, 2)

Expected Output: ('success', [1, 2, 3, 2, 4, 5])

Explanation: The reachable courses are 1, 2, 3, 4, and 5. Course 1 passes first. Course 2 fails once and goes to the back of the queue, so 3 is attempted next and passes. Then 2 passes on retry, unlocking both 4 and 5. Both target roots are eventually passed.

Input: ({1: [2], 2: [3], 3: [1]}, [1], {}, 2)

Expected Output: ('error', 'cycle detected')

Explanation: The reachable subgraph contains the cycle 1 -> 2 -> 3 -> 1, so no valid prerequisite order exists.

Input: ({1: [2], 2: [4], 3: []}, [1], {}, 1)

Expected Output: ('error', 'missing prerequisite: 4')

Explanation: Course 4 is referenced as a prerequisite of reachable course 2 but does not exist in the course dictionary.

Input: ({1: [], 2: [1]}, [2], {1: [False, False, False]}, 2)

Expected Output: ('error', 'max retries exceeded: 1')

Explanation: Course 1 is the only available course. It fails three times. With `max_retries = 2`, the third failure exceeds the limit.

Input: ({7: []}, [7], {7: [False, False, True]}, 2)

Expected Output: ('success', [7, 7, 7])

Explanation: Exactly two failed attempts are allowed here. Course 7 fails twice, then succeeds on the third attempt, so the schedule still completes successfully.

Input: ({1: [], 2: [1]}, [], {}, 3)

Expected Output: ('success', [])

Explanation: There are no target courses, so the student already satisfies all goals without attempting anything.

Hints

  1. The input edges point from course -> prerequisite, but scheduling becomes much easier if you also build the reverse relation prerequisite -> dependents and track how many prerequisites each course still needs.
  2. Detect cycles on the reachable subgraph before simulating retries. Then use a queue of currently available courses, re-enqueueing failed courses and unlocking dependents only after a prerequisite passes.
Last updated: May 20, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,500+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Solve Array Distance and Wiki Navigation - Snowflake (medium)
  • Implement Document Predicate APIs - Snowflake (medium)
  • Find Shortest Wiki Click Path - Snowflake (medium)
  • Compute Inherited Role Privileges - Snowflake (hard)
  • Solve three coding rounds - Snowflake (medium)