Versioned Recipe System
Learn this problemProblem statement
Implement an in-memory recipe management system. The system receives a list of commands and returns one output string for each command.
Each recipe has a unique recipe_id, an owning user_id, a name, content, and a version number starting from 1.
Version Rules
ADDcreates versionv1.UPDATEcreates a new version only if eithernameorcontentdiffers from the current latest version. If both are unchanged, keep the current latest version.ROLLBACKdoes not delete history. It copies the target historical version into a new latest version.DELETEmarks a recipe as deleted. Deleted recipes are hidden from ordinaryGET,LIST, andSEARCH, but version-specificGETandHISTORYcan still inspect history.
Permissions
Only the owning user can run UPDATE, DELETE, or ROLLBACK. If another user attempts one of these commands, return FORBIDDEN.
Commands
Each command is a string whose fields are separated by |:
ADD|recipe_id|user_id|name|content
GET|recipe_id
GET|recipe_id|version
UPDATE|recipe_id|user_id|name|content
DELETE|recipe_id|user_id
LIST
LIST|user_id
SEARCH|keyword
HISTORY|recipe_id
ROLLBACK|recipe_id|user_id|versionOutput Rules
ADDsuccess:OK v1UPDATEsuccess:OK vXDELETEsuccess:OKROLLBACKsuccess:OK vXGETsuccess:recipe_id|user_id|vX|name|contentLISTandSEARCHsuccess: entries joined by;, where each entry isrecipe_id:vX:name.HISTORYsuccess: all versions joined by;, where each entry isvX:name.- No matching visible result:
EMPTY - Missing recipe or invalid version:
NOT_FOUND - Permission failure:
FORBIDDEN - Other invalid operations, such as adding a duplicate
recipe_id:ERROR
LIST and SEARCH results are sorted by recipe_id in lexicographic order. SEARCH|keyword matches active latest recipes where keyword is a case-insensitive substring of the latest name or content.
Function
processRecipeCommands(commands: String[]) β String[]Examples
Example 1
commands = ["ADD|r1|u1|Pasta|tomato", "GET|r1", "UPDATE|r1|u1|Pasta|tomato basil", "GET|r1|1", "GET|r1", "HISTORY|r1", "UPDATE|r1|u1|Pasta|tomato basil", "HISTORY|r1"]return = ["OK v1", "r1|u1|v1|Pasta|tomato", "OK v2", "r1|u1|v1|Pasta|tomato", "r1|u1|v2|Pasta|tomato basil", "v1:Pasta;v2:Pasta", "OK v2", "v1:Pasta;v2:Pasta"]The first update changes the content, so it creates v2. The version-specific GET|r1|1 still returns the original content. The second update is identical to the latest version, so no new version is created.
Example 2
commands = ["ADD|r2|u2|Salad|greens", "UPDATE|r2|u3|Salad|greens and oil", "LIST|u2", "SEARCH|GREEN", "DELETE|r2|u2", "GET|r2", "HISTORY|r2"]return = ["OK v1", "FORBIDDEN", "r2:v1:Salad", "r2:v1:Salad", "OK", "NOT_FOUND", "v1:Salad"]User u3 cannot update a recipe owned by u2. After deletion, ordinary GET does not expose the recipe, but HISTORY can still show its prior version.
Constraints
1 <= commands.length <= 10^5recipe_id,user_id,name,content, andkeywordeach have length at most100.- Fields do not contain the character
|.