Иван обнови решението на 06.11.2018 23:49 (преди 9 месеца)
+package main
+
+type Editor interface {
+        // String returns complete representation of what a file looks
+        // like after all manipulations.
+        String() string
+
+        // Insert text starting from given position.
+        Insert(position uint, text string) Editor
+
+        // Delete length items from offset.
+        Delete(offset, length uint) Editor
+}
+
+type CustomEditor struct {
+        Origin         []byte
+        Add            []byte
+        CurrOffsetAdd  uint
+        Table          []Piece
+        CurrLengthFile uint
+}
+
+type Piece struct {
+        Origin bool
+        Offset uint
+        Length uint
+}
+
+func (f CustomEditor) String() (result string) {
+        for _, piece := range f.Table {
+                if piece.Origin == true {
+                        result += string(f.Origin[piece.Offset:piece.Length])
+                } else {
+                        result += string(f.Add[piece.Offset : piece.Offset+piece.Length])
+                }
+        }
+
+        return
+}
+
+func NewEditor(s string) (e Editor) {
+        origin := []byte(s)
+        add := make([]byte, 0)
+        table := make([]Piece, 0)
+        table = append(table, Piece{Origin: true, Offset: 0, Length: uint(len(s))})
+        e = &CustomEditor{Origin: origin, CurrOffsetAdd: 0, Add: add, Table: table, CurrLengthFile: uint(len(s))}
+
+        return
+}
+
+func (f CustomEditor) Delete(offset uint, length uint) Editor {
+        if offset >= f.CurrLengthFile {
+                //do nothing
+        } else if offset+length >= f.CurrLengthFile {
+                if offset == 0 {
+                        f.Table = f.Table[:0]
+                } else {
+                        var currLength uint
+                        var idxDelete int
+                        var lastLength uint
+                        for i, piece := range f.Table {
+                                currLength += piece.Length
+                                if offset < currLength {
+                                        idxDelete = i
+                                        lastLength = piece.Length
+                                        break
+                                }
+
+                        }
+
+                        f.Table = f.Table[0 : idxDelete+1]
+                        del := offset - currLength + lastLength
+                        f.Table[idxDelete].Length = del
+                }
+        } else {
+                var currLength uint
+                var idxFirstDelete int
+                var idxSecondDelete int
+                var firstDelete uint
+                var secondDelete uint
+                var gone bool
+                var isSameBuf bool
+
+                var secondDeleteStart uint
+
+                for i, piece := range f.Table {
+                        currLength += piece.Length
+                        if !isSameBuf && offset < currLength && offset+length < currLength {
+                                isSameBuf = true
+                                idxFirstDelete = i
+                                idxSecondDelete = i
+                                firstDelete = offset - currLength + piece.Length
+                                secondDelete = firstDelete + length
+                                break
+                        }
+                        if !gone && offset < currLength {
+                                idxFirstDelete = i
+                                firstDelete = offset - currLength + piece.Length
+                                gone = true
+                        }
+
+                        if gone && offset+length < currLength {
+                                idxSecondDelete = i
+                                secondDeleteStart = offset + length - currLength + piece.Length
+                                secondDelete = currLength - length - offset
+                                break
+                        }
+
+                }
+
+                if isSameBuf {
+                        cLength := f.Table[idxFirstDelete].Length
+                        f.Table[idxFirstDelete].Length = firstDelete
+                        newPieceInAdd := Piece{Origin: f.Table[idxFirstDelete].Origin, Offset: secondDelete, Length: cLength - secondDelete}
+                        f.Table = append(f.Table, Piece{})
+
+                        copy(f.Table[idxFirstDelete+1:], f.Table[idxFirstDelete:])
+
+                        f.Table[idxFirstDelete+1] = newPieceInAdd
+
+                } else {
+                        //handle first
+                        f.Table[idxFirstDelete].Length = firstDelete
+
+                        //handle second
+                        f.Table[idxSecondDelete].Offset += secondDeleteStart
+                        f.Table[idxSecondDelete].Length = secondDelete
+                        f.Table = append(f.Table[0:idxFirstDelete+1], f.Table[idxSecondDelete:]...)
+                }
+
+        }
+
+        return f
+}
+
+func (f CustomEditor) Insert(position uint, text string) Editor {
+        //append new string to add slice
+        f.Add = append(f.Add, text...)
+        //create new piece for add,
+        //offset is calcualted by add buffer
+        newPieceInAdd := Piece{Origin: false, Offset: f.CurrOffsetAdd, Length: uint(len(text))}
+        f.CurrOffsetAdd += uint(len(text)) //+ 1
+
+        if position > f.CurrLengthFile {
+                if f.Table[len(f.Table)-1].Origin == false {
+                        position = f.CurrLengthFile
+                        //append to curr file
+                        f.Table[len(f.Table)-1].Length += uint(len(text))
+                        //f.Table = append(f.Table, newPieceInAdd)
+                } else {
+                        position = f.CurrLengthFile
+                        //append to curr file
+                        f.Table = append(f.Table, newPieceInAdd)
+                }
+
+        } else {
+                //find before piece
+                var idx int
+                for i, piece := range f.Table {
+                        if piece.Offset <= position && position <= piece.Length {
+                                idx = i
+                                break
+                        }
+                }
+
+                f.CurrLengthFile += uint(len(text))
+
+                //modify before piece
+                oldLength := f.Table[idx].Length
+                f.Table[idx].Length = position
+
+                //create afterPiece
+                newPieceAfterAdded := Piece{Origin: f.Table[idx].Origin, Offset: f.Table[idx].Length, Length: oldLength}
+
+                //add new piece
+                //add after added piece
+
+                if len(f.Table) == 1 {
+                        f.Table = append(f.Table, newPieceInAdd, newPieceAfterAdded)
+                } else {
+                        f.Table = append(f.Table, Piece{}, Piece{})
+                        copy(f.Table[idx+3:], f.Table[idx+1:])
+                        f.Table[idx+1] = newPieceInAdd
+                        f.Table[idx+2] = newPieceAfterAdded
+                }
+        }
+
+        return f
+}
