Решение на Piece table от Ангел Александров

Обратно към всички решения

Към профила на Ангел Александров

Резултати

  • 10 точки от тестове
  • 0 бонус точки
  • 10 точки общо
  • 8 успешни тест(а)
  • 0 неуспешни тест(а)

Код

package main
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 int
length int
}
type State struct {
pieces []Piece
}
func NewEditor(s string) Editor {
var tm *TextManager = new(TextManager)
tm.originBuffer = []byte(s)
tm.redoStack = make([]State, 0)
tm.pieceTable = make([]State, 1)
var st *State = new(State)
st.pieces = make([]Piece, 1)
st.pieces[0] = Piece{true, 0, len(s)}
tm.pieceTable[0] = *st
return tm
}
type TextManager struct {
originBuffer []byte
addBuffer []byte
pieceTable []State
redoStack []State
}
func (tm *TextManager) getCurrentState() State {
return tm.pieceTable[len(tm.pieceTable)-1]
}
func (tm *TextManager) setNewState(s State) {
tm.pieceTable = append(tm.pieceTable, s)
}
func (tm *TextManager) Insert(position uint, text string) Editor {
offset := len(tm.addBuffer) //len(nil) == 0
tm.redoStack = tm.redoStack[:0]
if tm.addBuffer == nil {
tm.addBuffer = []byte(text)
} else {
tm.addBuffer = append(tm.addBuffer, []byte(text)...)
}
piece := Piece{false, offset, len(text)}
state := tm.getCurrentState()
if length := (uint)(len(tm.String())); position >= length {
state.pieces = append(state.pieces, piece)
} else if position == 0 {
state.pieces = append([]Piece{piece}, state.pieces...)
} else {
var bytes uint = 0
for index, p := range state.pieces {
bytes += (uint)(p.length)
if bytes > position {
i := (int)(position - (bytes - (uint)(p.length)))
p1 := Piece{p.origin, p.offset, i}
p2 := Piece{p.origin, p.offset + i, p.length - i}
toAppend := []Piece{p1, piece, p2}
if index+1 < len(state.pieces) {
toAppend = append(toAppend, state.pieces[index+1:]...)
}
state.pieces = append(state.pieces[:index], toAppend...)
break
}
}
}
tm.setNewState(state)
return tm
}
func (tm *TextManager) Delete(offset, length uint) Editor {
contentLength := (uint)(len(tm.String()))
if offset > contentLength {
return tm
}
if offset+length > contentLength {
length = contentLength - offset
}
tm.redoStack = tm.redoStack[:0]
state := tm.getCurrentState()
resultState := new(State)
resultState.pieces = make([]Piece, 0)
var bytes uint = 0
flag := false
for index, piece := range state.pieces {
bytes += (uint)(piece.length)
if bytes >= offset {
i := (int)(offset - (bytes - (uint)(piece.length)))
var p1, p2 *Piece = new(Piece), new(Piece)
if i != 0 {
*p1 = Piece{piece.origin, piece.offset, i}
}
if length >= (uint)(piece.length-i) {
offset = bytes
length -= (uint)(piece.length - i)
if p1.length != 0 {
resultState.pieces = append(resultState.pieces, *p1)
}
flag = true
continue
} else {
if flag {
size := (int)((uint)(piece.length) - length)
*p2 = Piece{piece.origin, piece.offset + (int)(length), size}
} else {
size := (int)((uint)(piece.length) - length - offset)
*p2 = Piece{piece.origin, piece.offset + (int)(offset) + (int)(length), size}
}
}
if p1.length != 0 {
resultState.pieces = append(resultState.pieces, *p1)
}
if p2.length != 0 {
resultState.pieces = append(resultState.pieces, *p2)
}
if index+1 < len(state.pieces) {
resultState.pieces = append(resultState.pieces, state.pieces[index+1:]...)
}
break
} else {
offset -= (uint)(piece.length) + 1
bytes -= ((uint)(piece.length))
resultState.pieces = append(resultState.pieces, piece)
}
}
tm.setNewState(*resultState)
return tm
}
func (tm *TextManager) Undo() Editor {
if length := len(tm.pieceTable); length > 1 {
tm.redoStack = append(tm.redoStack, tm.pieceTable[length-1])
tm.pieceTable = tm.pieceTable[:length-1]
}
return tm
}
func (tm *TextManager) Redo() Editor {
if length := len(tm.redoStack); length > 0 {
tm.pieceTable = append(tm.pieceTable, tm.redoStack[length-1])
tm.redoStack = tm.redoStack[:length-1]
}
return tm
}
func (tm *TextManager) String() string {
i := len(tm.pieceTable) - 1
res := []byte{}
for _, p := range tm.pieceTable[i].pieces {
if p.origin {
res = append(res, tm.originBuffer[p.offset:p.offset+p.length]...)
} else {
res = append(res, tm.addBuffer[p.offset:p.offset+p.length]...)
}
}
return string(res)
}

Лог от изпълнението

PASS
ok  	_/tmp/d20181107-53-1dek1o8	0.002s
PASS
ok  	_/tmp/d20181107-53-1dek1o8	0.002s
PASS
ok  	_/tmp/d20181107-53-1dek1o8	0.002s
PASS
ok  	_/tmp/d20181107-53-1dek1o8	0.003s
PASS
ok  	_/tmp/d20181107-53-1dek1o8	0.002s
PASS
ok  	_/tmp/d20181107-53-1dek1o8	0.002s
PASS
ok  	_/tmp/d20181107-53-1dek1o8	0.002s
PASS
ok  	_/tmp/d20181107-53-1dek1o8	0.002s

История (1 версия и 2 коментара)

Ангел обнови решението на 04.11.2018 14:50 (преди 9 месеца)

+package main
+
+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 int
+ length int
+}
+
+type State struct {
+ pieces []Piece
+}
+
+func NewEditor(s string) Editor {
+ var tm *TextManager = new(TextManager)
+ tm.originBuffer = []byte(s)
+ tm.redoStack = make([]State, 0)
+ tm.pieceTable = make([]State, 1)
+ var st *State = new(State)
+ st.pieces = make([]Piece, 1)
+ st.pieces[0] = Piece{true, 0, len(s)}
+ tm.pieceTable[0] = *st
+ return tm
+}
+
+type TextManager struct {
+ originBuffer []byte
+ addBuffer []byte
+ pieceTable []State
+ redoStack []State
+}
+
+func (tm *TextManager) getCurrentState() State {
+ return tm.pieceTable[len(tm.pieceTable)-1]
+}
+
+func (tm *TextManager) setNewState(s State) {
+ tm.pieceTable = append(tm.pieceTable, s)
+}
+
+func (tm *TextManager) Insert(position uint, text string) Editor {
+ offset := len(tm.addBuffer) //len(nil) == 0
+
+ tm.redoStack = tm.redoStack[:0]
+
+ if tm.addBuffer == nil {
+ tm.addBuffer = []byte(text)
+ } else {
+ tm.addBuffer = append(tm.addBuffer, []byte(text)...)
+ }
+ piece := Piece{false, offset, len(text)}
+
+ state := tm.getCurrentState()
+ if length := (uint)(len(tm.String())); position >= length {
+ state.pieces = append(state.pieces, piece)
+ } else if position == 0 {
+ state.pieces = append([]Piece{piece}, state.pieces...)
+ } else {
+ var bytes uint = 0
+
+ for index, p := range state.pieces {
+ bytes += (uint)(p.length)
+ if bytes > position {
+ i := (int)(position - (bytes - (uint)(p.length)))
+ p1 := Piece{p.origin, p.offset, i}
+ p2 := Piece{p.origin, p.offset + i, p.length - i}
+ toAppend := []Piece{p1, piece, p2}
+ if index+1 < len(state.pieces) {
+ toAppend = append(toAppend, state.pieces[index+1:]...)
+ }
+ state.pieces = append(state.pieces[:index], toAppend...)
+ break
+ }
+ }
+ }
+ tm.setNewState(state)
+ return tm
+}
+
+func (tm *TextManager) Delete(offset, length uint) Editor {
+ contentLength := (uint)(len(tm.String()))
+ if offset > contentLength {
+ return tm
+ }
+ if offset+length > contentLength {
+ length = contentLength - offset
+ }
+
+ tm.redoStack = tm.redoStack[:0]
+
+ state := tm.getCurrentState()
+ resultState := new(State)
+ resultState.pieces = make([]Piece, 0)
+ var bytes uint = 0
+ flag := false
+ for index, piece := range state.pieces {
+ bytes += (uint)(piece.length)
+ if bytes >= offset {
+ i := (int)(offset - (bytes - (uint)(piece.length)))
+ var p1, p2 *Piece = new(Piece), new(Piece)
+ if i != 0 {
+ *p1 = Piece{piece.origin, piece.offset, i}
+ }
+ if length >= (uint)(piece.length-i) {
+ offset = bytes
+ length -= (uint)(piece.length - i)
+ if p1.length != 0 {
+ resultState.pieces = append(resultState.pieces, *p1)
+ }
+ flag = true
+ continue
+ } else {
+ if flag {
+ size := (int)((uint)(piece.length) - length)
+ *p2 = Piece{piece.origin, piece.offset + (int)(length), size}
+ } else {
+ size := (int)((uint)(piece.length) - length - offset)
+ *p2 = Piece{piece.origin, piece.offset + (int)(offset) + (int)(length), size}
+ }
+ }
+ if p1.length != 0 {
+ resultState.pieces = append(resultState.pieces, *p1)
+ }
+ if p2.length != 0 {
+ resultState.pieces = append(resultState.pieces, *p2)
+ }
+ if index+1 < len(state.pieces) {
+ resultState.pieces = append(resultState.pieces, state.pieces[index+1:]...)
+ }
+ break
+ } else {
+ offset -= (uint)(piece.length) + 1
+ bytes -= ((uint)(piece.length))
+ resultState.pieces = append(resultState.pieces, piece)
+ }
+ }
+ tm.setNewState(*resultState)
+ return tm
+}
+
+func (tm *TextManager) Undo() Editor {
+ if length := len(tm.pieceTable); length > 1 {
+ tm.redoStack = append(tm.redoStack, tm.pieceTable[length-1])
+ tm.pieceTable = tm.pieceTable[:length-1]
+ }
+ return tm
+}
+
+func (tm *TextManager) Redo() Editor {
+ if length := len(tm.redoStack); length > 0 {
+ tm.pieceTable = append(tm.pieceTable, tm.redoStack[length-1])
+ tm.redoStack = tm.redoStack[:length-1]
+ }
+ return tm
+}
+
+func (tm *TextManager) String() string {
+ i := len(tm.pieceTable) - 1
+ res := []byte{}
+ for _, p := range tm.pieceTable[i].pieces {
+ if p.origin {
+ res = append(res, tm.originBuffer[p.offset:p.offset+p.length]...)
+ } else {
+ res = append(res, tm.addBuffer[p.offset:p.offset+p.length]...)
+ }
+ }
+ return string(res)
+}