Ангел обнови решението на 04.11.2018 14:50 (преди 9 месеца)
+package main
+
+type Editor interface {
+        Insert(position uint, text string) Editor
+
+        Delete(offset, length uint) Editor
+
+        Undo() Editor
+
+        Redo() Editor
+
+        String() string
+}
+
+type Piece struct {
+        origin bool
+        offset int
+        length int
+}
+
+type State struct {
+        pieces []Piece
+}
+
+func NewEditor(s string) Editor {
+        var tm *TextManager = new(TextManager)
+        tm.originBuffer = []byte(s)
+        tm.redoStack = make([]State, 0)
+        tm.pieceTable = make([]State, 1)
+        var st *State = new(State)
+        st.pieces = make([]Piece, 1)
+        st.pieces[0] = Piece{true, 0, len(s)}
+        tm.pieceTable[0] = *st
+        return tm
+}
+
+type TextManager struct {
+        originBuffer []byte
+        addBuffer    []byte
+        pieceTable   []State
+        redoStack    []State
+}
+
+func (tm *TextManager) getCurrentState() State {
+        return tm.pieceTable[len(tm.pieceTable)-1]
+}
+
+func (tm *TextManager) setNewState(s State) {
+        tm.pieceTable = append(tm.pieceTable, s)
+}
+
+func (tm *TextManager) Insert(position uint, text string) Editor {
+        offset := len(tm.addBuffer) //len(nil) == 0
+
+        tm.redoStack = tm.redoStack[:0]
+
+        if tm.addBuffer == nil {
+                tm.addBuffer = []byte(text)
+        } else {
+                tm.addBuffer = append(tm.addBuffer, []byte(text)...)
+        }
+        piece := Piece{false, offset, len(text)}
+
+        state := tm.getCurrentState()
+        if length := (uint)(len(tm.String())); position >= length {
+                state.pieces = append(state.pieces, piece)
+        } else if position == 0 {
+                state.pieces = append([]Piece{piece}, state.pieces...)
+        } else {
+                var bytes uint = 0
+
+                for index, p := range state.pieces {
+                        bytes += (uint)(p.length)
+                        if bytes > position {
+                                i := (int)(position - (bytes - (uint)(p.length)))
+                                p1 := Piece{p.origin, p.offset, i}
+                                p2 := Piece{p.origin, p.offset + i, p.length - i}
+                                toAppend := []Piece{p1, piece, p2}
+                                if index+1 < len(state.pieces) {
+                                        toAppend = append(toAppend, state.pieces[index+1:]...)
+                                }
+                                state.pieces = append(state.pieces[:index], toAppend...)
+                                break
+                        }
+                }
+        }
+        tm.setNewState(state)
+        return tm
+}
+
+func (tm *TextManager) Delete(offset, length uint) Editor {
+        contentLength := (uint)(len(tm.String()))
+        if offset > contentLength {
+                return tm
+        }
+        if offset+length > contentLength {
+                length = contentLength - offset
+        }
+
+        tm.redoStack = tm.redoStack[:0]
+
+        state := tm.getCurrentState()
+        resultState := new(State)
+        resultState.pieces = make([]Piece, 0)
+        var bytes uint = 0
+        flag := false
+        for index, piece := range state.pieces {
+                bytes += (uint)(piece.length)
+                if bytes >= offset {
+                        i := (int)(offset - (bytes - (uint)(piece.length)))
+                        var p1, p2 *Piece = new(Piece), new(Piece)
+                        if i != 0 {
+                                *p1 = Piece{piece.origin, piece.offset, i}
+                        }
+                        if length >= (uint)(piece.length-i) {
+                                offset = bytes
+                                length -= (uint)(piece.length - i)
+                                if p1.length != 0 {
+                                        resultState.pieces = append(resultState.pieces, *p1)
+                                }
+                                flag = true
+                                continue
+                        } else {
+                                if flag {
+                                        size := (int)((uint)(piece.length) - length)
+                                        *p2 = Piece{piece.origin, piece.offset + (int)(length), size}
+                                } else {
+                                        size := (int)((uint)(piece.length) - length - offset)
+                                        *p2 = Piece{piece.origin, piece.offset + (int)(offset) + (int)(length), size}
+                                }
+                        }
+                        if p1.length != 0 {
+                                resultState.pieces = append(resultState.pieces, *p1)
+                        }
+                        if p2.length != 0 {
+                                resultState.pieces = append(resultState.pieces, *p2)
+                        }
+                        if index+1 < len(state.pieces) {
+                                resultState.pieces = append(resultState.pieces, state.pieces[index+1:]...)
+                        }
+                        break
+                } else {
+                        offset -= (uint)(piece.length) + 1
+                        bytes -= ((uint)(piece.length))
+                        resultState.pieces = append(resultState.pieces, piece)
+                }
+        }
+        tm.setNewState(*resultState)
+        return tm
+}
+
+func (tm *TextManager) Undo() Editor {
+        if length := len(tm.pieceTable); length > 1 {
+                tm.redoStack = append(tm.redoStack, tm.pieceTable[length-1])
+                tm.pieceTable = tm.pieceTable[:length-1]
+        }
+        return tm
+}
+
+func (tm *TextManager) Redo() Editor {
+        if length := len(tm.redoStack); length > 0 {
+                tm.pieceTable = append(tm.pieceTable, tm.redoStack[length-1])
+                tm.redoStack = tm.redoStack[:length-1]
+        }
+        return tm
+}
+
+func (tm *TextManager) String() string {
+        i := len(tm.pieceTable) - 1
+        res := []byte{}
+        for _, p := range tm.pieceTable[i].pieces {
+                if p.origin {
+                        res = append(res, tm.originBuffer[p.offset:p.offset+p.length]...)
+                } else {
+                        res = append(res, tm.addBuffer[p.offset:p.offset+p.length]...)
+                }
+        }
+        return string(res)
+}
Имплементацията на Insert и Delete е прекалено сложна. Дори не мога да предположа дали работи във всички случаи. Опитай се да генерализираш малко.
Мерси за feedback-a, но съм притиснат от времето, затова решението изглежда по този начин...
