File Storage Service
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 arefile-1,file-2, and so on, in upload order. An ID is never reused, even after its file is deleted.timestampis the upload time; store it as given.["GET", fileId]returns the file's content, orERRORif no stored file has that ID. A file with empty content returns an empty string.["DELETE", fileId]deletes the file and returnstrue, or returnsfalseif no stored file has that ID.["LIST"]returns the metadata of every stored file in upload order, asfileId|fileName|fileSize|uploadTimestampentries joined by;.fileSizeis 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:
- Split
fileNameat 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. - Use the smallest
k >= 1for whichstem + " (" + k + ")" + extensionis 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 most2operations areLIST.- Every operation has one of the four forms above.
fileNamehas 1 to 20 characters, each a letter, digit,.,_,-, space,(or), and it does not start or end with a space.contenthas 0 to 20 characters, each a lowercase letter or digit.timestampis a decimal integer from0to10^6without leading zeros, and timestamps never decrease from one upload to the next.fileIdinGETandDELETEhas 1 to 12 characters, each a lowercase letter, digit or-.