Simulate an In-Memory Directory Tree with mkdir, ls, Append and Read
GoogleSoftware Engineer · OtherLast updated
A Google coding problem that simulates an in-memory file system through a sequence of mkdir, ls, add and read operations, with missing directories created on demand and existing files appended to. It tests tree modeling, path parsing, sorted directory listings and precise operation semantics.
Reported from a Google software engineering coding interview.
Simulate a small in-memory file system. It starts with only the root directory /. You receive a sequence of operations and must return the output of each one, in order.
The four operations are:
mkdir path: create the directory atpath, also creating any missing directories along the way. If the directory already exists, do nothing. Output:[].add path content: if no file exists atpath, create it (creating any missing directories along the way) withcontentas its text. If the file already exists, appendcontentto the end of its current text. Output:[].read path: output the file's full current text as a one-element list,[text].ls path: ifpathis a file, output a one-element list containing the file's own name. Ifpathis a directory, output the names of its direct children (both files and directories), sorted in ascending lexicographic order. An empty directory outputs[].
Function Signature
def simulate_file_system(operations: list[str], arguments: list[list[str]]) -> list[list[str]]:
operations[i] is one of "mkdir", "add", "read", "ls". arguments[i] is [path] for mkdir, read and ls, and [path, content] for add. Return a list with exactly one output per operation.
Rules
- Every path is absolute: it starts with
/, components are separated by single/characters, and there is no trailing/except for the root path/itself. lsmay be called on/;mkdirandaddare never called on/.- A name inside one directory refers to either a file or a directory, never both. Inputs never use a file as if it were a directory (no path passes through an existing file), never
mkdiran existing file path, and neveraddto an existing directory path. readis only called on existing files, andlsonly on existing paths.- Names contain only lowercase letters, so ascending order is plain string comparison.
Constraints
1 <= len(operations) == len(arguments) <= 3001 <= len(path) <= 100- Each path component is a non-empty string of lowercase letters
atoz. 1 <= len(content) <= 50, lowercase letters only.
Examples
Example 1
- Input:
operations = ["ls", "mkdir", "add", "ls", "read"]arguments = [["/"], ["/a/b/c"], ["/a/b/c/d", "hello"], ["/"], ["/a/b/c/d"]]- Output:
[[], [], [], ["a"], ["hello"]] - Explanation: the root starts empty.
mkdircreates/a,/a/band/a/b/c;addcreates the filedinside/a/b/c. Listing the root shows onlya.
Example 2
- Input:
operations = ["add", "add", "mkdir", "ls", "ls", "read"]arguments = [["/notes", "ab"], ["/notes", "cd"], ["/docs/old"], ["/"], ["/notes"], ["/notes"]]- Output:
[[], [], [], ["docs", "notes"], ["notes"], ["abcd"]] - Explanation: the second
addappends to the existing file. Listing the root returns the directorydocsand the filenotesin sorted order; listing a file path returns just that file's name.
Example 3
- Input:
operations = ["mkdir", "add", "add", "ls", "mkdir", "ls"]arguments = [["/x/zeta"], ["/x/alpha", "q"], ["/x/mid/file", "r"], ["/x"], ["/x/zeta"], ["/x/mid"]]- Output:
[[], [], [], ["alpha", "mid", "zeta"], [], ["file"]] - Explanation:
/xends up holding the filealphaand the directoriesmidandzeta. Creating/x/zetaa second time changes nothing.
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.