Траян обнови решението на 07.11.2018 16:13 (преди 9 месеца)
+package main
+
+type Editor interface {
+ // Insert text starting from given position.
+ Insert(position uint, text string) Editor
+
+ // Delete length items from offset.
+ Delete(offset, length uint) Editor
+
+ // Undo reverts latest change.
+ Undo() Editor
+
+ // Redo re-applies latest undone change.
+ Redo() Editor
+
+ // String returns complete representation of what a file looks
+ // like after all manipulations.
+ String() string
+}
+
+type pieceTable struct {
+ origin bool
+ offset int
+ length int
+}
+
+type transition struct {
+ from []pieceTable
+ to []pieceTable
+}
+
+type editor1 struct {
+ origin string
+ add string
+ pceTbl []pieceTable
+ textLenght uint
+ transitionsBackward []transition
+ transitionsForward []transition
+}
+
+func (editor editor1) Insert(position uint, text string) Editor {
+ if position > editor.textLenght {
+ position = editor.textLenght
+ }
+ editor.transitionsForward = []transition{}
+ editor.textLenght += uint(len(text))
+ i := 0
+ pieceOffset := position
+ for i = 0; i < len(editor.pceTbl) && pieceOffset >= uint(editor.pceTbl[i].length); i++ {
+ pieceOffset -= uint(editor.pceTbl[i].length)
+ }
+ if pieceOffset == 0 {
+ var oldPieces []pieceTable
+ newPiece := pieceTable{false, len(editor.add), len(text)}
+ editor.pceTbl = append(editor.pceTbl, newPiece)
+ copy(editor.pceTbl[i+1:], editor.pceTbl[i:len(editor.pceTbl)])
+ editor.pceTbl[i] = newPiece
+ newPieces := append([]pieceTable{}, newPiece)
+ oldPieces = []pieceTable{pieceTable{false, i, -1}}
+ editor.transitionsBackward = append(editor.transitionsBackward, transition{oldPieces, newPieces})
+ } else {
+ oldPieces := append([]pieceTable{}, editor.pceTbl[i])
+ firstPieceOfDividedElement := pieceTable{editor.pceTbl[i].origin,
+ editor.pceTbl[i].offset, int(pieceOffset)}
+ newGluePiece := pieceTable{false, len(editor.add), len(text)}
+ secondPieceOfDividedElement := pieceTable{editor.pceTbl[i].origin,
+ editor.pceTbl[i].offset + int(pieceOffset),
+ editor.pceTbl[i].length - int(pieceOffset)}
+ newPieces := append([]pieceTable{}, firstPieceOfDividedElement, newGluePiece, secondPieceOfDividedElement)
+ editor.pceTbl = append(editor.pceTbl, firstPieceOfDividedElement, secondPieceOfDividedElement)
+ copy(editor.pceTbl[i+3:], editor.pceTbl[i+1:])
+ editor.pceTbl[i] = firstPieceOfDividedElement
+ editor.pceTbl[i+1] = newGluePiece
+ editor.pceTbl[i+2] = secondPieceOfDividedElement
+ editor.transitionsBackward = append(editor.transitionsBackward, transition{oldPieces, newPieces})
+ }
+ editor.add += text
+ return editor
+}
+
+func (editor editor1) Delete(offset, length uint) Editor {
+ if offset < editor.textLenght && length > 0 {
+ if offset+length > editor.textLenght {
+ length = editor.textLenght - offset
+ }
+ editor.textLenght -= length
+ idx := 0
+ endIdx := 0
+ for idx = 0; idx < len(editor.pceTbl) && offset >= uint(editor.pceTbl[idx].length); idx++ {
+ offset -= uint(editor.pceTbl[idx].length)
+ }
+ endIdx = idx
+ if length > uint(editor.pceTbl[idx].length)-offset {
+ length -= uint(editor.pceTbl[idx].length) - offset
+ for endIdx = idx + 1; endIdx < len(editor.pceTbl) && length >= uint(editor.pceTbl[endIdx].length); endIdx++ {
+ length -= uint(editor.pceTbl[endIdx].length)
+ }
+ }
+ if offset == 0 {
+ var oldPieces []pieceTable
+ if idx == 0 && endIdx > 0 {
+ oldPieces = append(oldPieces, editor.pceTbl[idx:endIdx]...)
+ } else if idx != 0 && endIdx != 0 {
+ oldPieces = append([]pieceTable{}, editor.pceTbl[idx-1:endIdx-1]...)
+ }
+ var newPieces []pieceTable
+ editor.pceTbl = append(editor.pceTbl[:idx], editor.pceTbl[endIdx:]...)
+ if len(editor.pceTbl) > idx {
+ oldPieces = append(oldPieces, editor.pceTbl[idx])
+ copy(editor.pceTbl[:], append(editor.pceTbl[:idx], editor.pceTbl[idx+1:]...))
+ editor.pceTbl = append(editor.pceTbl[:len(editor.pceTbl)-1])
+ newPieces = append([]pieceTable{}, pieceTable{false, idx, -1})
+ }
+ editor.transitionsBackward = append(editor.transitionsBackward, transition{oldPieces, newPieces})
+ } else {
+ if idx == endIdx {
+ oldPieces := append([]pieceTable{}, editor.pceTbl[idx])
+ firstPieceOfDividedElement := pieceTable{editor.pceTbl[idx].origin,
+ editor.pceTbl[idx].offset,
+ int(offset)}
+ secondPieceOfDividedElement := pieceTable{editor.pceTbl[idx].origin,
+ editor.pceTbl[idx].offset + int(offset) + int(length),
+ editor.pceTbl[idx].length - (int(offset) + int(length))}
+ newPieces := append([]pieceTable{}, firstPieceOfDividedElement, secondPieceOfDividedElement)
+
+ editor.pceTbl = append(editor.pceTbl, firstPieceOfDividedElement)
+ copy(editor.pceTbl[idx+2:], editor.pceTbl[idx+1:])
+ editor.pceTbl[idx] = firstPieceOfDividedElement
+ editor.pceTbl[idx+1] = secondPieceOfDividedElement
+ editor.transitionsBackward = append(editor.transitionsBackward, transition{oldPieces, newPieces})
+ } else {
+ oldPieces := append([]pieceTable{}, editor.pceTbl[idx:endIdx]...)
+ editor.pceTbl = append(editor.pceTbl[:idx+1], editor.pceTbl[endIdx:]...)
+ firstOfTheFirstPiece := pieceTable{editor.pceTbl[idx].origin,
+ editor.pceTbl[idx].offset,
+ int(offset)}
+ newPieces := append([]pieceTable{}, firstOfTheFirstPiece)
+ if length != 0 {
+ oldPieces = append(oldPieces, editor.pceTbl[idx+1])
+ secondOfTheSecondPiece := pieceTable{editor.pceTbl[idx+1].origin,
+ editor.pceTbl[idx+1].offset + int(length),
+ editor.pceTbl[idx+1].length - int(length)}
+ editor.pceTbl[idx+1] = secondOfTheSecondPiece
+ newPieces = append(newPieces, secondOfTheSecondPiece)
+ }
+ editor.transitionsBackward = append(editor.transitionsBackward, transition{oldPieces, newPieces})
+ editor.pceTbl[idx] = firstOfTheFirstPiece
+ }
+ }
+ }
+ return editor
+}
+
+func (editor editor1) Undo() Editor {
+ if len(editor.transitionsBackward) > 0 {
+ backwTransitionsLastIndex := len(editor.transitionsBackward) - 1
+ undoTransition := editor.transitionsBackward[backwTransitionsLastIndex]
+ startIdx := 0
+ endIdx := 0
+ if undoTransition.from[0].length != -1 {
+ if undoTransition.to[0].length != -1 {
+ for i := 0; i < len(editor.pceTbl); i++ {
+ if undoTransition.to[0] == editor.pceTbl[i] {
+ startIdx = i
+ i = len(editor.pceTbl)
+ }
+ }
+ endIdx = startIdx + len(undoTransition.to)
+ editor.pceTbl = append(editor.pceTbl[:startIdx], editor.pceTbl[endIdx:]...)
+ for idx := 0; idx < len(undoTransition.from); idx++ {
+ editor.pceTbl = append(editor.pceTbl, pieceTable{})
+ }
+ copy(editor.pceTbl[startIdx+len(undoTransition.from):], editor.pceTbl[startIdx:])
+ copy(editor.pceTbl[startIdx:startIdx+len(undoTransition.from)], undoTransition.from)
+ } else {
+ startIdx = undoTransition.to[0].offset
+ for idx := 0; idx < len(undoTransition.from); idx++ {
+ editor.pceTbl = append(editor.pceTbl, pieceTable{})
+ }
+
+ copy(editor.pceTbl[startIdx+len(undoTransition.from):], editor.pceTbl[startIdx:])
+ copy(editor.pceTbl[undoTransition.to[0].offset:undoTransition.to[0].offset+len(undoTransition.from)],
+ undoTransition.from[:])
+ }
+ editor.transitionsForward = append(editor.transitionsForward, undoTransition)
+ editor.transitionsBackward = editor.transitionsBackward[:backwTransitionsLastIndex]
+ } else {
+ editor.pceTbl = append(editor.pceTbl[:undoTransition.from[0].offset], editor.pceTbl[undoTransition.from[0].offset+1:]...)
+ editor.transitionsForward = append(editor.transitionsForward, undoTransition)
+ editor.transitionsBackward = editor.transitionsBackward[:backwTransitionsLastIndex]
+ }
+ }
+ return editor
+}
+
+func (editor editor1) Redo() Editor {
+ if len(editor.transitionsForward) > 0 {
+ forwTransitionsLastIndex := len(editor.transitionsForward) - 1
+ redoTransition := editor.transitionsForward[forwTransitionsLastIndex]
+ startIdx := 0
+ endIdx := 0
+ if redoTransition.from[0].length != -1 {
+ if redoTransition.to[0].length != -1 {
+ for i := 0; i < len(editor.pceTbl); i++ {
+ if redoTransition.from[0] == editor.pceTbl[i] {
+ startIdx = i
+ i = len(editor.pceTbl)
+ }
+ }
+ endIdx = startIdx + len(redoTransition.from)
+
+ editor.pceTbl = append(editor.pceTbl[:startIdx], editor.pceTbl[endIdx:]...)
+
+ for idx := 0; idx < len(redoTransition.to); idx++ {
+ editor.pceTbl = append(editor.pceTbl, pieceTable{})
+ }
+ copy(editor.pceTbl[startIdx+len(redoTransition.to):], editor.pceTbl[startIdx:])
+ copy(editor.pceTbl[startIdx:startIdx+len(redoTransition.to)], redoTransition.to)
+ } else {
+ editor.pceTbl = append(editor.pceTbl[:redoTransition.to[0].offset], editor.pceTbl[redoTransition.to[0].offset+1:]...)
+ }
+ } else {
+ startIdx = redoTransition.from[0].offset
+ for idx := 0; idx < len(redoTransition.to); idx++ {
+ editor.pceTbl = append(editor.pceTbl, pieceTable{})
+ }
+
+ copy(editor.pceTbl[startIdx+len(redoTransition.to):], editor.pceTbl[startIdx:])
+ copy(editor.pceTbl[redoTransition.from[0].offset:redoTransition.from[0].offset+len(redoTransition.to)],
+ redoTransition.to[:])
+ }
+ editor.transitionsBackward = append(editor.transitionsBackward, redoTransition)
+ editor.transitionsForward = editor.transitionsForward[:forwTransitionsLastIndex]
+ }
+ return editor
+}
+
+func (editor editor1) String() string {
+ resultText := ""
+ for i := 0; i < len(editor.pceTbl); i++ {
+ if editor.pceTbl[i].origin == true {
+ resultText += editor.origin[editor.pceTbl[i].offset:(editor.pceTbl[i].offset + editor.pceTbl[i].length)]
+ } else {
+ resultText += editor.add[editor.pceTbl[i].offset:(editor.pceTbl[i].offset + editor.pceTbl[i].length)]
+ }
+ }
+ return resultText
+}
+
+func (editor editor1) GetAdd() string {
+ return editor.add
+}
+
+func (editor editor1) GetOriginLen() int {
+ return len(editor.origin)
+}
+
+func (editor editor1) GetAddLen() int {
+ return len(editor.add)
+}
+
+func NewEditor(editorContent string) Editor {
+ var editor = editor1{origin: editorContent, add: "",
+ pceTbl: []pieceTable{{
+ true, 0, len(editorContent)}},
+ textLenght: uint(len(editorContent))}
+ return editor
+}