AlgoMaster Logo
AlgoMasterDesign Playlist Iteratoreasy

Design Playlist Iterator

easy

A playlist can be explored in two directions. One listener may move from the first song to the last while another moves backwards from the final song, and neither walk should disturb the playlist—or the other listener's place.

The Playlist class is already implemented for you. Your task is to implement only the Iterator pattern participants:

  • SongCursor, the common cursor contract with hasNext() and next().
  • ForwardCursor, which starts at index 0 and moves toward the end.
  • ReverseCursor, which starts at the final index and moves toward the beginning.

Both concrete cursors receive the playlist's song collection when they are created. Each cursor must keep its own index. Return "END" from next() once that cursor is exhausted; do not modify or reverse the underlying collection.

The pre-implemented Playlist exposes the following API to the tests:

  • Playlist() creates a playlist holding no songs and no cursors.
  • boolean addSong(String title) appends a song and returns true, or returns false once 20 songs are stored.
  • int songCount() returns how many songs are stored.
  • int openForward() opens a cursor that reads first to last and returns its id. Ids start at 1 and count up across both kinds of cursor.
  • int openReverse() opens a cursor that reads last to first and returns its id.
  • boolean hasNext(int cursorId) returns whether that cursor has a song left. An id that was never handed out returns false.
  • String next(int cursorId) returns that cursor's next song and moves it along. A cursor with nothing left returns "END". An id that was never handed out returns "NONE".
  • int cursorCount() returns how many cursors have been opened.

All songs are added before any cursor is opened. Playlist creates the appropriate cursor and delegates hasNext and next to it. Unknown cursor ids are handled by the provided code, so stay focused on the iterator contract, traversal direction, and per-cursor state.

Example 1:

Input:

Output:

Explanation: The reverse cursor starts at the last song and works back to the first. Once all three have come back, hasNext is false and next reports the sentinel.

Example 2:

Input:

Output:

Explanation: Two cursors read the same three songs alternately. The forward one moves first to last while the reverse one moves last to first, and neither disturbs the other.

Constraints

  • 1 <= title.length <= 40
  • At most 20 songs are stored in one playlist.
  • At most 10 cursors are opened on one playlist.
  • -100 <= cursorId <= 100
  • At most 100 calls in total are made across all methods.

How the design is graded

needs 7/10 to pass
  • Iterator separation

    Full marks when each way of walking the songs is its own class behind one contract, and the playlist answers `hasNext` and `next` by delegating to a cursor it looks up by id. Lose points heavily when the position is a field on `Playlist`, or when `next` branches on which direction the caller asked for.

  • Cursors are independent

    Full marks when two cursors over the same playlist keep separate positions, so advancing one leaves the other exactly where it was, and a cursor opened later starts from its own end of the list. Lose points when opening a second cursor resets the first, or when both cursors share one index.

  • Structure and naming

    Full marks when the reverse walk returns the first song before it finishes, an exhausted cursor returns `END` instead of failing, an id that was never handed out returns `NONE` and `false`, and reading leaves the stored order untouched. Lose points for printing to stdout.

Passing every test is not enough on its own. A submission is accepted only when the design also clears the bar.

Hints

Loading...
CallReturns
new Playlist()null
addSong("Shape of You")true
addSong("Bohemian Rhapsody")true
addSong("Blinding Lights")true
songCount()3
openReverse()1
next(1)"Blinding Lights"
next(1)"Bohemian Rhapsody"
next(1)"Shape of You"
hasNext(1)false
next(1)"END"

The reverse cursor starts at the last song and works back to the first. Once all three have come back, `hasNext` is false and `next` reports the sentinel.

Run checks these cases. Submit also runs a larger hidden set.