Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Implement a simplified version of text editor

Scenario

Your task is to implement a simplified version of text editor.

All operations that should be supported are listed below. Partial credit will be given for each implemented operation. Please submit often to ensure partial credits are captured.

Implementation tips

Implement operations and provided steps one by one, and not all together, keeping in mind that you will need to make refactors to support each additional step. In the first three levels you can assume that only one text document is modified.

Note

As a result, for every operation that potentially modifies the document (APPEND, BACKSPACE, PASTE, UNDO, and REDO), append the current state of the text after applying the operation, to the results.

Level 1

The editor starts with a blank text document, with the cursor at initial position 0.

  1. APPEND should append the inputted string text to the document starting from the current position of the cursor. After the operation, the cursor should be at the end of the added string.
queries = [
    ["APPEND", "Hey"],               | "" -> "Hey"
    ["APPEND", " there"],            | "Hey" -> "Hey there"
    ["APPEND", "!"]                  | "Hey there" -> "Hey there!"
]

// returns: "Hey there!"
  1. MOVE should move the cursor to the specified position. The cursor should be positioned between document characters, and are enumerated sequentially starting from 0. If the specified position is out of bounds, then move the cursor to the nearest available position.
queries = [
    ["APPEND", "Hey you"],           | "" -> "Hey you"
    ["MOVE", "3"],                   | moves the cursor after the first "y"
    ["APPEND", ","]                  | "Hey you" -> "Hey, you"
]

// returns: "Hey, you"
  1. BACKSPACE should remove the character right before the cursor, if any.
queries = [
    [APPEND", "Hey you"],            | "" -> "Hey you"
    ["BACKSPACE"],                   | "Hey you" -> "Hey yo"
    ["BACKSPACE"]                    | "Hey yo" -> "Hey y"
]

// returns: "Hey y"

and

queries = [
    ["APPEND", "!"],                 | "" -> "!"
    ["BACKSPACE"],                   | "!" -> ""
    ["BACKSPACE"]                    | "" -> ""
]

// returns: ""

Level 2

Introduce methods to copy a part of the document text.

  1. SELECT should select the text between the left and right cursor positions. Selection borders should be returned to the bounds of the document. If the selection is empty, it becomes a cursor position. Any modification operation replace the selected text and places the cursor at the end of the modified segment.

For example, the following operations

queries = [
    ["APPEND", "Hello cruel world!"],  | "" -> "Hello cruel world!"
    ["SELECT", "5", "11"],             | selects " cruel"
    ["APPEND", ","]                    | "Hello cruel world!" -> "Hello, world!"
  ]

produce "Hello, world!" with the cursor positioned after the comma.

SELECT and APPEND should replace the selected characters with the appended characters:

queries = [
    ["APPEND", "Hello"],               | "" -> "Hello"        
    ["SELECT", "2", "5"],              | Selects a substring "llo"
    ["APPEND", "y there"]              | "Hello" -> "Hey there"
]

// returns: "Hey there"
  1. COPY should copy the selected text to the clipboard, if there is an active non-empty selection.
  2. PASTE should append the text from the clipboard.

For example, the following operations

queries = [
    ["APPEND", "Hello, world!"],       | "" -> "Hello, world!"
    ["SELECT", "5", "12"],             | selects ", world"
    ["COPY"],                          | copies ", world"
    ["MOVE", "12"],                    | moves the cursor to after "d"
    ["PASTE"],                         | "Hello, world!" -> "Hello, world, world!"
    ["PASTE"]                          | "Hello, world, world!" -> "Hello, world, world, world!"
]

produce "Hello, world, world, world!".

Level 3

The text editor should allow document changes to be tracked and reverted. Consider only operations that actually modify the contents of the text document.

  1. UNDO should restore the document to the state before the previous modification or REDO operation. The selection and cursor position should be also restored.

For example,

queries = [
    ["APPEND", "Hello, world!"],       | "" -> "Hello, world!"
    ["SELECT", "7", "12"],             | selects "world"
    ["BACKSPACE"],                     | "Hello, world!" -> "Hello, !"
    ["UNDO"],                          | restores "Hello, world!" with "world" selected 
    ["APPEND", "you"]                  | "Hello, world!" -> "Hello, you!"
]

// returns "Hello, you!"
  1. REDO can only be performed if the document has not been modified since the last UNDO operation. REDO should restore the state before the previous UNDO operation, including the selection and cursor position. Multiple UNDO and REDO operations can be performed in a row.

For example,

queries = [
    ["APPEND", "Hello, world!"],       | "" -> "Hello, world!"
    ["SELECT", "7", "12"],             | selects "world"
    ["BACKSPACE"],                     | "Hello, world!" -> "Hello, !"
    ["MOVE", "6"],                     | moves the cursor to after the comma 
    ["UNDO"],                          | restores "Hello, world!" with "world" selected 
    ["UNDO"],                          | restores initial ""
    ["REDO"],                          | restores "Hello, world!" with "world" selected
    ["REDO"]                           | restores "Hello, !" with the cursor after the comma
]

// Returns "Hello, !"

Level 4

The text editor should support multiple text documents with a common clipboard.

  1. CREATE should create a blank text document name. If such a file already exists, ignore the operation. Modification history is stored individually for each document.
  2. SWITCH should switch the current document to name. If there is no such file, ignore the operation. When switching to a file, the position of the cursor and selection should return to the state in which they were left.

Implementation guarantee: all operations from the previous levels can only be performed when there is an active document.

For example,

queries = [
    ["CREATE", "document1"],       | creates document1
    ["CREATE", "document2"],       | creates document2
    ["CREATE", "document1"],       | ignores the operation
    ["SWITCH", "document1"],       | switches to document1
    ["APPEND", "Hello, world!"],   | document1: "" -> "Hello, world!"
    ["SELECT", "7", "12"],         | selects "world"
    ["COPY"],                      | copies "world" to the clipboard
    ["SWITCH", "document2"],       | switches to document2
    ["PASTE"],                     | document2: "" -> "world"
    ["SWITCH", "document1"],       | switches to document1
    ["BACKSPACE"]                  | document1: "Hello, world!" -> "Hello, !"
]

// Returns "Hello, !"

Example

For

queries = [
    ["APPEND", "Hey"],
    ["APPEND", " you"],
    ["APPEND", ", don't"],
    ["APPEND", " "],
    ["APPEND", "let me down"]
]

the output should be

textEditor1_2(queries) = [
    "Hey",
    "Hey you",
    "Hey you, don't",
    "Hey you, don't ",
    "Hey you, don't let me down"
]

For

queries = [
    ["APPEND", "Hey, you!"],
    ["BACKSPACE"],
    ["APPEND", "? Impossibel!"],
    ["BACKSPACE"],
    ["BACKSPACE"],
    ["BACKSPACE"],
    ["APPEND", "le!"]
]

the output should be

textEditor1_2(queries) = [
    "Hey, you!",
    "Hey, you",
    "Hey, you? Impossibel!",
    "Hey, you? Impossibel",
    "Hey, you? Impossibe",
    "Hey, you? Impossib",
    "Hey, you? Impossible!"
]

Input/Output

[execution time limit] 4 seconds (js)

[input] array.array.string queries

An array of operations need to be applied to the text editor. It is guaranteed that each operation is one of the operations described in the description, all operation parameters are given in correct format, and the text editor will never be in an incorrect state that is not described in the description.

Guaranteed constraints: 1 ≤ queries.length ≤ 250.

[output] array.string

For every operation that modifies the text (APPEND, BACKSPACE, PASTE, UNDO, and REDO), append the current state of the text to the results.

@Mirodil

This comment has been minimized.

Copy link
Owner Author

@Mirodil Mirodil commented Aug 23, 2021

Test 1
Input:
queries:
[["APPEND","Hey"],
["APPEND"," you"],
["APPEND",", don't"],
["APPEND"," "],
["APPEND","let me down"]]
Expected Output:
["Hey",
"Hey you",
"Hey you, don't",
"Hey you, don't ",
"Hey you, don't let me down"]

Test 2
Input:
queries:
[["APPEND","Hey, you!"],
["BACKSPACE"],
["APPEND","? Impossibel!"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["APPEND","le!"]]
Expected Output:
["Hey, you!",
"Hey, you",
"Hey, you? Impossibel!",
"Hey, you? Impossibel",
"Hey, you? Impossibe",
"Hey, you? Impossib",
"Hey, you? Impossible!"]

Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["APPEND",""],
["MOVE","-10"],
["APPEND","START. "],
["MOVE","57"],
["APPEND","END."]]
Expected Output:
["You'll never find a rainbow if you're looking down",
"You'll never find a rainbow if you're looking down",
"START. You'll never find a rainbow if you're looking down",
"START. You'll never find a rainbow if you're looking downEND."]

Input:
queries:
[["APPEND","Never give up"],
["MOVE","12"],
["APPEND","!"],
["MOVE","11"],
["APPEND","!"],
["MOVE","10"],
["APPEND","!"],
["MOVE","9"],
["APPEND","!"],
["MOVE","8"],
["APPEND","!"],
["MOVE","7"],
["APPEND","!"],
["MOVE","6"],
["APPEND","!"],
["MOVE","5"],
["APPEND","!"],
["MOVE","4"],
["APPEND","!"],
["MOVE","3"],
["APPEND","!"],
["MOVE","2"],
["APPEND","!"],
["MOVE","1"],
["APPEND","!"]]
Expected Output:
["Never give up",
"Never give u!p",
"Never give !u!p",
"Never give! !u!p",
"Never giv!e! !u!p",
"Never gi!v!e! !u!p",
"Never g!i!v!e! !u!p",
"Never !g!i!v!e! !u!p",
"Never! !g!i!v!e! !u!p",
"Neve!r! !g!i!v!e! !u!p",
"Nev!e!r! !g!i!v!e! !u!p",
"Ne!v!e!r! !g!i!v!e! !u!p",
"N!e!v!e!r! !g!i!v!e! !u!p"]

Input:
queries:
[["APPEND","Hello, what a wonderful world!"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["MOVE","4"],
["APPEND"," middle "]]
Expected Output:
["Hello, what a wonderful world!",
"Hello, what a wonderful world",
"Hello, what a wonderful worl",
"Hello, what a wonderful wor",
"Hello, what a wonderful wo",
"Hello, what a wonderful w",
"Hello, what a wonderful ",
"Hello, what a wonderful",
"Hello, what a wonderfu",
"Hello, what a wonderf",
"Hello, what a wonder",
"Hello, what a wonde",
"Hello, what a wond",
"Hello, what a won",
"Hello, what a wo",
"Hello, what a w",
"Hello, what a ",
"Hello, what a",
"Hello, what ",
"Hello, what",
"Hello, wha",
"Hell middle o, wha"]

Input:
queries:
[["APPEND","Hello, what a wonderful world!"],
["MOVE","5"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["APPEND","Hey, "]]
Expected Output:
["Hello, what a wonderful world!",
"Hell, what a wonderful world!",
"Hel, what a wonderful world!",
"He, what a wonderful world!",
"H, what a wonderful world!",
", what a wonderful world!",
"Hey, , what a wonderful world!"]

Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["MOVE","6"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["APPEND"," will"],
["MOVE","39"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["APPEND"," are"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
"You'l never find a rainbow if you're looking down",
"You' never find a rainbow if you're looking down",
"You never find a rainbow if you're looking down",
"You will never find a rainbow if you're looking down",
"You will never find a rainbow if you'r looking down",
"You will never find a rainbow if you' looking down",
"You will never find a rainbow if you looking down",
"You will never find a rainbow if you are looking down"]

Test 8
Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["MOVE","24"],
["BACKSPACE"],
["APPEND","APPEND"],
["APPEND","APPEND again"],
["MOVE","80"],
["MOVE","45"],
["APPEND","APPEND after MOVE"],
["BACKSPACE"],
["BACKSPACE"],
["MOVE","39"],
["BACKSPACE"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
"You'll never find a raibow if you're looking down",
"You'll never find a raiAPPENDbow if you're looking down",
"You'll never find a raiAPPENDAPPEND againbow if you're looking down",
"You'll never find a raiAPPENDAPPEND againbow APPEND after MOVEif you're looking down",
"You'll never find a raiAPPENDAPPEND againbow APPEND after MOVif you're looking down",
"You'll never find a raiAPPENDAPPEND againbow APPEND after MOif you're looking down",
"You'll never find a raiAPPENDAPPEND aginbow APPEND after MOif you're looking down"]

Test 9
Input:
queries:
[["APPEND","Never give up"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["BACKSPACE"],
["APPEND","g"],
["APPEND","L"],
["APPEND","Fr"],
["APPEND","wHIp"]]
Expected Output:
["Never give up",
"Never give u",
"Never give ",
"Never give",
"Never giv",
"Never gi",
"Never g",
"Never ",
"Never",
"Neve",
"Nev",
"Ne",
"N",
"",
"",
"",
"g",
"gL",
"gLFr",
"gLFrwHIp"]

Test 10
Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["MOVE","17"],
["APPEND","?"],
["MOVE","18"],
["APPEND","?"],
["MOVE","19"],
["APPEND","?"],
["MOVE","20"],
["APPEND","?"],
["MOVE","21"],
["APPEND","?"],
["MOVE","22"],
["APPEND","?"],
["MOVE","23"],
["APPEND","?"],
["MOVE","24"],
["APPEND","?"],
["MOVE","25"],
["APPEND","?"],
["MOVE","26"],
["APPEND","?"],
["MOVE","27"],
["APPEND","?"],
["MOVE","28"],
["APPEND","?"],
["MOVE","29"],
["APPEND","?"],
["MOVE","30"],
["APPEND","?"],
["MOVE","31"],
["APPEND","?"],
["MOVE","32"],
["APPEND","?"],
["MOVE","33"],
["APPEND","?"],
["MOVE","34"],
["APPEND","?"],
["MOVE","35"],
["APPEND","?"],
["MOVE","36"],
["APPEND","?"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
"You'll never find? a rainbow if you're looking down",
"You'll never find?? a rainbow if you're looking down",
"You'll never find??? a rainbow if you're looking down",
"You'll never find???? a rainbow if you're looking down",
"You'll never find????? a rainbow if you're looking down",
"You'll never find?????? a rainbow if you're looking down",
"You'll never find??????? a rainbow if you're looking down",
"You'll never find???????? a rainbow if you're looking down",
"You'll never find????????? a rainbow if you're looking down",
"You'll never find?????????? a rainbow if you're looking down",
"You'll never find??????????? a rainbow if you're looking down",
"You'll never find???????????? a rainbow if you're looking down",
"You'll never find????????????? a rainbow if you're looking down",
"You'll never find?????????????? a rainbow if you're looking down",
"You'll never find??????????????? a rainbow if you're looking down",
"You'll never find???????????????? a rainbow if you're looking down",
"You'll never find????????????????? a rainbow if you're looking down",
"You'll never find?????????????????? a rainbow if you're looking down",
"You'll never find??????????????????? a rainbow if you're looking down",
"You'll never find???????????????????? a rainbow if you're looking down"]

Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["SELECT","19","27"],
["BACKSPACE"],
["APPEND"," sunny place"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
"You'll never find a if you're looking down",
"You'll never find a sunny place if you're looking down"]

Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["SELECT","0","27"],
["BACKSPACE"],
["SELECT","7","12"],
["APPEND","--replaced--"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
" if you're looking down",
" if you--replaced--ooking down"]

Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["MOVE","9"],
["SELECT","9","10"],
["SELECT","9","9"],
["SELECT","-100","400"],
["SELECT","-100","400"],
["MOVE","30"],
["MOVE","30"],
["SELECT","0","50"],
["BACKSPACE"],
["SELECT","0","10"],
["BACKSPACE"],
["MOVE","10"],
["APPEND","empty"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
"",
"",
"empty"]

Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["SELECT","6","18"],
["COPY"],
["SELECT","0","6"],
["PASTE"],
["SELECT","14","21"],
["PASTE"],
["SELECT","26","50"],
["PASTE"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
" never find never find a rainbow if you're looking down",
" never find n never find nd a rainbow if you're looking down",
" never find n never find never find ooking down"]

Test 15
Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["SELECT","6","50"],
["BACKSPACE"],
["SELECT","0","6"],
["COPY"],
["PASTE"],
["PASTE"],
["PASTE"],
["PASTE"],
["PASTE"],
["PASTE"],
["PASTE"],
["PASTE"],
["PASTE"],
["PASTE"],
["BACKSPACE"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
"You'll",
"You'll",
"You'llYou'll",
"You'llYou'llYou'll",
"You'llYou'llYou'llYou'll",
"You'llYou'llYou'llYou'llYou'll",
"You'llYou'llYou'llYou'llYou'llYou'll",
"You'llYou'llYou'llYou'llYou'llYou'llYou'll",
"You'llYou'llYou'llYou'llYou'llYou'llYou'llYou'll",
"You'llYou'llYou'llYou'llYou'llYou'llYou'llYou'llYou'll",
"You'llYou'llYou'llYou'llYou'llYou'llYou'llYou'llYou'llYou'll",
"You'llYou'llYou'llYou'llYou'llYou'llYou'llYou'llYou'llYou'l"]

Test 16
Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["MOVE","40"],
["PASTE"],
["COPY"],
["MOVE","50"],
["PASTE"],
["SELECT","-10","64"],
["COPY"],
["MOVE","0"],
["PASTE"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
"You'll never find a rainbow if you're looking down",
"You'll never find a rainbow if you're looking down",
"You'll never find a rainbow if you're looking downYou'll never find a rainbow if you're looking down"]

Test 17
Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["SELECT","19","27"],
["BACKSPACE"],
["SELECT","30","38"],
["COPY"],
["MOVE","20"],
["PASTE"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
"You'll never find a if you're looking down",
"You'll never find a looking if you're looking down"]

Test 18
Input:
queries:
[["APPEND","Never give up"],
["SELECT","10","10"],
["COPY"],
["MOVE","2"],
["PASTE"],
["SELECT","13","23"],
["COPY"],
["MOVE","5"],
["PASTE"],
["APPEND",""]]
Expected Output:
["Never give up",
"Never give up",
"Never give up",
"Never give up"]

Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["SELECT","0","50"],
["COPY"],
["SELECT","1","49"],
["COPY"],
["SELECT","2","48"],
["COPY"],
["SELECT","3","47"],
["COPY"],
["SELECT","4","46"],
["COPY"],
["SELECT","5","45"],
["COPY"],
["SELECT","6","44"],
["COPY"],
["SELECT","7","43"],
["COPY"],
["SELECT","8","42"],
["COPY"],
["SELECT","9","41"],
["COPY"],
["SELECT","0","50"],
["MOVE","50"],
["PASTE"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
"You'll never find a rainbow if you're looking downver find a rainbow if you're loo"]

Test 20
Input:
queries:
[["APPEND","You'll never find a rainbow if you're looking down"],
["SELECT","6","11"],
["COPY"],
["BACKSPACE"],
["PASTE"],
["SELECT","0","50"],
["COPY"],
["PASTE"]]
Expected Output:
["You'll never find a rainbow if you're looking down",
"You'llr find a rainbow if you're looking down",
"You'll never find a rainbow if you're looking down",
"You'll never find a rainbow if you're looking down"]

Test 21
Input:
queries:
[["APPEND","Text generated by AI."],
["BACKSPACE"],
["APPEND"," that will conquer the world!"],
["APPEND","!!"],
["UNDO"],
["APPEND"," Stop it!"],
["UNDO"],
["UNDO"]]
Expected Output:
["Text generated by AI.",
"Text generated by AI",
"Text generated by AI that will conquer the world!",
"Text generated by AI that will conquer the world!!!",
"Text generated by AI that will conquer the world!",
"Text generated by AI that will conquer the world! Stop it!",
"Text generated by AI that will conquer the world!",
"Text generated by AI"]

Test 22
Input:
queries:
[["APPEND","Text generated by AI."],
["BACKSPACE"],
["APPEND"," that will conquer the world!"],
["APPEND","!!"],
["UNDO"],
["UNDO"],
["UNDO"],
["UNDO"],
["UNDO"]]
Expected Output:
["Text generated by AI.",
"Text generated by AI",
"Text generated by AI that will conquer the world!",
"Text generated by AI that will conquer the world!!!",
"Text generated by AI that will conquer the world!",
"Text generated by AI",
"Text generated by AI.",
"",
""]

Input:
queries:
[["APPEND","Text generated by AI."],
["BACKSPACE"],
["APPEND"," that will conquer the world!"],
["APPEND","!!"],
["UNDO"],
["APPEND"," Stop it!"],
["UNDO"],
["REDO"],
["REDO"],
["UNDO"],
["UNDO"],
["UNDO"],
["REDO"],
["REDO"]]
Expected Output:
["Text generated by AI.",
"Text generated by AI",
"Text generated by AI that will conquer the world!",
"Text generated by AI that will conquer the world!!!",
"Text generated by AI that will conquer the world!",
"Text generated by AI that will conquer the world! Stop it!",
"Text generated by AI that will conquer the world!",
"Text generated by AI that will conquer the world! Stop it!",
"Text generated by AI that will conquer the world! Stop it!",
"Text generated by AI that will conquer the world!",
"Text generated by AI",
"Text generated by AI.",
"Text generated by AI",
"Text generated by AI that will conquer the world!"]

@Mirodil

This comment has been minimized.

Copy link
Owner Author

@Mirodil Mirodil commented Aug 30, 2021

Scenario

Your task is to implement a simplified version of the text editor.

Implementation tips

Implement operations and provided steps one by one, and not all together, keeping in mind that you will need to make refactors to support each additional step. You can assume that only one text document is modified.

Note

As a result, for every operation that potentially modifies the document (APPEND, BACKSPACE, PASTE, UNDO, and REDO), append the current state of the text after applying the operation, to the results.

Commands/Queries

  • APPEND should append the inputted string text to the document starting from the current position of the cursor. After the operation, the cursor should be at the end of the added string.
  • MOVE should move the cursor to the specified position. The cursor should be positioned between document characters, and are enumerated sequentially starting from 0. If the specified position is out of bounds, then move the cursor to the nearest available position.
  • BACKSPACE should remove the character right before the cursor, if any.
  • SELECT should select the text between the left and right cursor positions. Selection borders should be returned to the bounds of the document. If the selection is empty, it becomes a cursor position. Any modification operation replace the selected text and places the cursor at the end of the modified segment.
  • COPY should copy the selected text to the clipboard, if there is an active non-empty selection.
  • PASTE should append the text from the clipboard.
  • UNDO should restore the document to the state before the previous modification or REDO operation. The selection and cursor position should be also restored.
  • REDO can only be performed if the document has not been modified since the last UNDO operation. REDO should restore the state before the previous UNDO operation, including the selection and cursor position. Multiple UNDO and REDO operations can be performed in a row.
console.assert(YourFunction([
    ["APPEND", "Hey"],               // "" -> "Hey"
    ["APPEND", " there"],            // "Hey" -> "Hey there"
    ["APPEND", "!"]                      // "Hey there" -> "Hey there!"
]) === 'Hey there!');


console.assert(YourFunction([
    ["APPEND", "Hey you"],           // "" -> "Hey you"
    ["MOVE", "3"],                   // moves the cursor after the first "y"
    ["APPEND", ","]                  // "Hey you" -> "Hey, you"
]) === 'Hey, you');

console.assert(YourFunction([
    [APPEND", "Hey you"],            // "" -> "Hey you"
    ["BACKSPACE"],                   // "Hey you" -> "Hey yo"
    ["BACKSPACE"]                    // "Hey yo" -> "Hey y"
]) === 'Hey y');

console.assert(YourFunction( [
    ["APPEND", "!"],                 // "" -> "!"
    ["BACKSPACE"],                  // "!" -> ""
    ["BACKSPACE"]                    // "" -> ""
]) === '');

// SELECT command
console.assert(YourFunction(  [
    ["APPEND", "Hello cruel world!"],  // "" -> "Hello cruel world!"
    ["SELECT", "5", "11"],             // selects " cruel"
    ["APPEND", ","]                    // "Hello cruel world!" -> "Hello, world!"
  ]) === 'Hello, world!');

console.assert(YourFunction([
    ["APPEND", "Hello"],               // "" -> "Hello"        
    ["SELECT", "2", "5"],              // Selects a substring "llo"
    ["APPEND", "y there"]              // "Hello" -> "Hey there"
]) === 'Hey there');

console.assert(YourFunction([
    ["APPEND", "Hello, world!"],       // "" -> "Hello, world!"
    ["SELECT", "5", "12"],             // selects ", world"
    ["COPY"],                          // copies ", world"
    ["MOVE", "12"],                    // moves the cursor to after "d"
    ["PASTE"],                         // "Hello, world!" -> "Hello, world, world!"
    ["PASTE"]                          // "Hello, world, world!" -> "Hello, world, world, world!"
]) === 'Hello, world, world, world!');

// UNDO/REDO commands
console.assert(YourFunction([
    ["APPEND", "Hello, world!"],       | "" -> "Hello, world!"
    ["SELECT", "7", "12"],             | selects "world"
    ["BACKSPACE"],                     | "Hello, world!" -> "Hello, !"
    ["UNDO"],                          | restores "Hello, world!" with "world" selected 
    ["APPEND", "you"]                  | "Hello, world!" -> "Hello, you!"
]) === 'Hello, you!');

console.assert(YourFunction([
    ["APPEND", "Hello, world!"],       | "" -> "Hello, world!"
    ["SELECT", "7", "12"],             | selects "world"
    ["BACKSPACE"],                     | "Hello, world!" -> "Hello, !"
    ["MOVE", "6"],                     | moves the cursor to after the comma 
    ["UNDO"],                          | restores "Hello, world!" with "world" selected 
    ["UNDO"],                          | restores initial ""
    ["REDO"],                          | restores "Hello, world!" with "world" selected
    ["REDO"]                           | restores "Hello, !" with the cursor after the comma
]) === 'Hello, !');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment