Решение на Piece table от Хакан Халил

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

Към профила на Хакан Халил

Резултати

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

Код

package main
import (
"math"
)
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 HistoryItem struct {
typeOfModif uint
offset int
length int
}
type History struct {
changes []HistoryItem
position uint
}
type MyEditor struct {
originBuffer string
addBuffer string
pTable []Piece
changeLog History
}
func NewEditor(str string) MyEditor {
var chLog History
arrOfP := make([]Piece, 1)
arrOfP[0] = Piece{true, 0, len(str)}
var val = MyEditor{str, "", arrOfP, chLog}
return val
}
func (m MyEditor) String() string {
var res string
for i := 0; i < len(m.pTable); i++ {
if m.pTable[i].origin == true {
res += m.originBuffer[m.pTable[i].offset : m.pTable[i].offset+m.pTable[i].length]
} else {
res += m.addBuffer[m.pTable[i].offset : m.pTable[i].offset+m.pTable[i].length]
}
}
return res
}
func (i MyEditor) Insert(position uint, text string) MyEditor {
addPiece := make([]Piece, 1)
addPiece[0] = Piece{false, len(i.addBuffer), len(text)}
indexSaver := len(i.addBuffer)
if position == 0 {
i.pTable = append(addPiece, i.pTable...)
} else if position > 0 && (int(position) < len(i.originBuffer)) { //mid insert
for key, val := range i.pTable {
if int(position) >= val.offset && int(position) <= val.offset+val.length {
newPieces := make([]Piece, 0)
newPieceTable1 := Piece{origin: true, offset: val.offset, length: int(position) - val.offset}
newPieceTable2 := Piece{origin: true, offset: newPieceTable1.offset + newPieceTable1.length,
length: val.length - newPieceTable1.length}
newPieces = append(newPieces, newPieceTable1, addPiece[0], newPieceTable2)
if len(i.pTable) == 1 {
i.pTable = newPieces
} else {
temp := make([]Piece, len(i.pTable[key+1:]))
copy(temp, i.pTable[key+1:])
i.pTable = append(i.pTable[:key], newPieces...)
i.pTable = append(i.pTable, temp...)
}
break
}
}
} else {
i.pTable = append(i.pTable, Piece{false, len(i.addBuffer), len(text)})
}
i.addBuffer += text
temp := make([]HistoryItem, len(i.changeLog.changes[i.changeLog.position:]))
if i.changeLog.position != 0 {
copy(temp, i.changeLog.changes[:i.changeLog.position])
i.changeLog.changes = append(i.changeLog.changes[:i.changeLog.position],
HistoryItem{1, int(indexSaver), len(text)})
i.changeLog.changes = append(i.changeLog.changes, temp...)
} else {
copy(temp, i.changeLog.changes[i.changeLog.position:])
newChLog := make([]HistoryItem, len(temp)+1)
newChLog[0] = HistoryItem{1, int(indexSaver), len(text)}
newChLog = append(newChLog[:1], temp...)
i.changeLog.changes = newChLog
}
i.changeLog.position++
return i
}
func (i MyEditor) Delete(offset, length uint) MyEditor {
if int(offset) > len(i.originBuffer)-1 {
return i
}
if int(length) > len(i.originBuffer) {
length = uint(len(i.originBuffer) - int(offset))
}
for key, val := range i.pTable {
if int(offset) >= val.offset && int(offset) <= int(val.offset+val.length) {
newPieces := make([]Piece, 0)
newPieceTable1 := Piece{origin: true, offset: val.offset,
length: int(math.Abs(float64((int(offset) - int(val.offset)))))}
newPieceTable2 := Piece{origin: true, offset: int(offset + length), length: val.length + val.offset - int(offset+length)}
newPieces = append(newPieces, newPieceTable1, newPieceTable2)
if len(i.pTable) == 1 {
i.pTable = newPieces
} else {
temp := make([]Piece, len(i.pTable[key+1:]))
copy(temp, i.pTable[key+1:])
i.pTable = append(i.pTable[:key], newPieces...)
i.pTable = append(i.pTable, temp...)
}
break
}
}
temp := make([]HistoryItem, len(i.changeLog.changes[i.changeLog.position:]))
if i.changeLog.position != 0 {
copy(temp, i.changeLog.changes[:i.changeLog.position])
i.changeLog.changes = append(i.changeLog.changes[:i.changeLog.position],
HistoryItem{0, int(offset), int(length)})
i.changeLog.changes = append(i.changeLog.changes, temp...)
} else {
copy(temp, i.changeLog.changes[i.changeLog.position:])
newChLog := make([]HistoryItem, len(temp)+1)
newChLog[0] = HistoryItem{0, int(offset), int(length)}
newChLog = append(newChLog[:1], temp...)
i.changeLog.changes = newChLog
}
i.changeLog.position++
return i
}
func (i MyEditor) Undo() MyEditor {
if i.changeLog.position == 0 {
return i
}
sOffset := i.changeLog.changes[i.changeLog.position-1].offset
sLength := i.changeLog.changes[i.changeLog.position-1].length
modType := i.changeLog.changes[i.changeLog.position-1].typeOfModif
if modType == 1 {
for j := 0; j < len(i.pTable); j++ {
if i.pTable[j].origin == false {
if i.pTable[j].offset == sOffset && i.pTable[j].length == sLength {
i.pTable[j].length = 0
}
}
}
} else {
for key, value := range i.pTable {
if value.origin == true {
if key+1 < len(i.pTable) {
if value.length+value.offset == sOffset && i.pTable[key+1].offset == sOffset+sLength {
i.pTable[key].length = i.pTable[key+1].offset - value.offset
break
}
}
}
}
}
i.changeLog.position--
return i
}
func (i MyEditor) Redo() MyEditor {
if int(i.changeLog.position) == len(i.changeLog.changes) {
return i
}
sOffset := i.changeLog.changes[i.changeLog.position].offset
sLength := i.changeLog.changes[i.changeLog.position].length
modType := i.changeLog.changes[i.changeLog.position].typeOfModif
if modType == 1 {
for key, value := range i.pTable {
if value.origin == false {
if value.offset == sOffset {
i.pTable[key].length = sLength
break
}
}
}
} else {
for key, value := range i.pTable {
if value.origin == true {
if key+1 < len(i.pTable) {
if value.length+value.offset == i.pTable[key+1].offset {
i.pTable[key].length = sOffset - value.offset
break
}
}
}
}
}
i.changeLog.position++
return i
}

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

--- FAIL: TestExampleFromReadme (0.00s)
panic: runtime error: slice bounds out of range [recovered]
	panic: runtime error: slice bounds out of range

goroutine 6 [running]:
testing.tRunner.func1(0xc0000b2100)
	/usr/local/go/src/testing/testing.go:792 +0x387
panic(0x513f20, 0x61bff0)
	/usr/local/go/src/runtime/panic.go:513 +0x1b9
_/tmp/d20181107-53-11gbfgz.MyEditor.String(0x53b8c0, 0x14, 0x5392bb, 0x8, 0xc000012090, 0x5, 0x6, 0xc00001a360, 0x3, 0x4, ...)
	/tmp/d20181107-53-11gbfgz/solution.go:50 +0x153
_/tmp/d20181107-53-11gbfgz.TestExampleFromReadme(0xc0000b2100)
	/tmp/d20181107-53-11gbfgz/solution_test.go:15 +0x3e7
testing.tRunner(0xc0000b2100, 0x541a68)
	/usr/local/go/src/testing/testing.go:827 +0xbf
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:878 +0x353
exit status 2
FAIL	_/tmp/d20181107-53-11gbfgz	0.004s
PASS
ok  	_/tmp/d20181107-53-11gbfgz	0.002s
PASS
ok  	_/tmp/d20181107-53-11gbfgz	0.002s
--- FAIL: TestSeveralUndos (0.00s)
panic: runtime error: slice bounds out of range [recovered]
	panic: runtime error: slice bounds out of range

goroutine 6 [running]:
testing.tRunner.func1(0xc0000b0100)
	/usr/local/go/src/testing/testing.go:792 +0x387
panic(0x513f20, 0x61bff0)
	/usr/local/go/src/runtime/panic.go:513 +0x1b9
_/tmp/d20181107-53-11gbfgz.MyEditor.String(0x53b8c0, 0x14, 0x5392bb, 0x8, 0xc000012090, 0x5, 0x6, 0xc00001a420, 0x3, 0x4, ...)
	/tmp/d20181107-53-11gbfgz/solution.go:50 +0x153
_/tmp/d20181107-53-11gbfgz.TestSeveralUndos(0xc0000b0100)
	/tmp/d20181107-53-11gbfgz/solution_test.go:39 +0x2de
testing.tRunner(0xc0000b0100, 0x541a90)
	/usr/local/go/src/testing/testing.go:827 +0xbf
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:878 +0x353
exit status 2
FAIL	_/tmp/d20181107-53-11gbfgz	0.004s
PASS
ok  	_/tmp/d20181107-53-11gbfgz	0.002s
--- FAIL: TestSeveralRedos (0.00s)
panic: runtime error: slice bounds out of range [recovered]
	panic: runtime error: slice bounds out of range

goroutine 6 [running]:
testing.tRunner.func1(0xc0000b0100)
	/usr/local/go/src/testing/testing.go:792 +0x387
panic(0x513f20, 0x61bff0)
	/usr/local/go/src/runtime/panic.go:513 +0x1b9
_/tmp/d20181107-53-11gbfgz.MyEditor.String(0x53b8c0, 0x14, 0x5392bb, 0x8, 0xc000012090, 0x5, 0x6, 0xc00001a420, 0x3, 0x4, ...)
	/tmp/d20181107-53-11gbfgz/solution.go:50 +0x153
_/tmp/d20181107-53-11gbfgz.TestSeveralRedos(0xc0000b0100)
	/tmp/d20181107-53-11gbfgz/solution_test.go:55 +0x3f8
testing.tRunner(0xc0000b0100, 0x541a88)
	/usr/local/go/src/testing/testing.go:827 +0xbf
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:878 +0x353
exit status 2
FAIL	_/tmp/d20181107-53-11gbfgz	0.004s
--- FAIL: TestOpAfterUndoInvalidatesRedo (0.00s)
    solution_test.go:75: Expect: "large span of text"; got "large span of English text"
FAIL
exit status 1
FAIL	_/tmp/d20181107-53-11gbfgz	0.002s
PASS
ok  	_/tmp/d20181107-53-11gbfgz	0.002s

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

Хакан обнови решението на 06.11.2018 17:56 (преди 9 месеца)

+package main
+
+import (
+ "math"
+)
+
+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 HistoryItem struct {
+ typeOfModif uint
+ offset int
+ length int
+}
+type History struct {
+ changes []HistoryItem
+ position uint
+}
+
+type MyEditor struct {
+ originBuffer string
+ addBuffer string
+ pTable []Piece
+ changeLog History
+}
+
+func NewEditor(str string) MyEditor {
+ var chLog History
+ arrOfP := make([]Piece, 1)
+ arrOfP[0] = Piece{true, 0, len(str)}
+ var val = MyEditor{str, "", arrOfP, chLog}
+ return val
+}
+
+func (m MyEditor) String() string {
+ var res string
+ for i := 0; i < len(m.pTable); i++ {
+ if m.pTable[i].origin == true {
+ res += m.originBuffer[m.pTable[i].offset : m.pTable[i].offset+m.pTable[i].length]
+ } else {
+ res += m.addBuffer[m.pTable[i].offset : m.pTable[i].offset+m.pTable[i].length]
+ }
+ }
+ return res
+}
+
+func (i MyEditor) Insert(position uint, text string) MyEditor {
+ addPiece := make([]Piece, 1)
+ addPiece[0] = Piece{false, len(i.addBuffer), len(text)}
+ indexSaver := len(i.addBuffer)
+ if position == 0 {
+ i.pTable = append(addPiece, i.pTable...)
+ } else if position > 0 && (int(position) < len(i.originBuffer)) { //mid insert
+ for key, val := range i.pTable {
+ if int(position) >= val.offset && int(position) <= val.offset+val.length {
+ newPieces := make([]Piece, 0)
+ newPieceTable1 := Piece{origin: true, offset: val.offset, length: int(position) - val.offset}
+ newPieceTable2 := Piece{origin: true, offset: newPieceTable1.offset + newPieceTable1.length,
+ length: val.length - newPieceTable1.length}
+ newPieces = append(newPieces, newPieceTable1, addPiece[0], newPieceTable2)
+ if len(i.pTable) == 1 {
+ i.pTable = newPieces
+ } else {
+ temp := make([]Piece, len(i.pTable[key+1:]))
+ copy(temp, i.pTable[key+1:])
+ i.pTable = append(i.pTable[:key], newPieces...)
+ i.pTable = append(i.pTable, temp...)
+ }
+ break
+ }
+ }
+ } else {
+ i.pTable = append(i.pTable, Piece{false, len(i.addBuffer), len(text)})
+ }
+ i.addBuffer += text
+ temp := make([]HistoryItem, len(i.changeLog.changes[i.changeLog.position:]))
+ if i.changeLog.position != 0 {
+ copy(temp, i.changeLog.changes[:i.changeLog.position])
+ i.changeLog.changes = append(i.changeLog.changes[:i.changeLog.position],
+ HistoryItem{1, int(indexSaver), len(text)})
+ i.changeLog.changes = append(i.changeLog.changes, temp...)
+ } else {
+ copy(temp, i.changeLog.changes[i.changeLog.position:])
+ newChLog := make([]HistoryItem, len(temp)+1)
+ newChLog[0] = HistoryItem{1, int(indexSaver), len(text)}
+ newChLog = append(newChLog[:1], temp...)
+ i.changeLog.changes = newChLog
+ }
+ i.changeLog.position++
+ return i
+}
+
+func (i MyEditor) Delete(offset, length uint) MyEditor {
+ if int(offset) > len(i.originBuffer)-1 {
+ return i
+ }
+ if int(length) > len(i.originBuffer) {
+ length = uint(len(i.originBuffer) - int(offset))
+ }
+ for key, val := range i.pTable {
+ if int(offset) >= val.offset && int(offset) <= int(val.offset+val.length) {
+ newPieces := make([]Piece, 0)
+ newPieceTable1 := Piece{origin: true, offset: val.offset,
+ length: int(math.Abs(float64((int(offset) - int(val.offset)))))}
+ newPieceTable2 := Piece{origin: true, offset: int(offset + length), length: val.length + val.offset - int(offset+length)}
+ newPieces = append(newPieces, newPieceTable1, newPieceTable2)
+ if len(i.pTable) == 1 {
+ i.pTable = newPieces
+ } else {
+ temp := make([]Piece, len(i.pTable[key+1:]))
+ copy(temp, i.pTable[key+1:])
+ i.pTable = append(i.pTable[:key], newPieces...)
+ i.pTable = append(i.pTable, temp...)
+ }
+ break
+ }
+ }
+ temp := make([]HistoryItem, len(i.changeLog.changes[i.changeLog.position:]))
+ if i.changeLog.position != 0 {
+ copy(temp, i.changeLog.changes[:i.changeLog.position])
+ i.changeLog.changes = append(i.changeLog.changes[:i.changeLog.position],
+ HistoryItem{0, int(offset), int(length)})
+ i.changeLog.changes = append(i.changeLog.changes, temp...)
+ } else {
+ copy(temp, i.changeLog.changes[i.changeLog.position:])
+ newChLog := make([]HistoryItem, len(temp)+1)
+ newChLog[0] = HistoryItem{0, int(offset), int(length)}
+ newChLog = append(newChLog[:1], temp...)
+ i.changeLog.changes = newChLog
+ }
+ i.changeLog.position++
+ return i
+}
+
+func (i MyEditor) Undo() MyEditor {
+ if i.changeLog.position == 0 {
+ return i
+ }
+ sOffset := i.changeLog.changes[i.changeLog.position-1].offset
+ sLength := i.changeLog.changes[i.changeLog.position-1].length
+ modType := i.changeLog.changes[i.changeLog.position-1].typeOfModif
+ if modType == 1 {
+ for j := 0; j < len(i.pTable); j++ {
+ if i.pTable[j].origin == false {
+ if i.pTable[j].offset == sOffset && i.pTable[j].length == sLength {
+ i.pTable[j].length = 0
+ }
+ }
+ }
+ } else {
+ for key, value := range i.pTable {
+ if value.origin == true {
+ if key+1 < len(i.pTable) {
+ if value.length+value.offset == sOffset && i.pTable[key+1].offset == sOffset+sLength {
+ i.pTable[key].length = i.pTable[key+1].offset - value.offset
+ break
+ }
+ }
+ }
+ }
+ }
+ i.changeLog.position--
+ return i
+}
+
+func (i MyEditor) Redo() MyEditor {
+ if int(i.changeLog.position) == len(i.changeLog.changes) {
+ return i
+ }
+ sOffset := i.changeLog.changes[i.changeLog.position].offset
+ sLength := i.changeLog.changes[i.changeLog.position].length
+ modType := i.changeLog.changes[i.changeLog.position].typeOfModif
+ if modType == 1 {
+ for key, value := range i.pTable {
+ if value.origin == false {
+ if value.offset == sOffset {
+ i.pTable[key].length = sLength
+ break
+ }
+ }
+ }
+ } else {
+ for key, value := range i.pTable {
+ if value.origin == true {
+ if key+1 < len(i.pTable) {
+ if value.length+value.offset == i.pTable[key+1].offset {
+ i.pTable[key].length = sOffset - value.offset
+ break
+ }
+ }
+ }
+ }
+ }
+ i.changeLog.position++
+ return i
+}