Мартин обнови решението на 07.11.2018 15:22 (преди 9 месеца)
+package main
+
+import (
+ "fmt"
+)
+
+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 Piece struct {
+ origin bool // Does the piece belongs to the origin slice
+ offset int // The start of the piece
+ length int // The length of the piece
+}
+
+type Table struct {
+ rows []Piece
+ origin string // the original content of the file
+ add string // the new words in the file
+}
+
+type SimpleEditor struct {
+ table Table
+ functions []Function
+}
+
+func newPiece(isOrigin bool, offset, length int) Piece {
+ return Piece{origin: isOrigin, offset: offset, length: length}
+}
+
+func (s *SimpleEditor) newRow(piece Piece) {
+
+ s.table.rows = append(s.table.rows, piece)
+}
+
+func NewEditor(origin string) Editor {
+
+ var piece Piece = newPiece(true, 0, len(origin))
+ var editor SimpleEditor
+
+ editor.newRow(piece)
+ editor.table.origin = origin
+
+ return &editor
+}
+
+// Find the index of the row in the table where the position belongs
+func findPosRowIndex(position int, rows []Piece) int {
+
+ if len(rows) <= 0 {
+ return -100
+ }
+ var currEnd int
+ resultIndex := -1
+ for index, piece := range rows {
+
+ currEnd += piece.length
+ fmt.Println("The currEnd + pieceLenght are: ", currEnd)
+ if position < currEnd {
+ resultIndex = index
+ break
+ }
+ }
+ return resultIndex
+}
+
+// ------------------------- Insertion -------------------------
+
+func (s *SimpleEditor) addElementAtIndex(index int, elem Piece) {
+ rightPart := make([]Piece, len(s.table.rows[:index]))
+ leftPart := make([]Piece, len(s.table.rows[index:]))
+ copy(rightPart, s.table.rows[:index])
+ copy(leftPart, s.table.rows[index:])
+ if len(rightPart) == 0 {
+ //fmt.Println("Add here the elem: ", elem)
+ tempSlice := []Piece{elem}
+ s.table.rows = append(tempSlice, s.table.rows...)
+ } else {
+ rightPart = append(rightPart, elem)
+ s.table.rows = append(rightPart, leftPart...)
+ }
+ //fmt.Println("Print the rows in addElement in index function: ", s.table.rows)
+}
+
+func (s *SimpleEditor) addAtEnd(text string) {
+ elem := newPiece(false, len(s.table.add), len(text))
+ s.table.add += text
+ s.table.rows = append(s.table.rows, elem)
+}
+
+func (s *SimpleEditor) addAtBegin(text string) {
+ newRow := newPiece(false, len(s.table.add), len(text))
+ tempSlice := []Piece{newRow}
+ s.table.rows = append(tempSlice, s.table.rows...)
+}
+
+func (s *SimpleEditor) insertInMiddle(position, rowIndex int, text string) {
+
+ var isOriginCurrent bool = s.table.rows[rowIndex].origin
+ var currRowLength = s.table.rows[rowIndex].length
+ s.table.rows[rowIndex].length = position
+
+ //fmt.Println("Before adding: ", s.table.rows)
+ newAddRow := newPiece(false, len(s.table.add), len(text))
+ s.table.add += text
+ s.addElementAtIndex(rowIndex+1, newAddRow)
+
+ //fmt.Println("After adding the first element: ", s.table.rows)
+ var newOffset = s.table.rows[rowIndex].length
+ newSplitedRow := newPiece(isOriginCurrent, newOffset, currRowLength-newOffset)
+ s.addElementAtIndex(rowIndex+2, newSplitedRow)
+
+ //fmt.Println("The slice in the end of Insert is: ", s.table.rows)
+}
+
+// Insert text starting from given position.
+func (s *SimpleEditor) Insert(position uint, text string) Editor {
+
+ truePos := int(position)
+ rowIndex := findPosRowIndex(truePos, s.table.rows)
+ if rowIndex == -1 {
+ rowIndex = len(s.table.rows) + 1
+ }
+ //fmt.Println("The position is: ", rowIndex)
+ if rowIndex >= len(s.table.rows) {
+
+ s.addAtEnd(text)
+ s.table.add += text
+ fmt.Println("The slice in the end of Insert is: ", s.table.rows)
+ } else if truePos == 0 {
+
+ s.addAtBegin(text)
+ s.table.add += text
+ fmt.Println("The slice in the end of Insert is: ", s.table.rows)
+ } else {
+ s.insertInMiddle(truePos, rowIndex, text)
+ }
+ s.deleteRowsWithZeroLength()
+ return s
+}
+
+// ------------------------- Deletion -------------------------
+
+func (s *SimpleEditor) deleteAtIndex(index int) {
+ if index+1 == len(s.table.rows) {
+ s.table.rows = s.table.rows[:index-1]
+ } else {
+ s.table.rows = append(s.table.rows[:index], s.table.rows[index+1:]...)
+ }
+}
+
+func (s *SimpleEditor) deleteRowsWithZeroLength() {
+
+ for index, piece := range s.table.rows {
+ if piece.length == 0 {
+ s.deleteAtIndex(index)
+ }
+ }
+}
+
+func (s *SimpleEditor) deleteRowsInBetween(delLength, begin, end int) int {
+
+ rightPart := make([]Piece, len(s.table.rows[:begin]))
+ leftPart := make([]Piece, len(s.table.rows[end:]))
+ copy(rightPart, s.table.rows[:begin])
+ copy(leftPart, s.table.rows[end:])
+ s.table.rows = append(rightPart, leftPart...)
+
+ return delLength
+}
+
+func (s *SimpleEditor) deleteInSameRow(trueOffset, trueLength, startIndex int) {
+ pastLength := s.table.rows[startIndex].length
+ s.table.rows[startIndex].length = trueOffset
+ isOrigin := s.table.rows[startIndex].origin
+ newOffset := trueOffset + trueLength
+ newLength := pastLength - (trueLength + s.table.rows[startIndex].length)
+ s.addElementAtIndex(startIndex+1, newPiece(isOrigin, newOffset, newLength))
+}
+
+func (s *SimpleEditor) Delete(offset, length uint) Editor {
+ trueOffset := int(offset)
+ trueLength := int(length)
+ starDelIndex := findPosRowIndex(trueOffset, s.table.rows)
+ endDelIndex := findPosRowIndex(trueLength+trueOffset, s.table.rows)
+
+ if starDelIndex == -1 {
+ return s
+ } else if endDelIndex == -1 {
+ s.deleteRowsInBetween(trueLength, starDelIndex, len(s.table.rows))
+
+ } else if starDelIndex == endDelIndex {
+ s.deleteInSameRow(trueOffset, trueLength, starDelIndex)
+ } else {
+ trueLength = s.deleteRowsInBetween(trueLength, starDelIndex, endDelIndex)
+ pastEndPos := s.table.rows[starDelIndex].offset + s.table.rows[starDelIndex].length
+ fmt.Println(pastEndPos)
+ // Here all redundant rows are removed
+ s.table.rows[starDelIndex].length -= trueLength
+ s.table.rows[starDelIndex].offset = pastEndPos - s.table.rows[starDelIndex].length
+ }
+ fmt.Println(s.table.rows)
+ s.deleteRowsWithZeroLength()
+ return s
+}
+
+// ------------------------- Undo -------------------------
+
+type Function struct {
+ isInsert bool
+ offsetOrPos uint
+ textToAdd string
+ lengthToDel uint
+}
+
+func (s *SimpleEditor) newInsertFuncInStack(position uint, text string) {
+ var newFuncInsert Function = Function{isInsert: true, offsetOrPos: position, textToAdd: text}
+ s.functions = append(s.functions, newFuncInsert)
+}
+
+func (s *SimpleEditor) newDelFunction(offset, length uint) {
+ var newFuncDel Function = Function{isInsert: false, offsetOrPos: offset, lengthToDel: length}
+ s.functions = append(s.functions, newFuncDel)
+}
+
+func (s *SimpleEditor) Undo() Editor {
+
+ return s
+}
+
+func (s *SimpleEditor) Redo() Editor {
+
+ return s
+}
+
+// ------------------------- String -------------------------
+
+// String returns complete representation of what a file looks
+// like after all manipulations.
+func (s *SimpleEditor) String() string {
+
+ var result string
+ fmt.Println("The editor rows are: ", s.table.rows)
+ fmt.Println("The origin array: ", s.table.origin)
+ fmt.Println("The add array: ", s.table.add)
+ for _, piece := range s.table.rows {
+ offsetIndex := piece.offset
+ length := piece.length
+ fmt.Println("Piece is: ", piece)
+ if piece.origin {
+ result += s.table.origin[offsetIndex : length+offsetIndex]
+ } else {
+ result += s.table.add[offsetIndex : length+offsetIndex]
+ }
+ }
+ return result
+}