PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates data structures and algorithmic skills alongside system-design thinking for managing stateful in-memory storage, ownership and capacity accounting, file operations, copying, and compression.

  • medium
  • eBay
  • Coding & Algorithms
  • Software Engineer

Implement an In-Memory File System

Company: eBay

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Take-home Project

Design an in-memory file system that supports file management, search, user ownership, capacity limits, copying, and compression. Each file has a unique `name` and an integer `size`. Some files may also be owned by a user. Implement a class that supports the following operations: ### Basic file operations - `addFile(name, size) -> bool` - Add a new file. - Return `false` if a file with the same name already exists. - `getFileSize(name) -> int | None` - Return the file's current size. - Return `None` if the file does not exist. - `deleteFile(name) -> bool` - Delete the file. - Return `true` if deleted, otherwise `false`. - `listFiles() -> List[string]` - Return all files formatted as `"name(size)"`. - Sort by `size` descending. - If sizes are equal, sort by `name` ascending. ### Search and filtering - `findFiles(prefix, suffix) -> List[string]` - Return files whose names start with `prefix` and end with `suffix`. - Format each result as `"name(size)"`. - Use the same sorting rule as `listFiles()`. ### Users and storage capacity - `addUser(userId, capacity) -> bool` - Add a user with a maximum storage capacity. - Return `false` if the user already exists. - `addFileByUser(userId, name, size) -> bool` - Add a file owned by `userId`. - Return `false` if: - the user does not exist, - the file name already exists, or - adding the file would make the user's total file size exceed their capacity. ### Capacity updates - `updateCapacity(userId, newCapacity) -> int | None` - Update the user's storage capacity. - If the user's total file size is greater than `newCapacity`, remove that user's largest files first until the total size is within the limit. - Return the number of removed files. - Return `None` if the user does not exist. ### File copying - `copyFile(fromName, toName) -> bool` - Copy an existing file. - Return `false` if the source file does not exist or the destination name already exists. - The copied file must preserve the source file's size and ownership. ### Compression - `compressFile(name) -> bool` - Compress the file so its size becomes `size // 2`. - A file cannot be compressed twice in a row without first being decompressed. - Return `false` if the file does not exist. - `decompressFile(name) -> bool` - Restore a previously compressed file to its original size. - Return `false` if the file does not exist. General rules: - File names are globally unique. - Return `false` for failed boolean operations. - Return `None` only for operations that explicitly require it.

Quick Answer: This question evaluates data structures and algorithmic skills alongside system-design thinking for managing stateful in-memory storage, ownership and capacity accounting, file operations, copying, and compression.

Part 1: Implement an In-Memory File System

Design a simple in-memory file system. Each file has a unique name and an integer size. Process a sequence of operations: addFile(name, size), getFileSize(name), deleteFile(name), and listFiles(). addFile returns False if the file already exists. getFileSize returns the size or None if the file does not exist. deleteFile returns True only if the file existed and was removed. listFiles returns all files formatted as 'name(size)', sorted by size descending, then by name ascending when sizes are equal. Return the result of every operation in order.

Constraints

  • 0 <= len(operations) <= 10^4
  • 0 <= size <= 10^9
  • File names are strings of length 1 to 50
  • File names are unique within the file system

Examples

Input: [("addFile", "a", 3), ("addFile", "b", 5), ("addFile", "c", 5), ("listFiles",), ("getFileSize", "a"), ("deleteFile", "b"), ("listFiles",)]

Expected Output: [True, True, True, ['b(5)', 'c(5)', 'a(3)'], 3, True, ['c(5)', 'a(3)']]

Explanation: Files are listed by size descending. For the tie between b and c, name ascending puts b first.

Input: [("addFile", "readme", 1), ("addFile", "readme", 2), ("getFileSize", "missing"), ("deleteFile", "missing")]

Expected Output: [True, False, None, False]

Explanation: Duplicate adds fail, and operations on missing files return None or False as required.

Input: [("addFile", "beta", 4), ("addFile", "alpha", 4), ("listFiles",)]

Expected Output: [True, True, ['alpha(4)', 'beta(4)']]

Explanation: When sizes tie, sort by name ascending.

Input: [("listFiles",)]

Expected Output: [[]]

Explanation: Edge case: listing an empty file system returns an empty list.

Hints

  1. A hash map from file name to size gives O(1) average-time add, lookup, and delete.
  2. For listFiles, sort items with a key like (-size, name).

Part 2: Progressive File System - Level 1: Basic Operations

Implement only the core file-system operations: addFile(name, size), getFileSize(name), and deleteFile(name). File names must be unique. addFile returns False if the file already exists. getFileSize returns the file size or None if the file is missing. deleteFile returns True if a file was removed and False otherwise. Process all operations and return their results in order.

Constraints

  • 0 <= len(operations) <= 10^4
  • 0 <= size <= 10^9
  • File names are strings of length 1 to 50
  • No duplicate file names are allowed

Examples

Input: [("addFile", "a", 10), ("getFileSize", "a"), ("deleteFile", "a"), ("getFileSize", "a")]

Expected Output: [True, 10, True, None]

Explanation: A file can be added, queried, deleted, and then no longer found.

Input: [("addFile", "x", 1), ("addFile", "x", 2), ("deleteFile", "y")]

Expected Output: [True, False, False]

Explanation: Adding a duplicate file fails, and deleting a missing file also fails.

Input: []

Expected Output: []

Explanation: Edge case: no operations means no results.

Input: [("addFile", "solo", 7), ("deleteFile", "solo"), ("deleteFile", "solo")]

Expected Output: [True, True, False]

Explanation: Deleting the same file twice only succeeds the first time.

Hints

  1. You only need a dictionary from file name to size.
  2. Be careful about the difference between returning False and returning None.

Part 3: Progressive File System - Level 2: Search / Filtering

Extend the file system with search. Support addFile(name, size) and findFiles(prefix, suffix). findFiles must return every file whose name starts with prefix and ends with suffix at the same time. Return matching files formatted as 'name(size)', sorted by size descending and then name ascending for ties. addFile returns False when a duplicate name is inserted. Process all operations and return their results in order.

Constraints

  • 0 <= len(operations) <= 10^4
  • 0 <= size <= 10^9
  • File names, prefixes, and suffixes have length between 0 and 50
  • An empty prefix or suffix is allowed

Examples

Input: [("addFile", "apple.log", 4), ("addFile", "app_error.log", 10), ("addFile", "app.log", 10), ("findFiles", "app", ".log")]

Expected Output: [True, True, True, ['app.log(10)', 'app_error.log(10)', 'apple.log(4)']]

Explanation: All three names start with 'app' and end with '.log'. The two size-10 files are ordered by name.

Input: [("addFile", "a.txt", 2), ("addFile", "b.log", 3), ("addFile", "notes.txt", 5), ("findFiles", "", ".txt")]

Expected Output: [True, True, True, ['notes.txt(5)', 'a.txt(2)']]

Explanation: An empty prefix matches every name, so only the suffix filter matters here.

Input: [("findFiles", "pre", "suf")]

Expected Output: [[]]

Explanation: Edge case: searching an empty system returns no matches.

Input: [("addFile", "ab", 3), ("addFile", "ac", 3), ("addFile", "ab", 4), ("findFiles", "a", "")]

Expected Output: [True, True, False, ['ab(3)', 'ac(3)']]

Explanation: Duplicate adds fail. An empty suffix matches every ending.

Hints

  1. Python's startswith and endswith already handle empty strings the way you want.
  2. Collect matching files first, then sort them with the same ordering rule as listFiles.

Part 4: Progressive File System - Level 3: User and Capacity

Add users to the file system. Support addUser(userId, capacity), addFileByUser(userId, name, size), and getFileSize(name). Each user has a storage capacity, and the total size of files owned by that user must never exceed it. File names are globally unique across all users. addUser returns False if the user already exists. addFileByUser returns False if the user does not exist, the file name already exists, or the new file would exceed the user's capacity. getFileSize returns the size or None if the file is missing. Return results for all operations in order.

Constraints

  • 0 <= len(operations) <= 10^4
  • 0 <= size, capacity <= 10^9
  • User IDs and file names are strings of length 1 to 50
  • File names are unique globally

Examples

Input: [("addUser", "u1", 10), ("addFileByUser", "u1", "a", 4), ("addFileByUser", "u1", "b", 6), ("addFileByUser", "u1", "c", 1), ("getFileSize", "b")]

Expected Output: [True, True, True, False, 6]

Explanation: The third file would exceed u1's capacity of 10, so it is rejected.

Input: [("addUser", "u1", 5), ("addUser", "u2", 5), ("addFileByUser", "u3", "x", 1), ("addFileByUser", "u1", "a", 3), ("addFileByUser", "u2", "a", 1), ("getFileSize", "a")]

Expected Output: [True, True, False, True, False, 3]

Explanation: Adding for a missing user fails, and file names must stay globally unique.

Input: [("addUser", "u0", 0), ("addFileByUser", "u0", "empty", 0), ("getFileSize", "missing")]

Expected Output: [True, True, None]

Explanation: Edge case: a zero-capacity user can still store a zero-size file.

Input: [("addUser", "u1", 7), ("addUser", "u1", 9)]

Expected Output: [True, False]

Explanation: Duplicate users are not allowed.

Hints

  1. Store each user's capacity and currently used space.
  2. A second map from file name to its size and owner makes getFileSize easy.

Part 5: Progressive File System - Level 4: Capacity Update

Extend the multi-user file system with updateCapacity(userId, newCapacity). If the user's current total file size exceeds the new capacity, delete files owned by that user until the total fits. Always remove the largest files first. If multiple files have the same size, remove the lexicographically smaller name first to make the result deterministic. updateCapacity returns the number of removed files, or None if the user does not exist. Also support addUser, addFileByUser, and listFiles(), where listFiles returns all remaining files formatted as 'name(size)' sorted by size descending, then name ascending. Return results for all operations in order.

Constraints

  • 0 <= len(operations) <= 10^4
  • 0 <= size, capacity, newCapacity <= 10^9
  • User IDs and file names are strings of length 1 to 50
  • File names are unique globally

Examples

Input: [("addUser", "u1", 15), ("addFileByUser", "u1", "a", 4), ("addFileByUser", "u1", "b", 6), ("addFileByUser", "u1", "c", 3), ("updateCapacity", "u1", 7), ("listFiles",)]

Expected Output: [True, True, True, True, 1, ['a(4)', 'c(3)']]

Explanation: Shrinking from total size 13 to capacity 7 removes the largest file b(6).

Input: [("addUser", "u1", 20), ("addUser", "u2", 10), ("addFileByUser", "u1", "aa", 5), ("addFileByUser", "u1", "ab", 5), ("addFileByUser", "u1", "c", 4), ("addFileByUser", "u2", "x", 7), ("updateCapacity", "u1", 4), ("listFiles",)]

Expected Output: [True, True, True, True, True, True, 2, ['x(7)', 'c(4)']]

Explanation: u1 must drop two size-5 files. The tie is broken by name, so aa is removed before ab.

Input: [("updateCapacity", "ghost", 5)]

Expected Output: [None]

Explanation: Edge case: updating a missing user returns None.

Input: [("addUser", "u1", 8), ("addFileByUser", "u1", "a", 3), ("addFileByUser", "u1", "b", 5), ("updateCapacity", "u1", 8), ("listFiles",)]

Expected Output: [True, True, True, 0, ['b(5)', 'a(3)']]

Explanation: If the user already fits in the new capacity, no files are removed.

Hints

  1. Track each user's used space and the set of file names they own.
  2. When shrinking capacity, you only need to sort that one user's files by the required removal order.

Part 6: File Copy and Ownership

Extend the file system with copying. Support addUser(userId, capacity), addFileByUser(userId, name, size), copyFile(fromName, toName), getFileOwner(name), and getFileSize(name). copyFile should fail if the source file does not exist or the destination name already exists. A copied file keeps the same size and the same owner as the source file. Because the owner does not change, the copy also counts against that same user's capacity; if the owner does not have enough free space for the copy, the operation fails. getFileOwner returns the owner ID or None if the file is missing. Return results for all operations in order.

Constraints

  • 0 <= len(operations) <= 10^4
  • 0 <= size, capacity <= 10^9
  • User IDs and file names are strings of length 1 to 50
  • File names are unique globally

Examples

Input: [("addUser", "u1", 10), ("addFileByUser", "u1", "report", 4), ("copyFile", "report", "backup"), ("getFileOwner", "backup"), ("getFileSize", "backup")]

Expected Output: [True, True, True, 'u1', 4]

Explanation: The copy succeeds, keeps the same owner, and has the same size as the original.

Input: [("addUser", "u1", 15), ("addFileByUser", "u1", "a", 4), ("addFileByUser", "u1", "b", 1), ("copyFile", "a", "b")]

Expected Output: [True, True, True, False]

Explanation: Copying fails because the destination name already exists.

Input: [("addUser", "u1", 5), ("copyFile", "missing", "x"), ("getFileOwner", "x")]

Expected Output: [True, False, None]

Explanation: Edge case: copying a non-existent source fails.

Input: [("addUser", "u1", 7), ("addFileByUser", "u1", "a", 4), ("copyFile", "a", "b"), ("getFileSize", "b")]

Expected Output: [True, True, False, None]

Explanation: The copy would raise u1's used storage from 4 to 8, exceeding capacity 7.

Hints

  1. Store both size and owner for every file.
  2. When copying, check destination existence, source existence, and the owner's remaining capacity in that order.

Part 7: Compression Feature

Add compression support to the file system. Support addFile(name, size), compressFile(name), decompressFile(name), and getFileSize(name). When a file is compressed, its current size becomes size // 2. Decompressing restores the original size from before compression. A file cannot be compressed twice in a row without being decompressed first. decompressFile should return False if the file does not exist or is not currently compressed. Return the result of every operation in order.

Constraints

  • 0 <= len(operations) <= 10^4
  • 0 <= size <= 10^9
  • File names are strings of length 1 to 50
  • File names are unique

Examples

Input: [("addFile", "doc", 9), ("compressFile", "doc"), ("getFileSize", "doc"), ("decompressFile", "doc"), ("getFileSize", "doc")]

Expected Output: [True, True, 4, True, 9]

Explanation: Compression uses integer division, and decompression restores the original size exactly.

Input: [("addFile", "x", 8), ("compressFile", "x"), ("compressFile", "x"), ("getFileSize", "x")]

Expected Output: [True, True, False, 4]

Explanation: A file cannot be compressed twice without an intervening decompression.

Input: [("addFile", "y", 5), ("decompressFile", "y"), ("getFileSize", "y")]

Expected Output: [True, False, 5]

Explanation: Edge case: decompressing an uncompressed file fails.

Input: [("addFile", "tiny", 1), ("compressFile", "tiny"), ("getFileSize", "tiny"), ("decompressFile", "tiny"), ("getFileSize", "tiny"), ("compressFile", "missing")]

Expected Output: [True, True, 0, True, 1, False]

Explanation: A size-1 file compresses to 0, and a missing file cannot be compressed.

Hints

  1. For each file, store both the current size and the original size.
  2. A boolean compressed flag is enough to prevent invalid double-compress or invalid decompress.
Last updated: Apr 19, 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

  • Format Words into Fixed-Width Lines - eBay (medium)
  • Assign Ads to Browser Positions - eBay (medium)
  • Solve Dependency, Prefix, and Cache Problems - eBay (medium)
  • Find top co-viewed products - eBay (hard)
  • Implement bitmap-based block allocator - eBay (medium)