Павел обнови решението на 07.11.2018 16:59 (преди 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 Piece struct {
+ origin bool
+ offset uint
+ length uint
+}
+
+type MyEditor struct {
+ pieceTable []Piece
+
+ origin []byte
+ add []byte
+}
+
+func NewEditor(originString string) Editor {
+ initialPiece := Piece{origin: true, offset: 0, length: uint(len(originString))}
+ pieceTable := make([]Piece, 1)
+ pieceTable[0] = initialPiece
+
+ origin := make([]byte, 0, len(originString))
+ origin = append(origin, []byte(originString)...)
+
+ add := make([]byte, 0, 10)
+
+ return &MyEditor{pieceTable: pieceTable, origin: origin, add: add}
+}
+
+func (ed *MyEditor) Insert(position uint, text string) Editor {
+ length := uint(0)
+ inserted := false
+ addPiece := Piece{origin: false, offset: uint(len(ed.add)), length: uint(len(text))}
+ for index, piece := range ed.pieceTable {
+ if (length + piece.length == position) {
+ temp := append([]Piece{addPiece}, ed.pieceTable[index + 1:]...)
+ ed.pieceTable = append(ed.pieceTable[:index + 1], temp...)
+
+ inserted = true
+ break
+ }
+
+ if (length + piece.length > position) {
+ firstHalfLength := position - length
+ secondHalfLength := piece.length - firstHalfLength
+
+ firstHalfOffset := piece.offset
+ secondHalfOffset := firstHalfOffset + firstHalfLength
+
+ firstHalf := Piece{origin: piece.origin, offset: firstHalfOffset, length: firstHalfLength}
+ secondHalf := Piece{origin: piece.origin, offset: secondHalfOffset, length: secondHalfLength}
+
+ ed.pieceTable[index] = firstHalf
+
+ temp := append([]Piece{addPiece, secondHalf}, ed.pieceTable[index + 1:]...)
+ ed.pieceTable = append(ed.pieceTable[:index + 1], temp...)
+
+ inserted = true
+ break
+ }
+
+ length += piece.length;
+ }
+
+ if !inserted {
+ ed.pieceTable = append(ed.pieceTable, []Piece{addPiece}...)
+ }
+
+ ed.add = append(ed.add, []byte(text)...)
+
+ return ed
+}
+
+func (ed *MyEditor) Delete(offset, lengthToDelete uint) Editor {
+ length := uint(0)
+ for index := 0; index < len(ed.pieceTable); index++ {
+ piece := ed.pieceTable[index]
+ if lengthToDelete == 0 {
+ break
+ }
+
+ if offset == length {
+ if lengthToDelete >= piece.length {
+ if index + 1 < len(ed.pieceTable) {
+ lengthToDelete -= piece.length
+ ed.pieceTable = append(ed.pieceTable[:index], ed.pieceTable[index + 1:]...)
+ index--
+ continue
+ } else {
+ ed.pieceTable = ed.pieceTable[:index]
+ break
+ }
+ } else {
+ ed.pieceTable[index].offset += lengthToDelete
+ ed.pieceTable[index].length -= lengthToDelete
+ break;
+ }
+
+ }
+
+ // if offset < length + piece.length {
+ // if lengthToDelete >= piece.length {
+ // if index + 1 < len(ed.pieceTable) {
+ // lengthToDelete -= piece.length
+ // ed.pieceTable = append(ed.pieceTable[:index], ed.pieceTable[index + 1:]...)
+ // index--
+ // continue
+ // } else {
+ // ed.pieceTable = ed.pieceTable[:index]
+ // break
+ // }
+ // } else {
+ // ed.pieceTable[index].length -= lengthToDelete
+ // break;
+ // }
+
+ // }
+
+ length += piece.length
+ }
+
+ return ed
+}
+
+func (ed *MyEditor) Undo() Editor {
+ return ed
+}
+
+func (ed *MyEditor) Redo() Editor {
+ return ed
+}
+
+func (ed MyEditor) String() string {
+ result := ""
+ for _, piece := range ed.pieceTable {
+ var toAppend string
+ if (piece.origin) {
+ toAppend = string(ed.origin[piece.offset:piece.offset + piece.length])
+ } else {
+ toAppend = string(ed.add[piece.offset:piece.offset + piece.length])
+ }
+ result += toAppend
+ }
+
+ return result
+}
Само Insert е имплементиран корекнтно, Delete e наполовина, Undo & Redo не са изобщо. За толкова ми стигна времето.
П.С. - завършения Delete, който не ми стигна времето да напиша:
func (ed *MyEditor) Delete(offset, lengthToDelete uint) Editor {
length := uint(0)
for index := 0; index < len(ed.pieceTable); index++ {
piece := ed.pieceTable[index]
if lengthToDelete == 0 || offset < length {
break
}
if offset == length {
if lengthToDelete >= piece.length {
if index + 1 < len(ed.pieceTable) {
lengthToDelete -= piece.length
ed.pieceTable = append(ed.pieceTable[:index], ed.pieceTable[index + 1:]...)
index--
continue
} else {
ed.pieceTable = ed.pieceTable[:index]
break
}
} else {
ed.pieceTable[index].offset += lengthToDelete
ed.pieceTable[index].length -= lengthToDelete
break;
}
}
if offset < length + piece.length {
if lengthToDelete >= piece.length - (offset - length) {
deleted := piece.length - (offset - length)
lengthToDelete -= deleted
ed.pieceTable[index].length = offset - length
length = offset
continue
} else {
ed.pieceTable[index].length = offset - length
newPieceOffset := piece.offset + ed.pieceTable[index].length + lengthToDelete
newPiece := Piece{origin: piece.origin, offset: newPieceOffset, length: piece.length - newPieceOffset}
if index + 1 < len(ed.pieceTable) {
temp := append([]Piece{newPiece}, ed.pieceTable[index + 1:]...)
ed.pieceTable = append(ed.pieceTable[:index + 1], temp...)
} else {
ed.pieceTable = append(ed.pieceTable, newPiece)
}
break
}
}
length += piece.length
}
return ed
}
Next time :)