Кристиан обнови решението на 04.11.2018 13:28 (преди 9 месеца)
+package main
+
+import (
+        "bytes"
+        "fmt"
+)
+
+type Editor interface {
+        Insert(position uint, text string) Editor
+
+        Delete(offset, length uint) Editor
+
+        Undo() Editor
+
+        Redo() Editor
+
+        String() string
+}
+
+type PieceTable struct {
+        origin          []byte
+        add             []byte
+        pStack          piecesStack
+        lastAddedOffset int
+}
+
+type piecesStack struct {
+        currentPieces  []Piece
+        previousPieces []Piece
+        nextPieces     []Piece
+}
+
+type Piece struct {
+        origin bool
+        offset int
+        length int
+}
+
+func (pieceTable *PieceTable) Insert(position uint, text string) Editor {
+        if position > uint(len(pieceTable.origin)+len(pieceTable.add)) {
+                position = uint(len(pieceTable.origin) + len(pieceTable.add))
+        }
+
+        pieceTable.add = append(pieceTable.add, text...)
+
+        newPieces := make([]Piece, 128)
+        counter := 0
+        isAdded := false
+
+        for _, piece := range pieceTable.pStack.currentPieces {
+                if piece.length > 0 {
+                        if uint(counter+piece.length) >= position && !isAdded {
+                                diff := int(position) - counter
+                                firstPiece := Piece{origin: piece.origin, offset: piece.offset, length: diff}
+                                secondPiece := Piece{origin: false, offset: pieceTable.lastAddedOffset, length: len(text)}
+                                thirdPiece := Piece{origin: piece.origin, offset: piece.offset + diff, length: piece.length - diff}
+
+                                newPieces = append(newPieces, firstPiece)
+                                newPieces = append(newPieces, secondPiece)
+                                newPieces = append(newPieces, thirdPiece)
+
+                                pieceTable.lastAddedOffset += len(text)
+                                isAdded = true
+                        } else {
+                                newPieces = append(newPieces, piece)
+                        }
+                        counter += piece.length
+                }
+        }
+        pieceTable.pStack.previousPieces = pieceTable.pStack.currentPieces
+        pieceTable.pStack.currentPieces = newPieces
+        pieceTable.pStack.nextPieces = nil
+
+        return pieceTable
+}
+
+func (pieceTable *PieceTable) Delete(offset, length uint) Editor {
+        if offset > uint(len(pieceTable.origin)+len(pieceTable.add)) {
+                return pieceTable
+        }
+        if offset+length > uint(len(pieceTable.origin)+len(pieceTable.add)) {
+                length = length + offset - uint(len(pieceTable.origin)+len(pieceTable.add))
+        }
+
+        newPieces := make([]Piece, 128)
+        counter := uint(0)
+        isDeletionStarted := false
+
+        for _, piece := range pieceTable.pStack.currentPieces {
+                if piece.length > 0 {
+                        if counter+uint(piece.length) >= offset && length > 0 {
+                                diff := int(offset - counter)
+                                if !isDeletionStarted {
+                                        firstPiece := Piece{origin: piece.origin, offset: piece.offset, length: piece.offset + diff}
+                                        newPieces = append(newPieces, firstPiece)
+                                        isDeletionStarted = true
+                                }
+                                if uint(piece.length-diff) > length {
+                                        secondPiece := Piece{origin: piece.origin, offset: piece.offset + int(length) + 1, length: piece.length - int(length) - 1}
+                                        newPieces = append(newPieces, secondPiece)
+                                        length = 0
+                                } else {
+                                        length -= uint(piece.length - diff)
+                                }
+
+                        } else {
+                                newPieces = append(newPieces, piece)
+                        }
+                        counter += uint(piece.length)
+
+                        if length > 0 {
+                                offset = counter
+                        }
+                }
+        }
+
+        pieceTable.pStack.previousPieces = pieceTable.pStack.currentPieces
+        pieceTable.pStack.currentPieces = newPieces
+        pieceTable.pStack.nextPieces = nil
+        return pieceTable
+}
+
+func (pieceTable *PieceTable) Redo() Editor {
+        if pieceTable.pStack.currentPieces != nil && pieceTable.pStack.nextPieces != nil {
+                pieceTable.pStack.currentPieces = pieceTable.pStack.nextPieces
+        }
+        return pieceTable
+}
+
+func (pieceTable *PieceTable) Undo() Editor {
+        if pieceTable.pStack.currentPieces != nil && pieceTable.pStack.previousPieces != nil {
+                pieceTable.pStack.nextPieces = pieceTable.pStack.currentPieces
+                pieceTable.pStack.currentPieces = pieceTable.pStack.previousPieces
+        }
+        return pieceTable
+}
+
+func (pieceTable *PieceTable) String() string {
+        var buffer bytes.Buffer
+
+        for _, piece := range pieceTable.pStack.currentPieces {
+                if piece.length > 0 {
+                        if piece.origin {
+                                buffer.WriteString(string(pieceTable.origin[piece.offset : piece.offset+piece.length]))
+                        } else {
+                                buffer.WriteString(string(pieceTable.add[piece.offset : piece.offset+piece.length]))
+                        }
+                }
+        }
+
+        return buffer.String()
+}
+
+func NewEditor(text string) Editor {
+        initPieces := make([]Piece, 34)
+        piece := Piece{origin: true, offset: 0, length: len(text)}
+        initPieces[0] = piece
+        initStack := piecesStack{currentPieces: initPieces, previousPieces: nil, nextPieces: nil}
+        pieceTable := new(PieceTable)
+        pieceTable.origin = []byte(text)
+        pieceTable.pStack = initStack
+        return pieceTable
+}
+
+func main() {
+        var f = NewEditor("A large span of text")
+        f = f.Insert(16, "English ").Delete(2, 6)
+        fmt.Println(f.String())
+}
