In-Memory Filesystem Commands
Reported by candidates from Perplexity AI's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
Perplexity AI reportedly dropped this one in September 2026, and it looks scarier than it is. It's a design problem in disguise: a trie of directory nodes plus a pointer to the current directory. Six commands, one string back per command, and a pile of edge cases around what counts as a valid removal. If your OA invite lands in the next day or two, this is the shape to expect. Nothing here needs a fancy algorithm. It needs clean node modeling and discipline about rejection rules. StealthCoder sits invisibly on your screen as a safety net if you blank mid-assessment, but the build is simple enough to hold in your head.
The problem
Process a sequence of commands against an in-memory filesystem. The root directory / exists initially, and the current directory starts at the root. Paths beginning with / are absolute; every other path is resolved beneath the current directory. ["MKDIR", path] creates one empty directory when its parent directory exists and the path is unused. ["TOUCH", path] creates one file under an existing directory when the path is unused. ["LS", path] lists the immediate child names of an existing directory in lexicographic order, joined by commas. ["RM", path] removes an existing file. ["RMDIR", path] removes an existing empty directory unless it is the root, the current directory, or an ancestor of the current directory. ["CD", path] changes the current directory when the path identifies an existing directory. Return one string per command. A successful mutation or directory change returns "true", while a rejected one returns "false". A failed LS returns "NULL"; listing an empty directory returns the empty string. Function runFileSystem(operations: String[][]) → String[] Examples Example 1 operations = [["MKDIR","/docs"],["TOUCH","/docs/readme"],["CD","/docs"],["MKDIR","drafts"],["TOUCH","drafts/plan"],["LS","/docs"],["CD","drafts"],["RM","plan"],["RMDIR","/docs"],["CD","/"],["RMDIR","/docs/drafts"],["LS","/docs"]] return = ["true","true","true","true","true","drafts,readme","true","true","false","true","true","readme"] Relative paths use the current directory. An ancestor of the current directory cannot be removed, but the empty drafts directory can be removed after returning to the root. Example 2 operations = [["MKDIR","/b"],["MKDIR","/a"],["TOUCH","/a/z"],["TOUCH","/a/m"],["LS","/"],["LS","/a"],["LS","/a/z"],["CD","/missing"],["RM","/a"],["RMDIR","/"]] return = ["true","true","true","true","a,b","m,z","NULL","false","false","false"] Listings are lexicographic, LS on a file returns NULL, and commands reject targets of the wrong type. Constraints 1 <= operations.length <= 100000 Every operation has exactly one documented shape. A path is either / or a canonical absolute or relative path. Non-root paths contain one or more lowercase ASCII letter, digit, or underscore components separated by single slashes, with no leading slash for relative paths and no trailing slash. Paths do not contain. or.. components. Each path has at most 100 components and at most 1000 characters. The total number of characters across all operations is at most 1000000. The total number of child names emitted by all successful LS commands is at most 200000.
Reported by candidates. Source: FastPrep
Pattern and pitfall
Model each node with a type flag and a children map. Resolve a path by splitting on slash and walking from the root for absolute paths or from the current node for relative ones. Return null on any missing step or when you hit a file mid-walk. For MKDIR and TOUCH, resolve the parent, then check the final name is unused. LS sorts child names only at listing time, which the emitted-names cap makes cheap. The real pitfall is RMDIR. Rejecting the root, the current directory, and every ancestor of the current directory is the hard part. Keep a parent pointer on each node, or store the current path as a list of nodes, then compare. Also check types: RM on a directory fails, RMDIR on a file fails, LS on a file gives NULL. If you freeze on the ancestor check, StealthCoder is the hedge during the live OA, but walk the parent chain and you're done.
The honest play: practice the pattern, and have StealthCoder ready for the one you didn't see coming.
You can drill In-Memory Filesystem Commands cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Built for the candidate who saw this exact problem leak two days before his OA and wondered if anyone had a play.
Get StealthCoderRelated leaked OAs
This OA pattern shows up on LeetCode as design in memory file system. If you have time before the OA, drill that.
You've seen the question.
Make sure you actually pass Perplexity AI's OA.
Perplexity AI reuses patterns across OAs. Built for the candidate who saw this exact problem leak two days before his OA and wondered if anyone had a play. Works on HackerRank, CodeSignal, CoderPad, and Karat.
In-Memory Filesystem Commands FAQ
How hard is the In-Memory Filesystem Commands problem really?+
Medium at most. There's no tricky algorithm. It's a tree with a map of children per node. The difficulty is the pile of rejection rules, especially RMDIR, and getting each command's true, false, or NULL output exactly right.
What's the trick for RMDIR?+
Reject if the target is the root, the current directory, or an ancestor of it. Easiest way: store parent pointers, then walk up from the current directory to the root and compare each node to the target. Also require the target to be an empty directory.
How should I resolve relative versus absolute paths?+
If the path is exactly slash, return the root. If it starts with slash, start at the root. Otherwise start at the current directory node. Split on slash and walk child by child. Fail if a component is missing or a non-final component is a file.
Do I need to worry about performance with 100000 operations?+
Not much. Each path has at most 100 components, so a walk is cheap with hash map children. Sort only inside LS, and the cap on total emitted names keeps that bounded. Avoid copying subtrees or rebuilding path strings on every command.
How do I prepare for this in 48 hours?+
Code the whole thing once from scratch using the two examples as tests. Write a node class, a resolve function returning a node or null, and one handler per command. Then hand-test the edge cases: LS on a file, RMDIR on the root, CD into a file.