Problem · Design

Song Play Analytics

Learn this problem
MediumRipplingONSITE INTERVIEW

Problem statement

Implement a small music analytics service. It stores songs, records users listening to songs, ranks songs by unique listeners, and tracks each user's recently played unique songs.

Operations

Process operations in order and return one row for each operation that produces output.

  • ["ADD_SONG", songName]: Add a song and return its positive integer ID as a one-element row. IDs start at 1 and increase by 1.
  • ["PLAY", songId, userId]: Record that the user played the song. This operation produces no output.
  • ["ANALYTICS"]: Return one row containing every song formatted as songName(uniqueListeners). Sort by unique-listener count descending, then song name lexicographically ascending.
  • ["RECENT", userId, k]: Return up to k distinct song names most recently played by that user, newest first.

Repeated plays by the same user count once toward a song's unique-listener total. For RECENT, replaying a song moves it to the front rather than creating a duplicate.

Interviewer follow-ups

The base exercise adds songs, records plays, and prints analytics by unique listeners. Interviewers then ask candidates to return the last three, or more generally the last k, unique songs played by one user while preserving recency.

Function

runSongAnalytics(operations: String[][]) → String[][]

Examples

Example 1

operations = [["ADD_SONG","Song A"],["ADD_SONG","Song B"],["ADD_SONG","Song C"],["PLAY","1","u1"],["PLAY","1","u2"],["PLAY","2","u1"],["PLAY","2","u1"],["ANALYTICS"],["RECENT","u1","3"]]return = [["1"],["2"],["3"],["Song A(2)","Song B(1)","Song C(0)"],["Song B","Song A"]]

Song A has two unique listeners. User u1's repeated Song B play moves Song B to the front but does not duplicate it.

Constraints

  • Song names are unique.
  • Every PLAY references an existing song ID.
  • 1 <= k <= 100000

More Rippling problems

drafts saved locally
public String[][] runSongAnalytics(String[][] operations) {
  // write your code here
}
operations[["ADD_SONG","Song A"],["ADD_SONG","Song B"],["ADD_SONG","Song C"],["PLAY","1","u1"],["PLAY","1","u2"],["PLAY","2","u1"],["PLAY","2","u1"],["ANALYTICS"],["RECENT","u1","3"]]
expected[["1", "2", "3", "Song A(2)", "Song B(1)", "Song C(0)", "Song B", "Song A"]]
checking account