Imagine you're a master chef with a cookbook of recipes and a pantry full of supplies. Your challenge is to determine which recipes you can actually cook!
You have n different recipes, where each recipe has a name and requires specific ingredients. Here's the twist: some recipes can serve as ingredients for other recipes. For example, you might need "dough" to make "pizza", but "dough" itself is another recipe in your cookbook.
Given:
recipes[] - Array of recipe names
ingredients[][] - 2D array where ingredients[i] contains all ingredients needed for recipes[i]
supplies[] - Array of ingredients you initially have (infinite supply)
Goal: Return a list of all recipes you can make, considering that recipes can depend on other recipes. The order doesn't matter.
Note: Two recipes may contain each other in their ingredients (circular dependencies), but you should only return recipes that can actually be completed.
💡 Note:First we make bread using yeast and flour. Then we can make sandwich using the bread we just made plus meat from our supplies. Both recipes are possible.
💡 Note:We can't make bread because we're missing flour. Since bread can't be made, sandwich also can't be made (it needs bread as an ingredient). No recipes are possible.
Find All Possible Recipes from Given Supplies — Solution
The optimal solution uses topological sorting to resolve recipe dependencies. We model this as a directed graph where recipes depend on their ingredients, then use Kahn's algorithm to process recipes in the correct order. This achieves O(R + I) time complexity where R is recipes and I is total ingredient relationships.
Common Approaches
✓
Brute Force (Repeated Attempts)
⏱️ Time: O(R² × I)
Space: O(R + S)
Repeatedly iterate through all recipes, trying to make each one with currently available ingredients. Continue until a full pass produces no new recipes. This mimics trying recipes randomly without understanding dependencies.
Topological Sort (Optimal)
⏱️ Time: O(R + I)
Space: O(R + I)
Model this as a directed graph where each recipe points to recipes that depend on it. Use topological sorting to process recipes in dependency order, ensuring we make prerequisite recipes before dependent ones.
Brute Force (Repeated Attempts) — Algorithm Steps
Start with initial supplies as available ingredients
Repeat: try each recipe to see if all ingredients are available
If recipe can be made, add it to results and mark as available ingredient
Continue until no new recipes are made in a complete pass
Return all successfully made recipes
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Initial State
Start with supplies: [yeast, flour]. Try all recipes.
2
First Pass
Can make bread (needs yeast, flour). Add bread to available.
3
Second Pass
Can make sandwich (needs bread, ham). But no ham available.
4
No Progress
No new recipes possible. Return [bread].
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_RECIPES 1000
#define MAX_INGREDIENTS 1000
#define MAX_NAME_LEN 100
#define MAX_LINE_LEN 10000
static char recipes[MAX_RECIPES][MAX_NAME_LEN];
static char ingredients[MAX_RECIPES][MAX_INGREDIENTS][MAX_NAME_LEN];
static int ingredient_counts[MAX_RECIPES];
static char supplies[MAX_INGREDIENTS][MAX_NAME_LEN];
static char result[MAX_RECIPES][MAX_NAME_LEN];
static bool available[MAX_RECIPES];
static int indegree[MAX_RECIPES];
static int adj_list[MAX_RECIPES][MAX_RECIPES];
static int adj_count[MAX_RECIPES];
static int queue[MAX_RECIPES];
int find_recipe_index(char* name, int recipe_count) {
for (int i = 0; i < recipe_count; i++) {
if (strcmp(recipes[i], name) == 0) {
return i;
}
}
return -1;
}
bool is_supply_available(char* name, int supply_count) {
for (int i = 0; i < supply_count; i++) {
if (strcmp(supplies[i], name) == 0) {
return true;
}
}
return false;
}
void parse_string_array(char* line, char result[][MAX_NAME_LEN], int* count) {
*count = 0;
int len = strlen(line);
int i = 0;
// Skip leading whitespace and find '['
while (i < len && line[i] != '[') i++;
if (i >= len) return;
i++; // skip '['
while (i < len && line[i] != ']') {
// Skip whitespace and commas
while (i < len && (line[i] == ' ' || line[i] == ',' || line[i] == '\n' || line[i] == '\r')) i++;
if (i >= len || line[i] == ']') break;
// Parse string
if (line[i] == '"') {
i++; // skip opening quote
int j = 0;
while (i < len && line[i] != '"' && j < MAX_NAME_LEN - 1) {
result[*count][j++] = line[i++];
}
result[*count][j] = '\0';
if (i < len && line[i] == '"') i++; // skip closing quote
(*count)++;
}
}
}
void parse_2d_array(char* line, int recipe_count) {
int len = strlen(line);
int i = 0;
int recipe_idx = 0;
// Skip to first '['
while (i < len && line[i] != '[') i++;
if (i >= len) return;
i++; // skip outer '['
while (i < len && line[i] != ']' && recipe_idx < recipe_count) {
// Skip whitespace and commas
while (i < len && (line[i] == ' ' || line[i] == ',' || line[i] == '\n' || line[i] == '\r')) i++;
if (i >= len || line[i] == ']') break;
// Parse inner array
if (line[i] == '[') {
i++; // skip '['
ingredient_counts[recipe_idx] = 0;
while (i < len && line[i] != ']') {
// Skip whitespace and commas
while (i < len && (line[i] == ' ' || line[i] == ',' || line[i] == '\n' || line[i] == '\r')) i++;
if (i >= len || line[i] == ']') break;
// Parse string
if (line[i] == '"') {
i++; // skip opening quote
int j = 0;
while (i < len && line[i] != '"' && j < MAX_NAME_LEN - 1) {
ingredients[recipe_idx][ingredient_counts[recipe_idx]][j++] = line[i++];
}
ingredients[recipe_idx][ingredient_counts[recipe_idx]][j] = '\0';
if (i < len && line[i] == '"') i++; // skip closing quote
ingredient_counts[recipe_idx]++;
}
}
if (i < len && line[i] == ']') i++; // skip ']'
recipe_idx++;
}
}
}
int solve_recipes(int recipe_count, int supply_count) {
// Initialize
for (int i = 0; i < recipe_count; i++) {
available[i] = false;
indegree[i] = 0;
adj_count[i] = 0;
}
// Build dependency graph
for (int i = 0; i < recipe_count; i++) {
for (int j = 0; j < ingredient_counts[i]; j++) {
char* ingredient = ingredients[i][j];
int dep_recipe = find_recipe_index(ingredient, recipe_count);
if (dep_recipe != -1) {
// This recipe depends on another recipe
adj_list[dep_recipe][adj_count[dep_recipe]++] = i;
indegree[i]++;
}
}
}
// Initialize queue with recipes that have no recipe dependencies
int front = 0, rear = 0;
for (int i = 0; i < recipe_count; i++) {
if (indegree[i] == 0) {
// Check if all ingredients are available from supplies
bool can_make = true;
for (int j = 0; j < ingredient_counts[i]; j++) {
if (!is_supply_available(ingredients[i][j], supply_count)) {
can_make = false;
break;
}
}
if (can_make) {
queue[rear++] = i;
available[i] = true;
}
}
}
// Process queue (Kahn's algorithm)
while (front < rear) {
int current = queue[front++];
// Check all recipes that depend on current recipe
for (int i = 0; i < adj_count[current]; i++) {
int dependent = adj_list[current][i];
indegree[dependent]--;
if (indegree[dependent] == 0) {
// Check if all ingredients are now available
bool can_make = true;
for (int j = 0; j < ingredient_counts[dependent]; j++) {
char* ingredient = ingredients[dependent][j];
int recipe_idx = find_recipe_index(ingredient, recipe_count);
if (recipe_idx != -1) {
// It's a recipe ingredient
if (!available[recipe_idx]) {
can_make = false;
break;
}
} else {
// It's a supply ingredient
if (!is_supply_available(ingredient, supply_count)) {
can_make = false;
break;
}
}
}
if (can_make) {
queue[rear++] = dependent;
available[dependent] = true;
}
}
}
}
// Collect results
int result_count = 0;
for (int i = 0; i < recipe_count; i++) {
if (available[i]) {
strcpy(result[result_count], recipes[i]);
result_count++;
}
}
return result_count;
}
int main() {
char line[MAX_LINE_LEN];
int recipe_count = 0, supply_count = 0;
// Read recipes
if (fgets(line, sizeof(line), stdin)) {
parse_string_array(line, recipes, &recipe_count);
}
// Read ingredients
if (fgets(line, sizeof(line), stdin)) {
parse_2d_array(line, recipe_count);
}
// Read supplies
if (fgets(line, sizeof(line), stdin)) {
parse_string_array(line, supplies, &supply_count);
}
// Solve
int result_count = solve_recipes(recipe_count, supply_count);
// Output result
printf("[");
for (int i = 0; i < result_count; i++) {
if (i > 0) printf(",");
printf("\"%s\"", result[i]);
}
printf("]\n");
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(R² × I)
R recipes × R iterations (worst case) × I average ingredients per recipe
n
2n
✓ Linear Growth
Space Complexity
O(R + S)
Space for result list and set of available ingredients
n
2n
✓ Linear Space
39.2K Views
MediumFrequency
~25 minAvg. Time
1.7K Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.