Skip to content

Instantly share code, notes, and snippets.

@curioussavage
Created November 16, 2022 20:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save curioussavage/4b700f21f29c5840c096fafe5ee11423 to your computer and use it in GitHub Desktop.
Save curioussavage/4b700f21f29c5840c096fafe5ee11423 to your computer and use it in GitHub Desktop.
Adam_w editory exercise
from enum import Enum
class ActionType(Enum):
ADD = 1
EDIT = 2
DEL = 3
class Action:
def __init__(self, t, data=""):
self.t = t
self.data = data
class Editor:
def __init__(self) -> None:
self.actions = []
self.undo_history = []
def dump(self) -> str:
"""
dump renders the full text based on the previous actions.
"""
state = []
for action in self.actions:
if action.t == ActionType.ADD:
state.append(action.data)
elif action.t == ActionType.EDIT:
if len(state) == 0:
continue
state[-1] = action.data
elif action.t == ActionType.DEL:
if len(state) == 0:
continue
state.pop()
# elif action.t == ActionType.REDO:
res = ""
for s in state:
res += s
return res
def add(self, s: str) -> None:
"""
Appends s to current text.
Examples:
- Current text is 'foo'. if add('bar') is called, then dump() should return 'foobar'
"""
self.actions.append(Action(ActionType.ADD, s))
def edit(self, s: str) -> None:
"""
Edits the last 's' that was added and replaces it with the given 's'.
Examples:
- add('foo') and add('bars') -> 'foobars'. if edit('xyz') is called,
then dump() should return 'fooxyz' ('bars' with 'xyz'). If edit('abcd') is called,
then dump() would now return 'fooabcd'
"""
if len(self.actions) > 0:
self.actions.append(Action(ActionType.EDIT, s))
def delete(self) -> None:
"""
Deletes the last 's' that was added or edited.
Examples:
- Current text is 'foobar' after add('foo') and add('bar'). if delete() is called,
then dump() should return 'foo'
"""
self.actions.append(Action(ActionType.DEL))
def undo(self) -> None:
"""
undoes the last action.
For example, if the last action was a deletion, then it will remove the deletion.
If the last action was an edit, then it restores the previous state for the last added string.
If the last action as an add, then it removes the last string added.
Examples:
- Current text is 'foobar' after add('foo') and add('bar'). if undo() is called,
then dump() should return 'foo'
- Current text is 'bar' after add('foo') and edit('bar'). if undo() is called,
then dump() should return 'foo'
- Current text is 'foo' after add('foo'), add('bar'), delete(). if undo() is called,
then dump() should return 'foobar'
"""
if len(self.actions) > 0:
self.undo_history.append(self.actions.pop())
def redo(self) -> None:
"""
redoes the last action
"""
if len(self.undo_history) > 0:
self.actions.append(self.undo_history.pop())
if __name__ == "__main__":
# run tests
e = Editor()
e.add("hello")
e.add(" world")
assert e.dump() == "hello world"
e.edit(" adam")
assert e.dump() == "hello adam"
e.delete()
assert e.dump() == "hello"
e.undo()
assert e.dump() == "hello adam"
# assert True == False
editor = Editor()
editor.delete()
assert(editor.dump() == '')
editor.add('foo')
editor.add('bar')
assert(editor.dump() == 'foobar')
editor.edit('cocoon')
assert(editor.dump() == 'foococoon')
editor.delete()
assert(editor.dump() == 'foo')
editor.undo()
assert(editor.dump() == 'foococoon')
editor.undo()
assert(editor.dump() == 'foobar')
editor.undo()
assert(editor.dump() == 'foo')
editor.add('christmas')
editor.undo()
assert(editor.dump() == 'foo')
editor.undo()
assert(editor.dump() == '')
editor.undo()
editor.undo()
assert(editor.dump() == '')
editor.edit('bar')
assert(editor.dump() == '')
editor.add('christmas')
assert(editor.dump() == 'christmas')
editor = Editor()
editor.add("one")
editor.undo()
assert(editor.dump() == '')
editor.redo()
assert(editor.dump() == 'one')
editor.undo()
assert(editor.dump() == '')
editor.undo()
editor.redo()
editor.redo()
assert(editor.dump() == 'one')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment