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

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

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

Резултати

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

Код

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 pieceTable []piece
type editorState struct {
pieces *pieceTable
prev *editorState
next *editorState
}
// ConcreteEditor is an implementation of the Editor interface
type ConcreteEditor struct {
originBuffer string
addBuffer string
state *editorState
}
func (ce *ConcreteEditor) Insert(position uint, text string) Editor {
var currentPosition uint
for i, currentPiece := range *ce.state.pieces {
if currentPosition <= position && position < (currentPosition+currentPiece.length) {
ce.commitTable(ce.insertWithinPiece((uint)(i), position-currentPosition, text))
return ce
}
currentPosition += currentPiece.length
}
ce.commitTable(ce.insertAtTheEnd(text))
return ce
}
func (ce *ConcreteEditor) insertWithinPiece(pieceNum uint, pieceOffset uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+2)
toSplit := (*ce.state.pieces)[pieceNum]
leftPiece := piece{
origin: toSplit.origin,
offset: toSplit.offset,
length: pieceOffset}
midPiece := piece{
origin: false,
offset: (uint)(len(ce.addBuffer)),
length: (uint)(len(text))}
rightPiece := piece{
origin: toSplit.origin,
offset: toSplit.offset + pieceOffset,
length: toSplit.length - pieceOffset}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
if leftPiece.length != 0 {
newTable = append(newTable, leftPiece)
}
newTable = append(newTable, midPiece, rightPiece)
newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertAtTheEnd(text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midPiece := piece{
origin: false,
offset: (uint)(len(ce.addBuffer)),
length: (uint)(len(text))}
ce.addBuffer += text
newTable = append(*ce.state.pieces, midPiece)
return &newTable
}
func (ce *ConcreteEditor) Delete(offset, length uint) Editor {
var currentStart, charsToDelete uint
leftToDelete := length
currentOffset := offset
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
for _, currentPiece := range *ce.state.pieces {
if leftToDelete == 0 || currentOffset < currentStart || currentOffset > currentStart+currentPiece.length {
// nothing to do with this piece, just copy it to the new table
newTable = append(newTable, currentPiece)
} else {
rightPieceEmpty := currentPiece.length <= (currentOffset - currentStart + leftToDelete)
if rightPieceEmpty {
charsToDelete = currentPiece.length - (currentOffset - currentStart)
} else {
charsToDelete = leftToDelete
}
leftPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset,
length: currentOffset - currentStart}
rightPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset + (currentOffset - currentStart) + charsToDelete,
length: currentPiece.length - charsToDelete - (currentOffset - currentStart)}
if leftPiece.length > 0 {
newTable = append(newTable, leftPiece)
}
if !rightPieceEmpty {
newTable = append(newTable, rightPiece)
}
leftToDelete -= charsToDelete
currentOffset += charsToDelete
}
currentStart += currentPiece.length
}
ce.commitTable(&newTable)
return ce
}
func (ce *ConcreteEditor) commitTable(newTable *pieceTable) {
newState := editorState{pieces: newTable}
ce.state.next = &newState
newState.prev = ce.state
ce.state = &newState
}
func (ce *ConcreteEditor) Undo() Editor {
if ce.state.prev != nil {
ce.state = ce.state.prev
}
return ce
}
func (ce *ConcreteEditor) Redo() Editor {
if ce.state.next != nil {
ce.state = ce.state.next
}
return ce
}
func (ce *ConcreteEditor) String() string {
var result = ""
for _, piece := range *ce.state.pieces {
var currentBuffer *string
if piece.origin {
currentBuffer = &ce.originBuffer
} else {
currentBuffer = &ce.addBuffer
}
result += (*currentBuffer)[piece.offset : piece.offset+piece.length]
}
return result
}
// NewEditor creates an editor instance from a string
func NewEditor(s string) Editor {
pieces := pieceTable{
piece{
origin: true,
offset: 0,
length: (uint)(len(s))}}
state := editorState{pieces: &pieces}
return &ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
}

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

PASS
ok  	_/tmp/d20181107-53-vb4k14	0.002s
PASS
ok  	_/tmp/d20181107-53-vb4k14	0.002s
PASS
ok  	_/tmp/d20181107-53-vb4k14	0.002s
PASS
ok  	_/tmp/d20181107-53-vb4k14	0.002s
PASS
ok  	_/tmp/d20181107-53-vb4k14	0.002s
PASS
ok  	_/tmp/d20181107-53-vb4k14	0.002s
PASS
ok  	_/tmp/d20181107-53-vb4k14	0.002s
PASS
ok  	_/tmp/d20181107-53-vb4k14	0.002s

История (10 версии и 0 коментара)

Александър обнови решението на 07.11.2018 12:46 (преди 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 pieceTable []piece
+
+type editorState struct {
+ pieces *pieceTable
+ prev *editorState
+ next *editorState
+}
+
+// ConcreteEditor is an implementation of the Editor interface
+type ConcreteEditor struct {
+ originBuffer string
+ addBuffer string
+ state *editorState
+}
+
+func (ce *ConcreteEditor) Insert(position uint, text string) Editor {
+ var currentPosition, i uint
+
+ for i < (uint)(len(*ce.state.pieces)) {
+ if currentPosition == position {
+ ce.commitTable(ce.insertBeforePiece(i, text))
+
+ return ce
+ } else if currentPosition < position && position < (currentPosition+(*ce.state.pieces)[i].length) {
+ ce.commitTable(ce.insertWithinPiece(i, position-currentPosition, text))
+
+ return ce
+ }
+
+ currentPosition += (*ce.state.pieces)[i].length
+ i++
+ }
+
+ ce.commitTable(ce.insertAtTheEnd(text))
+
+ return ce
+}
+
+func (ce *ConcreteEditor) insertWithinPiece(pieceNum uint, pieceOffset uint, text string) *pieceTable {
+ newTable := make(pieceTable, 0, len(*ce.state.pieces)+2)
+ toSplit := (*ce.state.pieces)[pieceNum]
+
+ leftP := piece{origin: toSplit.origin, offset: toSplit.offset, length: pieceOffset}
+ midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
+ rightP := piece{origin: toSplit.origin, offset: toSplit.offset + pieceOffset, length: toSplit.length - pieceOffset}
+
+ newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
+ newTable = append(newTable, leftP, midP, rightP)
+ newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
+
+ ce.addBuffer += text
+
+ return &newTable
+}
+
+func (ce *ConcreteEditor) insertBeforePiece(pieceNum uint, text string) *pieceTable {
+ newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
+
+ midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
+
+ newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
+ newTable = append(newTable, midP)
+ newTable = append(newTable, (*ce.state.pieces)[pieceNum:]...)
+
+ ce.addBuffer += text
+
+ return &newTable
+}
+
+func (ce *ConcreteEditor) insertAtTheEnd(text string) *pieceTable {
+ newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
+ midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
+
+ ce.addBuffer += text
+
+ newTable = append(*ce.state.pieces, midP)
+
+ return &newTable
+}
+
+func (ce *ConcreteEditor) Delete(offset, length uint) Editor {
+ var currentStart, charsToDelete uint
+
+ leftToDelete := length
+ currentOffset := offset
+
+ newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
+
+ // for i < (uint)(len(*ce.state.pieces)) {
+ for i, currentPiece := range *ce.state.pieces {
+ // currentPiece = (*ce.state.pieces)[i]
+
+ if leftToDelete == 0 || currentOffset < currentStart || currentOffset > currentStart+currentPiece.length {
+ // nothing to do with this piece, just copy it to the new table
+ newTable = append(newTable, currentPiece)
+ } else {
+ rightPieceEmpty := currentPiece.length <= (currentOffset - currentStart + leftToDelete)
+
+ if rightPieceEmpty {
+ charsToDelete = currentPiece.length - currentOffset - currentStart
+ } else {
+ charsToDelete = leftToDelete
+ }
+
+ leftPiece := piece{
+ origin: currentPiece.origin,
+ offset: currentPiece.offset,
+ length: currentOffset - currentStart}
+
+ rightPiece := piece{
+ origin: currentPiece.origin,
+ offset: currentPiece.offset + currentOffset + charsToDelete,
+ length: currentPiece.length - charsToDelete - (currentOffset - currentStart)}
+
+ if leftPiece.length > 0 {
+ newTable = append(newTable, leftPiece)
+ }
+
+ if !rightPieceEmpty {
+ newTable = append(newTable, rightPiece)
+ }
+
+ leftToDelete -= charsToDelete
+ currentOffset += charsToDelete
+ }
+
+ currentStart += currentPiece.length
+ i++
+ }
+
+ ce.commitTable(&newTable)
+
+ return ce
+}
+
+func (ce *ConcreteEditor) commitTable(newTable *pieceTable) {
+ newState := editorState{pieces: newTable}
+
+ ce.state.next = &newState
+ newState.prev = ce.state
+ ce.state = &newState
+}
+
+func (ce *ConcreteEditor) Undo() Editor {
+ if ce.state.prev != nil {
+ ce.state = ce.state.prev
+ }
+
+ return ce
+}
+
+func (ce *ConcreteEditor) Redo() Editor {
+ if ce.state.next != nil {
+ ce.state = ce.state.next
+ }
+
+ return ce
+}
+
+func (ce *ConcreteEditor) String() string {
+ var result = ""
+ for _, piece := range *ce.state.pieces {
+ var buffer *string
+
+ if piece.origin {
+ buffer = &ce.originBuffer
+ } else {
+ buffer = &ce.addBuffer
+ }
+
+ result += (*buffer)[piece.offset:(piece.offset + piece.length)]
+ }
+
+ return result
+}
+
+// NewEditor creates an editor instance from a string
+func NewEditor(s string) ConcreteEditor {
+ pieces := pieceTable{piece{origin: true, offset: 0, length: (uint)(len(s))}}
+ state := editorState{pieces: &pieces}
+
+ return ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
+}

Александър обнови решението на 07.11.2018 12:48 (преди 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 pieceTable []piece
type editorState struct {
pieces *pieceTable
prev *editorState
next *editorState
}
// ConcreteEditor is an implementation of the Editor interface
type ConcreteEditor struct {
originBuffer string
addBuffer string
state *editorState
}
func (ce *ConcreteEditor) Insert(position uint, text string) Editor {
var currentPosition, i uint
for i < (uint)(len(*ce.state.pieces)) {
if currentPosition == position {
ce.commitTable(ce.insertBeforePiece(i, text))
return ce
} else if currentPosition < position && position < (currentPosition+(*ce.state.pieces)[i].length) {
ce.commitTable(ce.insertWithinPiece(i, position-currentPosition, text))
return ce
}
currentPosition += (*ce.state.pieces)[i].length
i++
}
ce.commitTable(ce.insertAtTheEnd(text))
return ce
}
func (ce *ConcreteEditor) insertWithinPiece(pieceNum uint, pieceOffset uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+2)
toSplit := (*ce.state.pieces)[pieceNum]
leftP := piece{origin: toSplit.origin, offset: toSplit.offset, length: pieceOffset}
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
rightP := piece{origin: toSplit.origin, offset: toSplit.offset + pieceOffset, length: toSplit.length - pieceOffset}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
newTable = append(newTable, leftP, midP, rightP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertBeforePiece(pieceNum uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
newTable = append(newTable, midP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertAtTheEnd(text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
ce.addBuffer += text
newTable = append(*ce.state.pieces, midP)
return &newTable
}
func (ce *ConcreteEditor) Delete(offset, length uint) Editor {
var currentStart, charsToDelete uint
leftToDelete := length
currentOffset := offset
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
- // for i < (uint)(len(*ce.state.pieces)) {
for i, currentPiece := range *ce.state.pieces {
// currentPiece = (*ce.state.pieces)[i]
if leftToDelete == 0 || currentOffset < currentStart || currentOffset > currentStart+currentPiece.length {
// nothing to do with this piece, just copy it to the new table
newTable = append(newTable, currentPiece)
} else {
rightPieceEmpty := currentPiece.length <= (currentOffset - currentStart + leftToDelete)
if rightPieceEmpty {
charsToDelete = currentPiece.length - currentOffset - currentStart
} else {
charsToDelete = leftToDelete
}
leftPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset,
length: currentOffset - currentStart}
rightPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset + currentOffset + charsToDelete,
length: currentPiece.length - charsToDelete - (currentOffset - currentStart)}
if leftPiece.length > 0 {
newTable = append(newTable, leftPiece)
}
if !rightPieceEmpty {
newTable = append(newTable, rightPiece)
}
leftToDelete -= charsToDelete
currentOffset += charsToDelete
}
currentStart += currentPiece.length
i++
}
ce.commitTable(&newTable)
return ce
}
func (ce *ConcreteEditor) commitTable(newTable *pieceTable) {
newState := editorState{pieces: newTable}
ce.state.next = &newState
newState.prev = ce.state
ce.state = &newState
}
func (ce *ConcreteEditor) Undo() Editor {
if ce.state.prev != nil {
ce.state = ce.state.prev
}
return ce
}
func (ce *ConcreteEditor) Redo() Editor {
if ce.state.next != nil {
ce.state = ce.state.next
}
return ce
}
func (ce *ConcreteEditor) String() string {
var result = ""
for _, piece := range *ce.state.pieces {
var buffer *string
if piece.origin {
buffer = &ce.originBuffer
} else {
buffer = &ce.addBuffer
}
result += (*buffer)[piece.offset:(piece.offset + piece.length)]
}
return result
}
// NewEditor creates an editor instance from a string
func NewEditor(s string) ConcreteEditor {
pieces := pieceTable{piece{origin: true, offset: 0, length: (uint)(len(s))}}
state := editorState{pieces: &pieces}
return ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
}

Александър обнови решението на 07.11.2018 12:49 (преди 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 pieceTable []piece
type editorState struct {
pieces *pieceTable
prev *editorState
next *editorState
}
// ConcreteEditor is an implementation of the Editor interface
type ConcreteEditor struct {
originBuffer string
addBuffer string
state *editorState
}
func (ce *ConcreteEditor) Insert(position uint, text string) Editor {
var currentPosition, i uint
for i < (uint)(len(*ce.state.pieces)) {
if currentPosition == position {
ce.commitTable(ce.insertBeforePiece(i, text))
return ce
} else if currentPosition < position && position < (currentPosition+(*ce.state.pieces)[i].length) {
ce.commitTable(ce.insertWithinPiece(i, position-currentPosition, text))
return ce
}
currentPosition += (*ce.state.pieces)[i].length
i++
}
ce.commitTable(ce.insertAtTheEnd(text))
return ce
}
func (ce *ConcreteEditor) insertWithinPiece(pieceNum uint, pieceOffset uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+2)
toSplit := (*ce.state.pieces)[pieceNum]
leftP := piece{origin: toSplit.origin, offset: toSplit.offset, length: pieceOffset}
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
rightP := piece{origin: toSplit.origin, offset: toSplit.offset + pieceOffset, length: toSplit.length - pieceOffset}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
newTable = append(newTable, leftP, midP, rightP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertBeforePiece(pieceNum uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
newTable = append(newTable, midP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertAtTheEnd(text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
ce.addBuffer += text
newTable = append(*ce.state.pieces, midP)
return &newTable
}
func (ce *ConcreteEditor) Delete(offset, length uint) Editor {
var currentStart, charsToDelete uint
leftToDelete := length
currentOffset := offset
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
for i, currentPiece := range *ce.state.pieces {
- // currentPiece = (*ce.state.pieces)[i]
-
if leftToDelete == 0 || currentOffset < currentStart || currentOffset > currentStart+currentPiece.length {
// nothing to do with this piece, just copy it to the new table
newTable = append(newTable, currentPiece)
} else {
rightPieceEmpty := currentPiece.length <= (currentOffset - currentStart + leftToDelete)
if rightPieceEmpty {
charsToDelete = currentPiece.length - currentOffset - currentStart
} else {
charsToDelete = leftToDelete
}
leftPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset,
length: currentOffset - currentStart}
rightPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset + currentOffset + charsToDelete,
length: currentPiece.length - charsToDelete - (currentOffset - currentStart)}
if leftPiece.length > 0 {
newTable = append(newTable, leftPiece)
}
if !rightPieceEmpty {
newTable = append(newTable, rightPiece)
}
leftToDelete -= charsToDelete
currentOffset += charsToDelete
}
currentStart += currentPiece.length
i++
}
ce.commitTable(&newTable)
return ce
}
func (ce *ConcreteEditor) commitTable(newTable *pieceTable) {
newState := editorState{pieces: newTable}
ce.state.next = &newState
newState.prev = ce.state
ce.state = &newState
}
func (ce *ConcreteEditor) Undo() Editor {
if ce.state.prev != nil {
ce.state = ce.state.prev
}
return ce
}
func (ce *ConcreteEditor) Redo() Editor {
if ce.state.next != nil {
ce.state = ce.state.next
}
return ce
}
func (ce *ConcreteEditor) String() string {
var result = ""
for _, piece := range *ce.state.pieces {
var buffer *string
if piece.origin {
buffer = &ce.originBuffer
} else {
buffer = &ce.addBuffer
}
result += (*buffer)[piece.offset:(piece.offset + piece.length)]
}
return result
}
// NewEditor creates an editor instance from a string
func NewEditor(s string) ConcreteEditor {
pieces := pieceTable{piece{origin: true, offset: 0, length: (uint)(len(s))}}
state := editorState{pieces: &pieces}
return ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
}

Александър обнови решението на 07.11.2018 13:19 (преди 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 pieceTable []piece
type editorState struct {
pieces *pieceTable
prev *editorState
next *editorState
}
// ConcreteEditor is an implementation of the Editor interface
type ConcreteEditor struct {
originBuffer string
addBuffer string
state *editorState
}
-func (ce *ConcreteEditor) Insert(position uint, text string) Editor {
+func (ce ConcreteEditor) Insert(position uint, text string) Editor {
var currentPosition, i uint
for i < (uint)(len(*ce.state.pieces)) {
if currentPosition == position {
ce.commitTable(ce.insertBeforePiece(i, text))
return ce
} else if currentPosition < position && position < (currentPosition+(*ce.state.pieces)[i].length) {
ce.commitTable(ce.insertWithinPiece(i, position-currentPosition, text))
return ce
}
currentPosition += (*ce.state.pieces)[i].length
i++
}
ce.commitTable(ce.insertAtTheEnd(text))
return ce
}
func (ce *ConcreteEditor) insertWithinPiece(pieceNum uint, pieceOffset uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+2)
toSplit := (*ce.state.pieces)[pieceNum]
leftP := piece{origin: toSplit.origin, offset: toSplit.offset, length: pieceOffset}
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
rightP := piece{origin: toSplit.origin, offset: toSplit.offset + pieceOffset, length: toSplit.length - pieceOffset}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
newTable = append(newTable, leftP, midP, rightP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertBeforePiece(pieceNum uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
newTable = append(newTable, midP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertAtTheEnd(text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
ce.addBuffer += text
newTable = append(*ce.state.pieces, midP)
return &newTable
}
-func (ce *ConcreteEditor) Delete(offset, length uint) Editor {
+func (ce ConcreteEditor) Delete(offset, length uint) Editor {
var currentStart, charsToDelete uint
leftToDelete := length
currentOffset := offset
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
for i, currentPiece := range *ce.state.pieces {
if leftToDelete == 0 || currentOffset < currentStart || currentOffset > currentStart+currentPiece.length {
// nothing to do with this piece, just copy it to the new table
newTable = append(newTable, currentPiece)
} else {
rightPieceEmpty := currentPiece.length <= (currentOffset - currentStart + leftToDelete)
if rightPieceEmpty {
charsToDelete = currentPiece.length - currentOffset - currentStart
} else {
charsToDelete = leftToDelete
}
+
leftPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset,
length: currentOffset - currentStart}
rightPiece := piece{
origin: currentPiece.origin,
- offset: currentPiece.offset + currentOffset + charsToDelete,
+ offset: currentOffset + charsToDelete,
length: currentPiece.length - charsToDelete - (currentOffset - currentStart)}
+
if leftPiece.length > 0 {
newTable = append(newTable, leftPiece)
}
if !rightPieceEmpty {
newTable = append(newTable, rightPiece)
}
leftToDelete -= charsToDelete
currentOffset += charsToDelete
}
currentStart += currentPiece.length
i++
}
ce.commitTable(&newTable)
return ce
}
func (ce *ConcreteEditor) commitTable(newTable *pieceTable) {
newState := editorState{pieces: newTable}
ce.state.next = &newState
newState.prev = ce.state
ce.state = &newState
}
-func (ce *ConcreteEditor) Undo() Editor {
+func (ce ConcreteEditor) Undo() Editor {
if ce.state.prev != nil {
ce.state = ce.state.prev
}
return ce
}
-func (ce *ConcreteEditor) Redo() Editor {
+func (ce ConcreteEditor) Redo() Editor {
if ce.state.next != nil {
ce.state = ce.state.next
}
return ce
}
-func (ce *ConcreteEditor) String() string {
+func (ce ConcreteEditor) String() string {
var result = ""
for _, piece := range *ce.state.pieces {
var buffer *string
if piece.origin {
buffer = &ce.originBuffer
} else {
buffer = &ce.addBuffer
}
result += (*buffer)[piece.offset:(piece.offset + piece.length)]
}
return result
}
// NewEditor creates an editor instance from a string
-func NewEditor(s string) ConcreteEditor {
+func NewEditor(s string) Editor {
pieces := pieceTable{piece{origin: true, offset: 0, length: (uint)(len(s))}}
state := editorState{pieces: &pieces}
return ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
}

Александър обнови решението на 07.11.2018 13:37 (преди 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 pieceTable []piece
type editorState struct {
pieces *pieceTable
prev *editorState
next *editorState
}
// ConcreteEditor is an implementation of the Editor interface
type ConcreteEditor struct {
originBuffer string
addBuffer string
state *editorState
}
func (ce ConcreteEditor) Insert(position uint, text string) Editor {
var currentPosition, i uint
for i < (uint)(len(*ce.state.pieces)) {
if currentPosition == position {
ce.commitTable(ce.insertBeforePiece(i, text))
return ce
} else if currentPosition < position && position < (currentPosition+(*ce.state.pieces)[i].length) {
ce.commitTable(ce.insertWithinPiece(i, position-currentPosition, text))
return ce
}
currentPosition += (*ce.state.pieces)[i].length
i++
}
ce.commitTable(ce.insertAtTheEnd(text))
return ce
}
func (ce *ConcreteEditor) insertWithinPiece(pieceNum uint, pieceOffset uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+2)
toSplit := (*ce.state.pieces)[pieceNum]
leftP := piece{origin: toSplit.origin, offset: toSplit.offset, length: pieceOffset}
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
rightP := piece{origin: toSplit.origin, offset: toSplit.offset + pieceOffset, length: toSplit.length - pieceOffset}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
newTable = append(newTable, leftP, midP, rightP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertBeforePiece(pieceNum uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
newTable = append(newTable, midP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertAtTheEnd(text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
ce.addBuffer += text
newTable = append(*ce.state.pieces, midP)
return &newTable
}
func (ce ConcreteEditor) Delete(offset, length uint) Editor {
var currentStart, charsToDelete uint
leftToDelete := length
currentOffset := offset
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
for i, currentPiece := range *ce.state.pieces {
+
if leftToDelete == 0 || currentOffset < currentStart || currentOffset > currentStart+currentPiece.length {
// nothing to do with this piece, just copy it to the new table
newTable = append(newTable, currentPiece)
} else {
rightPieceEmpty := currentPiece.length <= (currentOffset - currentStart + leftToDelete)
if rightPieceEmpty {
- charsToDelete = currentPiece.length - currentOffset - currentStart
+ charsToDelete = currentPiece.length - (currentOffset - currentStart)
} else {
charsToDelete = leftToDelete
}
-
leftPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset,
length: currentOffset - currentStart}
rightPiece := piece{
origin: currentPiece.origin,
- offset: currentOffset + charsToDelete,
+ offset: currentPiece.offset + (currentOffset - currentStart) + charsToDelete,
length: currentPiece.length - charsToDelete - (currentOffset - currentStart)}
-
if leftPiece.length > 0 {
newTable = append(newTable, leftPiece)
}
if !rightPieceEmpty {
newTable = append(newTable, rightPiece)
}
leftToDelete -= charsToDelete
currentOffset += charsToDelete
}
currentStart += currentPiece.length
i++
}
ce.commitTable(&newTable)
return ce
}
func (ce *ConcreteEditor) commitTable(newTable *pieceTable) {
newState := editorState{pieces: newTable}
ce.state.next = &newState
newState.prev = ce.state
ce.state = &newState
}
func (ce ConcreteEditor) Undo() Editor {
if ce.state.prev != nil {
ce.state = ce.state.prev
}
return ce
}
func (ce ConcreteEditor) Redo() Editor {
if ce.state.next != nil {
ce.state = ce.state.next
}
return ce
}
func (ce ConcreteEditor) String() string {
var result = ""
for _, piece := range *ce.state.pieces {
var buffer *string
if piece.origin {
buffer = &ce.originBuffer
} else {
buffer = &ce.addBuffer
}
result += (*buffer)[piece.offset:(piece.offset + piece.length)]
}
return result
}
// NewEditor creates an editor instance from a string
func NewEditor(s string) Editor {
pieces := pieceTable{piece{origin: true, offset: 0, length: (uint)(len(s))}}
state := editorState{pieces: &pieces}
return ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
}

Александър обнови решението на 07.11.2018 13:45 (преди 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 pieceTable []piece
type editorState struct {
pieces *pieceTable
prev *editorState
next *editorState
}
// ConcreteEditor is an implementation of the Editor interface
type ConcreteEditor struct {
originBuffer string
addBuffer string
state *editorState
}
func (ce ConcreteEditor) Insert(position uint, text string) Editor {
- var currentPosition, i uint
+ var currentPosition uint
- for i < (uint)(len(*ce.state.pieces)) {
+ for i := range *ce.state.pieces {
if currentPosition == position {
- ce.commitTable(ce.insertBeforePiece(i, text))
+ ce.commitTable(ce.insertBeforePiece((uint)(i), text))
return ce
} else if currentPosition < position && position < (currentPosition+(*ce.state.pieces)[i].length) {
- ce.commitTable(ce.insertWithinPiece(i, position-currentPosition, text))
+ ce.commitTable(ce.insertWithinPiece((uint)(i), position-currentPosition, text))
return ce
}
currentPosition += (*ce.state.pieces)[i].length
i++
}
ce.commitTable(ce.insertAtTheEnd(text))
return ce
}
func (ce *ConcreteEditor) insertWithinPiece(pieceNum uint, pieceOffset uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+2)
toSplit := (*ce.state.pieces)[pieceNum]
leftP := piece{origin: toSplit.origin, offset: toSplit.offset, length: pieceOffset}
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
rightP := piece{origin: toSplit.origin, offset: toSplit.offset + pieceOffset, length: toSplit.length - pieceOffset}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
newTable = append(newTable, leftP, midP, rightP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertBeforePiece(pieceNum uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
newTable = append(newTable, midP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertAtTheEnd(text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
ce.addBuffer += text
newTable = append(*ce.state.pieces, midP)
return &newTable
}
func (ce ConcreteEditor) Delete(offset, length uint) Editor {
var currentStart, charsToDelete uint
leftToDelete := length
currentOffset := offset
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
for i, currentPiece := range *ce.state.pieces {
if leftToDelete == 0 || currentOffset < currentStart || currentOffset > currentStart+currentPiece.length {
// nothing to do with this piece, just copy it to the new table
newTable = append(newTable, currentPiece)
} else {
rightPieceEmpty := currentPiece.length <= (currentOffset - currentStart + leftToDelete)
if rightPieceEmpty {
charsToDelete = currentPiece.length - (currentOffset - currentStart)
} else {
charsToDelete = leftToDelete
}
leftPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset,
length: currentOffset - currentStart}
rightPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset + (currentOffset - currentStart) + charsToDelete,
length: currentPiece.length - charsToDelete - (currentOffset - currentStart)}
if leftPiece.length > 0 {
newTable = append(newTable, leftPiece)
}
if !rightPieceEmpty {
newTable = append(newTable, rightPiece)
}
leftToDelete -= charsToDelete
currentOffset += charsToDelete
}
currentStart += currentPiece.length
i++
}
ce.commitTable(&newTable)
return ce
}
func (ce *ConcreteEditor) commitTable(newTable *pieceTable) {
newState := editorState{pieces: newTable}
ce.state.next = &newState
newState.prev = ce.state
ce.state = &newState
}
func (ce ConcreteEditor) Undo() Editor {
if ce.state.prev != nil {
ce.state = ce.state.prev
}
return ce
}
func (ce ConcreteEditor) Redo() Editor {
if ce.state.next != nil {
ce.state = ce.state.next
}
return ce
}
func (ce ConcreteEditor) String() string {
var result = ""
for _, piece := range *ce.state.pieces {
var buffer *string
if piece.origin {
buffer = &ce.originBuffer
} else {
buffer = &ce.addBuffer
}
result += (*buffer)[piece.offset:(piece.offset + piece.length)]
}
return result
}
// NewEditor creates an editor instance from a string
func NewEditor(s string) Editor {
pieces := pieceTable{piece{origin: true, offset: 0, length: (uint)(len(s))}}
state := editorState{pieces: &pieces}
return ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
}

Александър обнови решението на 07.11.2018 13:51 (преди 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 pieceTable []piece
type editorState struct {
pieces *pieceTable
prev *editorState
next *editorState
}
// ConcreteEditor is an implementation of the Editor interface
type ConcreteEditor struct {
originBuffer string
addBuffer string
state *editorState
}
func (ce ConcreteEditor) Insert(position uint, text string) Editor {
var currentPosition uint
for i := range *ce.state.pieces {
- if currentPosition == position {
- ce.commitTable(ce.insertBeforePiece((uint)(i), text))
-
- return ce
- } else if currentPosition < position && position < (currentPosition+(*ce.state.pieces)[i].length) {
+ if currentPosition <= position && position < (currentPosition+(*ce.state.pieces)[i].length) {
ce.commitTable(ce.insertWithinPiece((uint)(i), position-currentPosition, text))
return ce
}
currentPosition += (*ce.state.pieces)[i].length
i++
}
ce.commitTable(ce.insertAtTheEnd(text))
return ce
}
func (ce *ConcreteEditor) insertWithinPiece(pieceNum uint, pieceOffset uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+2)
toSplit := (*ce.state.pieces)[pieceNum]
- leftP := piece{origin: toSplit.origin, offset: toSplit.offset, length: pieceOffset}
- midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
- rightP := piece{origin: toSplit.origin, offset: toSplit.offset + pieceOffset, length: toSplit.length - pieceOffset}
+ leftP := piece{
+ origin: toSplit.origin,
+ offset: toSplit.offset,
+ length: pieceOffset}
- newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
- newTable = append(newTable, leftP, midP, rightP)
- newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
+ midP := piece{
+ origin: false,
+ offset: (uint)(len(ce.addBuffer)),
+ length: (uint)(len(text))}
- ce.addBuffer += text
+ rightP := piece{
+ origin: toSplit.origin,
+ offset: toSplit.offset + pieceOffset,
+ length: toSplit.length - pieceOffset}
- return &newTable
-}
+ newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
-func (ce *ConcreteEditor) insertBeforePiece(pieceNum uint, text string) *pieceTable {
- newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
+ if leftP.length != 0 {
+ newTable = append(newTable, leftP)
+ }
- midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
-
- newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
- newTable = append(newTable, midP)
- newTable = append(newTable, (*ce.state.pieces)[pieceNum:]...)
+ newTable = append(newTable, midP, rightP)
+ newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertAtTheEnd(text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
ce.addBuffer += text
newTable = append(*ce.state.pieces, midP)
return &newTable
}
func (ce ConcreteEditor) Delete(offset, length uint) Editor {
var currentStart, charsToDelete uint
leftToDelete := length
currentOffset := offset
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
for i, currentPiece := range *ce.state.pieces {
if leftToDelete == 0 || currentOffset < currentStart || currentOffset > currentStart+currentPiece.length {
// nothing to do with this piece, just copy it to the new table
newTable = append(newTable, currentPiece)
} else {
rightPieceEmpty := currentPiece.length <= (currentOffset - currentStart + leftToDelete)
if rightPieceEmpty {
charsToDelete = currentPiece.length - (currentOffset - currentStart)
} else {
charsToDelete = leftToDelete
}
leftPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset,
length: currentOffset - currentStart}
rightPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset + (currentOffset - currentStart) + charsToDelete,
length: currentPiece.length - charsToDelete - (currentOffset - currentStart)}
if leftPiece.length > 0 {
newTable = append(newTable, leftPiece)
}
if !rightPieceEmpty {
newTable = append(newTable, rightPiece)
}
leftToDelete -= charsToDelete
currentOffset += charsToDelete
}
currentStart += currentPiece.length
i++
}
ce.commitTable(&newTable)
return ce
}
func (ce *ConcreteEditor) commitTable(newTable *pieceTable) {
newState := editorState{pieces: newTable}
ce.state.next = &newState
newState.prev = ce.state
ce.state = &newState
}
func (ce ConcreteEditor) Undo() Editor {
if ce.state.prev != nil {
ce.state = ce.state.prev
}
return ce
}
func (ce ConcreteEditor) Redo() Editor {
if ce.state.next != nil {
ce.state = ce.state.next
}
return ce
}
func (ce ConcreteEditor) String() string {
var result = ""
for _, piece := range *ce.state.pieces {
var buffer *string
if piece.origin {
buffer = &ce.originBuffer
} else {
buffer = &ce.addBuffer
}
result += (*buffer)[piece.offset:(piece.offset + piece.length)]
}
return result
}
// NewEditor creates an editor instance from a string
func NewEditor(s string) Editor {
pieces := pieceTable{piece{origin: true, offset: 0, length: (uint)(len(s))}}
state := editorState{pieces: &pieces}
return ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
}

Александър обнови решението на 07.11.2018 13:58 (преди 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 pieceTable []piece
type editorState struct {
pieces *pieceTable
prev *editorState
next *editorState
}
// ConcreteEditor is an implementation of the Editor interface
type ConcreteEditor struct {
originBuffer string
addBuffer string
state *editorState
}
func (ce ConcreteEditor) Insert(position uint, text string) Editor {
var currentPosition uint
- for i := range *ce.state.pieces {
- if currentPosition <= position && position < (currentPosition+(*ce.state.pieces)[i].length) {
+ for i, currentPiece := range *ce.state.pieces {
+ if currentPosition <= position && position < (currentPosition+currentPiece.length) {
ce.commitTable(ce.insertWithinPiece((uint)(i), position-currentPosition, text))
return ce
}
- currentPosition += (*ce.state.pieces)[i].length
- i++
+ currentPosition += currentPiece.length
}
ce.commitTable(ce.insertAtTheEnd(text))
return ce
}
func (ce *ConcreteEditor) insertWithinPiece(pieceNum uint, pieceOffset uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+2)
toSplit := (*ce.state.pieces)[pieceNum]
leftP := piece{
origin: toSplit.origin,
offset: toSplit.offset,
length: pieceOffset}
midP := piece{
origin: false,
offset: (uint)(len(ce.addBuffer)),
length: (uint)(len(text))}
rightP := piece{
origin: toSplit.origin,
offset: toSplit.offset + pieceOffset,
length: toSplit.length - pieceOffset}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
if leftP.length != 0 {
newTable = append(newTable, leftP)
}
newTable = append(newTable, midP, rightP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertAtTheEnd(text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
ce.addBuffer += text
newTable = append(*ce.state.pieces, midP)
return &newTable
}
func (ce ConcreteEditor) Delete(offset, length uint) Editor {
var currentStart, charsToDelete uint
leftToDelete := length
currentOffset := offset
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
- for i, currentPiece := range *ce.state.pieces {
+ for _, currentPiece := range *ce.state.pieces {
if leftToDelete == 0 || currentOffset < currentStart || currentOffset > currentStart+currentPiece.length {
// nothing to do with this piece, just copy it to the new table
newTable = append(newTable, currentPiece)
} else {
rightPieceEmpty := currentPiece.length <= (currentOffset - currentStart + leftToDelete)
if rightPieceEmpty {
charsToDelete = currentPiece.length - (currentOffset - currentStart)
} else {
charsToDelete = leftToDelete
}
leftPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset,
length: currentOffset - currentStart}
rightPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset + (currentOffset - currentStart) + charsToDelete,
length: currentPiece.length - charsToDelete - (currentOffset - currentStart)}
if leftPiece.length > 0 {
newTable = append(newTable, leftPiece)
}
if !rightPieceEmpty {
newTable = append(newTable, rightPiece)
}
leftToDelete -= charsToDelete
currentOffset += charsToDelete
}
currentStart += currentPiece.length
- i++
}
ce.commitTable(&newTable)
return ce
}
func (ce *ConcreteEditor) commitTable(newTable *pieceTable) {
newState := editorState{pieces: newTable}
ce.state.next = &newState
newState.prev = ce.state
ce.state = &newState
}
func (ce ConcreteEditor) Undo() Editor {
if ce.state.prev != nil {
ce.state = ce.state.prev
}
return ce
}
func (ce ConcreteEditor) Redo() Editor {
if ce.state.next != nil {
ce.state = ce.state.next
}
return ce
}
func (ce ConcreteEditor) String() string {
var result = ""
for _, piece := range *ce.state.pieces {
var buffer *string
if piece.origin {
buffer = &ce.originBuffer
} else {
buffer = &ce.addBuffer
}
result += (*buffer)[piece.offset:(piece.offset + piece.length)]
}
return result
}
// NewEditor creates an editor instance from a string
func NewEditor(s string) Editor {
pieces := pieceTable{piece{origin: true, offset: 0, length: (uint)(len(s))}}
state := editorState{pieces: &pieces}
return ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
}

Александър обнови решението на 07.11.2018 14:15 (преди 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 pieceTable []piece
type editorState struct {
pieces *pieceTable
prev *editorState
next *editorState
}
// ConcreteEditor is an implementation of the Editor interface
type ConcreteEditor struct {
originBuffer string
addBuffer string
state *editorState
}
-func (ce ConcreteEditor) Insert(position uint, text string) Editor {
+func (ce *ConcreteEditor) Insert(position uint, text string) Editor {
var currentPosition uint
for i, currentPiece := range *ce.state.pieces {
if currentPosition <= position && position < (currentPosition+currentPiece.length) {
ce.commitTable(ce.insertWithinPiece((uint)(i), position-currentPosition, text))
return ce
}
currentPosition += currentPiece.length
}
ce.commitTable(ce.insertAtTheEnd(text))
return ce
}
func (ce *ConcreteEditor) insertWithinPiece(pieceNum uint, pieceOffset uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+2)
toSplit := (*ce.state.pieces)[pieceNum]
leftP := piece{
origin: toSplit.origin,
offset: toSplit.offset,
length: pieceOffset}
midP := piece{
origin: false,
offset: (uint)(len(ce.addBuffer)),
length: (uint)(len(text))}
rightP := piece{
origin: toSplit.origin,
offset: toSplit.offset + pieceOffset,
length: toSplit.length - pieceOffset}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
if leftP.length != 0 {
newTable = append(newTable, leftP)
}
newTable = append(newTable, midP, rightP)
newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertAtTheEnd(text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
ce.addBuffer += text
newTable = append(*ce.state.pieces, midP)
return &newTable
}
-func (ce ConcreteEditor) Delete(offset, length uint) Editor {
+func (ce *ConcreteEditor) Delete(offset, length uint) Editor {
var currentStart, charsToDelete uint
leftToDelete := length
currentOffset := offset
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
for _, currentPiece := range *ce.state.pieces {
if leftToDelete == 0 || currentOffset < currentStart || currentOffset > currentStart+currentPiece.length {
// nothing to do with this piece, just copy it to the new table
newTable = append(newTable, currentPiece)
} else {
rightPieceEmpty := currentPiece.length <= (currentOffset - currentStart + leftToDelete)
if rightPieceEmpty {
charsToDelete = currentPiece.length - (currentOffset - currentStart)
} else {
charsToDelete = leftToDelete
}
leftPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset,
length: currentOffset - currentStart}
rightPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset + (currentOffset - currentStart) + charsToDelete,
length: currentPiece.length - charsToDelete - (currentOffset - currentStart)}
if leftPiece.length > 0 {
newTable = append(newTable, leftPiece)
}
if !rightPieceEmpty {
newTable = append(newTable, rightPiece)
}
leftToDelete -= charsToDelete
currentOffset += charsToDelete
}
currentStart += currentPiece.length
}
ce.commitTable(&newTable)
return ce
}
func (ce *ConcreteEditor) commitTable(newTable *pieceTable) {
newState := editorState{pieces: newTable}
ce.state.next = &newState
newState.prev = ce.state
ce.state = &newState
}
-func (ce ConcreteEditor) Undo() Editor {
+func (ce *ConcreteEditor) Undo() Editor {
if ce.state.prev != nil {
ce.state = ce.state.prev
}
return ce
}
-func (ce ConcreteEditor) Redo() Editor {
+func (ce *ConcreteEditor) Redo() Editor {
if ce.state.next != nil {
ce.state = ce.state.next
}
return ce
}
-func (ce ConcreteEditor) String() string {
+func (ce *ConcreteEditor) String() string {
var result = ""
for _, piece := range *ce.state.pieces {
var buffer *string
if piece.origin {
buffer = &ce.originBuffer
} else {
buffer = &ce.addBuffer
}
result += (*buffer)[piece.offset:(piece.offset + piece.length)]
}
return result
}
// NewEditor creates an editor instance from a string
func NewEditor(s string) Editor {
pieces := pieceTable{piece{origin: true, offset: 0, length: (uint)(len(s))}}
state := editorState{pieces: &pieces}
- return ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
+ return &ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
}

Александър обнови решението на 07.11.2018 14:23 (преди 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 pieceTable []piece
type editorState struct {
pieces *pieceTable
prev *editorState
next *editorState
}
// ConcreteEditor is an implementation of the Editor interface
type ConcreteEditor struct {
originBuffer string
addBuffer string
state *editorState
}
func (ce *ConcreteEditor) Insert(position uint, text string) Editor {
var currentPosition uint
for i, currentPiece := range *ce.state.pieces {
if currentPosition <= position && position < (currentPosition+currentPiece.length) {
ce.commitTable(ce.insertWithinPiece((uint)(i), position-currentPosition, text))
return ce
}
currentPosition += currentPiece.length
}
ce.commitTable(ce.insertAtTheEnd(text))
return ce
}
func (ce *ConcreteEditor) insertWithinPiece(pieceNum uint, pieceOffset uint, text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+2)
toSplit := (*ce.state.pieces)[pieceNum]
- leftP := piece{
+ leftPiece := piece{
origin: toSplit.origin,
offset: toSplit.offset,
length: pieceOffset}
- midP := piece{
+ midPiece := piece{
origin: false,
offset: (uint)(len(ce.addBuffer)),
length: (uint)(len(text))}
- rightP := piece{
+ rightPiece := piece{
origin: toSplit.origin,
offset: toSplit.offset + pieceOffset,
length: toSplit.length - pieceOffset}
newTable = append(newTable, (*ce.state.pieces)[:pieceNum]...)
- if leftP.length != 0 {
- newTable = append(newTable, leftP)
+ if leftPiece.length != 0 {
+ newTable = append(newTable, leftPiece)
}
- newTable = append(newTable, midP, rightP)
+ newTable = append(newTable, midPiece, rightPiece)
newTable = append(newTable, (*ce.state.pieces)[pieceNum+1:]...)
ce.addBuffer += text
return &newTable
}
func (ce *ConcreteEditor) insertAtTheEnd(text string) *pieceTable {
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
- midP := piece{origin: false, offset: (uint)(len(ce.addBuffer)), length: (uint)(len(text))}
+ midPiece := piece{
+ origin: false,
+ offset: (uint)(len(ce.addBuffer)),
+ length: (uint)(len(text))}
ce.addBuffer += text
- newTable = append(*ce.state.pieces, midP)
+ newTable = append(*ce.state.pieces, midPiece)
return &newTable
}
func (ce *ConcreteEditor) Delete(offset, length uint) Editor {
var currentStart, charsToDelete uint
leftToDelete := length
currentOffset := offset
newTable := make(pieceTable, 0, len(*ce.state.pieces)+1)
for _, currentPiece := range *ce.state.pieces {
if leftToDelete == 0 || currentOffset < currentStart || currentOffset > currentStart+currentPiece.length {
// nothing to do with this piece, just copy it to the new table
newTable = append(newTable, currentPiece)
} else {
rightPieceEmpty := currentPiece.length <= (currentOffset - currentStart + leftToDelete)
if rightPieceEmpty {
charsToDelete = currentPiece.length - (currentOffset - currentStart)
} else {
charsToDelete = leftToDelete
}
leftPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset,
length: currentOffset - currentStart}
rightPiece := piece{
origin: currentPiece.origin,
offset: currentPiece.offset + (currentOffset - currentStart) + charsToDelete,
length: currentPiece.length - charsToDelete - (currentOffset - currentStart)}
if leftPiece.length > 0 {
newTable = append(newTable, leftPiece)
}
if !rightPieceEmpty {
newTable = append(newTable, rightPiece)
}
leftToDelete -= charsToDelete
currentOffset += charsToDelete
}
currentStart += currentPiece.length
}
ce.commitTable(&newTable)
return ce
}
func (ce *ConcreteEditor) commitTable(newTable *pieceTable) {
newState := editorState{pieces: newTable}
ce.state.next = &newState
newState.prev = ce.state
ce.state = &newState
}
func (ce *ConcreteEditor) Undo() Editor {
if ce.state.prev != nil {
ce.state = ce.state.prev
}
return ce
}
func (ce *ConcreteEditor) Redo() Editor {
if ce.state.next != nil {
ce.state = ce.state.next
}
return ce
}
func (ce *ConcreteEditor) String() string {
var result = ""
+
for _, piece := range *ce.state.pieces {
- var buffer *string
+ var currentBuffer *string
if piece.origin {
- buffer = &ce.originBuffer
+ currentBuffer = &ce.originBuffer
} else {
- buffer = &ce.addBuffer
+ currentBuffer = &ce.addBuffer
}
- result += (*buffer)[piece.offset:(piece.offset + piece.length)]
+ result += (*currentBuffer)[piece.offset : piece.offset+piece.length]
}
return result
}
// NewEditor creates an editor instance from a string
func NewEditor(s string) Editor {
- pieces := pieceTable{piece{origin: true, offset: 0, length: (uint)(len(s))}}
+ pieces := pieceTable{
+ piece{
+ origin: true,
+ offset: 0,
+ length: (uint)(len(s))}}
+
state := editorState{pieces: &pieces}
return &ConcreteEditor{originBuffer: s, addBuffer: "", state: &state}
}