FastPrepMultiline Text Editor with Cursor Movement
Problem · Stack

Multiline Text Editor with Cursor Movement

Learn this problem
MediumDatologyAI logoDatologyAIFULLTIMEPHONE SCREEN

Problem statement

Implement a text editor that begins with one empty line and a cursor at column 0 of that line. A cursor is a gap between characters: column 0 is before the first character and column equal to the line length is after the last.

Process operations in order. Each row is one of the following:

  • ["INSERT", text]: insert the lowercase letters in text at the cursor, without overwriting existing characters. The cursor ends immediately after the inserted text.
  • ["BACKSPACE"]: remove the character immediately before the cursor. At the beginning of a non-first line, remove the preceding newline instead, joining this line onto the previous line and leaving the cursor at the join. At the beginning of the whole document, do nothing.
  • ["NEWLINE"]: split the current line at the cursor. The suffix becomes a new next line, and the cursor moves to column 0 of that new line.
  • ["LEFT"] or ["RIGHT"]: move one character gap horizontally. Moving left from a line's beginning crosses the preceding newline to the previous line's end. Moving right from a line's end crosses the following newline to the next line's beginning. At the document's outer boundaries, do nothing.
  • ["UP"] or ["DOWN"]: move to the adjacent line, keeping the current column if it exists there; otherwise use that line's end. If there is no adjacent line in that direction, do nothing. Each move uses the current column: there is no remembered preferred column after a shorter line clamps it.
  • ["PRINT"]: record an independent snapshot of every line in document order, including empty lines. Printing does not move the cursor.

Return a String[][] containing one row per PRINT. Each such row contains the strings for all lines at that moment; line separators are represented by separate strings, not embedded newline characters. The empty document prints as [""]. Return an empty outer array if there are no PRINT operations. The cursor is not included in the output.

Function

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

Examples

Example 1

operations = [["INSERT","abc"],["LEFT"],["NEWLINE"],["INSERT","x"],["PRINT"],["UP"],["INSERT","z"],["PRINT"]]return = [["ab","xc"],["azb","xc"]]

After inserting abc, moving left and splitting, the lines are ab and c. Inserting x produces xc with the cursor at column one. UP moves to column one of ab, so inserting z makes azb. The first snapshot remains unchanged.

Example 2

operations = [["INSERT","abcd"],["NEWLINE"],["INSERT","x"],["NEWLINE"],["INSERT","wxyz"],["UP"],["UP"],["INSERT","q"],["PRINT"]]return = [["aqbcd","x","wxyz"]]

The cursor starts the two UP moves at column four of wxyz. Moving to the one-letter middle line clamps it to column one. Moving up again keeps that new column one, not the old column four. Inserting q therefore produces aqbcd.

Constraints

  • 0 ≤ operations.length ≤ 100.
  • Every row is a valid operation with the stated number of fields.
  • Each INSERT text contains from 1 through 20 lowercase English letters and no newline. NEWLINE is the only way to create a line separator.
  • There are at most 20 PRINT operations. Movement and backspace at boundaries are valid no-ops as specified.
drafts saved locally
public String[][] runCursorEditor(String[][] operations) {
    // Write your code here
}
operations[["INSERT","abc"],["LEFT"],["NEWLINE"],["INSERT","x"],["PRINT"],["UP"],["INSERT","z"],["PRINT"]]
expected[["ab", "xc"], ["azb", "xc"]]
checking account