| # | Problem | Pass Rate (passed user / total user) |
|---|---|---|
| 14857 | Simple Todo List |
|
| 14862 | Very useful playlist engine |
|
Description
With the deadline of the final project creeping closer and closer, an I2P student has completely lost track of what he needs to do. Help him build a simple todo list to keep track of the tasks he needs to complete for this class. ( ̄^ ̄ )ゞ

What You Must Implement
Implement the following:
PendingTaskIterator.__init__- Build and store the list of pending tasks (in insertion order).
- The iterator should snapshot the pending tasks at creation time: later
ADDorDONEoperations on theTaskQueuemust not affect an already-createdPendingTaskIterator.
PendingTaskIterator.__next__- Return the next pending task from this list and advance the internal index.
- The iterator must yield the same task dictionaries (the same dict objects) that are stored in the underlying
TaskQueue. - Raise
StopIterationwhen there are no more pending tasks.
TaskQueue.add_task- Append a new task dict with
"name"and"done": Falseto the underlying list.
- Append a new task dict with
TaskQueue.mark_done- mark the earliest added task whose
"name"equals name and whose"done"isFalse, and set that task’s"done"toTrue. If there is no pending task with that name, do nothing.
- mark the earliest added task whose
TaskQueue.__iter__- Return a
PendingTaskIteratorinstance for thisTaskQueueinstead of the default list iterator.
- Return a
Code Template
class PendingTaskIterator:
def __init__(self, task_queue):
self.pending = []
self.index = 0
# TODO: fill self.pending with the pending tasks in the correct order
def __next__(self):
# TODO:
raise NotImplementedError
class TaskQueue(list):
def add_task(self, name):
# TODO:
# Append a new task dict to the list.
raise NotImplementedError
def mark_done(self, name):
# TODO:
# Traverse the underlying list in insertion order
raise NotImplementedError
def __iter__(self):
# TODO:
# Return a PendingTaskIterator for this TaskQueue
raise NotImplementedError
""" Do not change the code below """
q = int(input())
tq = TaskQueue()
for _ in range(q):
op = input().split()
if op[0] == "ADD":
name = " ".join(op[1:])
tq.add_task(name)
elif op[0] == "DONE":
name = " ".join(op[1:])
tq.mark_done(name)
elif op[0] == "LEN":
print(len(tq))
elif op[0] == "PRINTALL":
print(tq)
elif op[0] == "PENDING":
k = int(op[1])
it = iter(tq)
for _ in range(k):
print(next(it))
Test cases:
- Test cases 1-3: Basic tests (ADD, LEN, PRINTALL)
- Test cases 4-6: Tests using __iter__ (PENDING command)
- Test cases 7-10: All commands (ADD, DONE, LEN, PRINTALL, PENDING)
Input
- The first line contains an integer
q: the number of operations. - Each of the next
qlines is one of:- ADD name
Append a new task with the given name to the queue. - DONE name
Mark one task with the given name as done. If no such task exists, do nothing.
Hint: Do not iterate withfor task in self:here, because that will use the overridden iterator. - LEN
Print the total number of tasks stored in the queue (done + not done). - PRINTALL
Print the internal list of tasks directly (using the default string representation).
This prints all tasks (done + not done) in insertion order. - PENDING k
Use the iterator protocol to iterate over pending tasks only and print the firstkof them.
- ADD name
Constraints:
-
1 ≤
q≤ 1000 -
0 ≤
k≤ current_number_of_pending_tasks
Output
For each following operation, output the corresponding text:
- LEN: Print the total number of tasks
- PRINTALL: Print the the internal list of tasks using default string representation.
- PENDING k: Print the first
kpending tasks.
Sample Input Download
Sample Output Download
Tags
Discuss
Description
After a long, messy legal battle between NewJeans and ADOR, the group has finally agreed to rejoin the label. For fans, this is a double-edged sword: some see it as a strategic win, while others see it as a corporate compromise. But one KPI remains rock solid—the music still hits. d[^-^]b
Your mission: build a smart playlist system that helps fans consume NewJeans’ discography more efficiently and enjoyably.

You will implement a small playlist system using:
- an abstract base class
BasePlaylist - two subclasses:
SequentialPlaylistandReversePlaylist - custom
__iter__ - operator overloading
__add__
Each playlist stores track names (strings without spaces) in a list self._tracks in insertion order.
What You Must Implement
Implement the following:
BasePlaylist (abstract)
BasePlaylist must:
-
inherit from
ABC -
__init__(self): initialize -
add(self, track_name): appendtrack_nametoself._tracks -
__len__(self): return number of tracks -
__repr__(self): return"label_name: [...]", where[...]is the list of track names -
__add__(self, other):- create a new
SequentialPlaylist - its
_tracksisself._tracks + other._tracks
- create a new
SequentialPlaylist(BasePlaylist)
__iter__(self): iterate in insertion order, e.g.return iter(self._tracks)
ReversePlaylist(BasePlaylist)
__iter__(self): iterate in reverse insertion order, e.g.return reversed(self._tracks)
Code Template
from abc import ABC, abstractmethod
class BasePlaylist(ABC):
def __init__(self):
# TODO: store the label name and initialize an empty list to store tracks
raise NotImplementedError
def add(self, track_name):
# TODO: append track_name (string) to self._tracks
raise NotImplementedError
def __len__(self):
# TODO: return number of tracks
raise NotImplementedError
def __repr__(self):
# TODO:
raise NotImplementedError
def __add__(self, other):
# TODO:
raise NotImplementedError
@abstractmethod
def __iter__(self):
pass
class SequentialPlaylist(BasePlaylist):
def __iter__(self):
# TODO: iterator in insertion order
raise NotImplementedError
class ReversePlaylist(BasePlaylist):
def __iter__(self):
# TODO: iterator in reverse insertion order
raise NotImplementedError
""" Do not change the code below """
q = int(input())
playlists = {} # label (str) -> BasePlaylist instance
for _ in range(q):
op = input().split()
if op[0] == "NEW_SEQ":
label = op[1]
playlist = SequentialPlaylist()
playlist._label = label
playlists[label] = playlist
elif op[0] == "NEW_REV":
label = op[1]
playlist = ReversePlaylist()
playlist._label = label
playlists[label] = playlist
elif op[0] == "ADD":
label = op[1]
track_name = op[2]
playlists[label].add(track_name)
elif op[0] == "LEN":
label = op[1]
print(len(playlists[label]))
elif op[0] == "PLAY":
label = op[1]
k = int(op[2])
it = iter(playlists[label])
played = []
for _ in range(k):
played.append(next(it))
print(" -> ".join(played))
elif op[0] == "MERGE":
new_label = op[1]
l1 = op[2]
l2 = op[3]
merged = playlists[l1] + playlists[l2]
merged._label = new_label
playlists[new_label] = merged
elif op[0] == "PRINT":
label = op[1]
print(playlists[label])
Test cases:
- Test cases 1-3: Basic tests (NEW_SEQ/NEW_REV, ADD, LEN, PRINT)
- Test cases 4-6: Tests using __iter__ (PLAY command)
- Test cases 7-10: All commands (NEW_SEQ, NEW_REV, ADD, LEN, PLAY, MERGE, PRINT)
Input
- The first line contains an integer
q: the number of operations. - Each of the next
qlines is one of:-
NEW_SEQ label
Create emptySequentialPlaylistunderlabel. -
NEW_REV label
Create emptyReversePlaylistunderlabel. -
ADD label track_name
Addtrack_nameto playlistlabel. -
LEN label
Print the number of tracks. -
PLAY label k
- Print all the tracks in label (by calling
next(it)) joined by->, e.g.
a -> b -> c
- Print all the tracks in label (by calling
-
MERGE new_label label1 label2
- Compute
playlists[new_label] = playlists[label1] + playlists[label2]
- Compute
-
PRINT label
- Print all tracks in
label(uses your__repr__)
- Print all tracks in
-
Constraints:
-
1 ≤
q≤ 1000 -
0 ≤
k≤ len_of_playlist
Output
For each following operation, output the corresponding text:
-
LEN label: Print the number of tracks.
-
PLAY label k: Print all the tracks in label (by calling
next(it)) joined by->, e.g.a -> b -> c -
PRINT label: Print all tracks in
label("label_name: [...]", where[...]is the list of track names)