Михаил обнови решението на 06.11.2018 14:22 (преди 9 месеца)
+package main
+
+type Operation interface {
+ Do()
+}
+type Insert struct {
+ f func(p uint, t string) *MyEditor
+ position uint
+ text string
+}
+type Delete struct {
+ f func(o, l uint) *MyEditor
+ offset uint
+ length uint
+}
+
+func (d Delete) Do() {
+ d.f(d.offset, d.length)
+}
+func (i Insert) Do() {
+ i.f(i.position, i.text)
+}
+
+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 uint
+ length uint
+}
+
+type MyEditor struct {
+ origin string
+ add string
+ table []piece
+ curLen int
+
+ undoes []Operation
+ redoes []Operation
+}
+
+type del func(uint, uint) *MyEditor
+
+func (m *MyEditor) String() string {
+ var str string
+ for _, pie := range m.table {
+ if pie.origin {
+ str += m.origin[pie.offset:(pie.offset + pie.length)]
+ } else {
+ str += m.add[pie.offset:(pie.offset + pie.length)]
+ }
+ }
+ return str
+}
+func (m *MyEditor) modifyLen(len int) {
+ m.curLen = m.curLen + len
+}
+
+func (m *MyEditor) Redo() MyEditor {
+ if m.redoes != nil && len(m.redoes) > 0 {
+
+ }
+
+ return *m
+}
+
+func (m *MyEditor) Undo() MyEditor {
+ if m.undoes != nil && len(m.undoes) > 0 {
+ last := m.undoes[len(m.undoes)-1]
+ last.Do()
+ // add opposite to redo
+ }
+ return *m
+}
+
+func (m *MyEditor) Delete(offset, len uint) *MyEditor {
+ currentLen := uint(m.curLen)
+
+ if currentLen < offset {
+ return m
+ }
+
+ if offset+len >= currentLen {
+ len = currentLen - offset
+ }
+
+ pieIndex, residualOffset := m.pieIndexAndResidualOffset(offset)
+ lastPieIndex, lastResidualOffset := m.pieIndexAndResidualOffset(offset + len)
+
+ first := piece{
+ origin: m.table[pieIndex].origin,
+ offset: m.table[pieIndex].offset,
+ length: residualOffset,
+ }
+ second := piece{
+ origin: m.table[lastPieIndex].origin,
+ offset: m.table[lastPieIndex].offset + lastResidualOffset,
+ length: m.table[lastPieIndex].length - lastResidualOffset,
+ }
+
+ m.modifyLen(-int(len))
+ parts := []piece{first, second}
+
+ prefix := m.table[:pieIndex]
+ how := lastPieIndex - pieIndex + 1
+ suffix := m.table[pieIndex+how:]
+ whole := append(prefix, append(parts, suffix...)...)
+ m.table = whole
+
+ var i Insert = Insert{m.Insert, offset, ""}
+ m.undoes = append(m.undoes, i)
+
+ return m
+}
+
+func (m *MyEditor) Insert(position uint, text string) *MyEditor {
+ currentLen := uint(m.curLen)
+
+ if position > currentLen {
+ position = currentLen
+ }
+ addOffset := uint(len(m.add))
+ m.add += text
+
+ m.modifyLen(len(text))
+
+ pieIndex, residualOffset := m.pieIndexAndResidualOffset(position)
+ currentPiece := m.table[pieIndex]
+
+ first := piece{
+ origin: currentPiece.origin,
+ offset: currentPiece.offset,
+ length: residualOffset,
+ }
+ second := piece{
+ origin: false,
+ offset: addOffset,
+ length: uint(len(text)),
+ }
+ third := piece{
+ origin: currentPiece.origin,
+ offset: residualOffset,
+ length: currentPiece.length - residualOffset,
+ }
+
+ parts := []piece{first, second, third}
+ prefix := m.table[:pieIndex]
+ suffix := m.table[pieIndex+1:]
+ whole := append(prefix, append(parts, suffix...)...)
+ m.table = whole
+
+ var d Delete = Delete{m.Delete, position, uint(len(text))}
+ m.undoes = append(m.undoes, d)
+ return m
+}
+func (m *MyEditor) pieIndexAndResidualOffset(offset uint) (int, uint) {
+ residualOffset := offset
+
+ for index, pie := range m.table {
+ if residualOffset <= pie.length {
+ return index, residualOffset
+ }
+ residualOffset = residualOffset - pie.length
+ }
+ return 0, 0 // todo return last element no just 0,0
+
+}
+
+func NewEditor(text string) *MyEditor {
+ myEditor := new(MyEditor)
+ myEditor.origin = text
+ myEditor.curLen = len(text)
+ table := []piece{{true, 0, uint(len(text))}}
+ myEditor.table = table
+
+ return myEditor
+}
Решението не е готово!! Качвам го просто ако не успея да го довърша.