FastPrepFile Storage Service

File Storage Service

Cresta logoCresta● MediumNEW GRADPHONE SCREEN

Problem statement

Build a small in-memory file storage service. Process operations in order and return one string for each operation.

  • ["UPLOAD", fileName, content, timestamp] stores a file and returns its new ID. IDs are file-1, file-2, and so on, in upload order. An ID is never reused, even after its file is deleted. timestamp is the upload time; store it as given.
  • ["GET", fileId] returns the file's content, or ERROR if no stored file has that ID. A file with empty content returns an empty string.
  • ["DELETE", fileId] deletes the file and returns true, or returns false if no stored file has that ID.
  • ["LIST"] returns the metadata of every stored file in upload order, as fileId|fileName|fileSize|uploadTimestamp entries joined by ;. fileSize is the number of characters in the content, which equals its size in bytes. With no stored files, return an empty string.

Duplicate names. If a file that is currently stored already has the name fileName, store the new file under a new name instead:

  1. Split fileName at its last dot into a stem and an extension that starts with that dot. If the name has no dot, or its last dot is its first character, the whole name is the stem and the extension is empty.
  2. Use the smallest k >= 1 for which stem + " (" + k + ")" + extension is not the name of a stored file.

For example, a second a.txt becomes a (1).txt, a copy of archive.tar.gz becomes archive.tar (1).gz, and a copy of .env becomes .env (1). Names of deleted files are free again. GET and LIST report the stored name.

Function

runFileStorage(operations: String[][]) → String[]

Examples

Example 1

operations = [["UPLOAD","a.txt","hello","10"],["UPLOAD","a.txt","world","12"],["UPLOAD","b","","12"],["LIST"],["GET","file-2"],["DELETE","file-1"],["GET","file-1"],["DELETE","file-1"],["UPLOAD","a.txt","again","20"],["LIST"]]return = ["file-1","file-2","file-3","file-1|a.txt|5|10;file-2|a (1).txt|5|12;file-3|b|0|12","world","true","ERROR","false","file-4","file-2|a (1).txt|5|12;file-3|b|0|12;file-4|a.txt|5|20"]

The second a.txt is renamed a (1).txt. b has empty content, so its size is 0. After file-1 is deleted, getting it returns ERROR and deleting it again returns false. The name a.txt is free again, so the last upload keeps it and gets the new ID file-4.

Example 2

operations = [["UPLOAD","report.txt","v1","1"],["UPLOAD","report.txt","v2","2"],["UPLOAD","report.txt","v3","3"],["DELETE","file-2"],["UPLOAD","report.txt","v4","4"],["UPLOAD","report (1).txt","v5","5"],["GET","file-3"],["LIST"]]return = ["file-1","file-2","file-3","true","file-4","file-5","v3","file-1|report.txt|2|1;file-3|report (2).txt|2|3;file-4|report (1).txt|2|4;file-5|report (1) (1).txt|2|5"]

Uploads 2 and 3 become report (1).txt and report (2).txt. Deleting file-2 frees report (1).txt, so the fourth report.txt takes that name again. Uploading report (1).txt while that name is taken adds a suffix to its own stem: report (1) (1).txt.

Example 3

operations = [["UPLOAD","archive.tar.gz","x1","7"],["UPLOAD","archive.tar.gz","x2","7"],["UPLOAD",".env","k","8"],["UPLOAD",".env","k2","9"],["UPLOAD","notes","","9"],["UPLOAD","notes","n","9"],["GET","file-5"],["GET","file-9"],["LIST"]]return = ["file-1","file-2","file-3","file-4","file-5","file-6","","ERROR","file-1|archive.tar.gz|2|7;file-2|archive.tar (1).gz|2|7;file-3|.env|1|8;file-4|.env (1)|2|9;file-5|notes|0|9;file-6|notes (1)|1|9"]

The extension starts at the last dot, so the copy of archive.tar.gz is archive.tar (1).gz. In .env the only dot is the first character, so there is no extension and the copy is .env (1). notes has no dot. Getting file-5 returns its empty content, while file-9 never existed.

Constraints

  • 1 <= operations.length <= 300, and at most 2 operations are LIST.
  • Every operation has one of the four forms above.
  • fileName has 1 to 20 characters, each a letter, digit, ., _, -, space, ( or ), and it does not start or end with a space.
  • content has 0 to 20 characters, each a lowercase letter or digit.
  • timestamp is a decimal integer from 0 to 10^6 without leading zeros, and timestamps never decrease from one upload to the next.
  • fileId in GET and DELETE has 1 to 12 characters, each a lowercase letter, digit or -.

More Cresta problems

See Cresta hiring insights
Saved
public String[] runFileStorage(String[][] operations) {
    // Write your code here.
}
Checking account…