FastPrepMajority Labels over Audio Intervals

Majority Labels over Audio Intervals

Nooks logoNooks● MediumFULLTIMEPHONE SCREEN

Problem statement

A call recording is 100 seconds long. Each of N labelers marks the whole recording as a list of time segments. Every segment has one of three labels: human, machine, or silence.

labelers[i] holds the segments of labeler i in time order, written as groups of three strings: start, end, label. For example, ["0.0", "10.5", "human", "10.5", "100.0", "silence"] labels 0.0 to 10.5 as human and 10.5 to 100.0 as silence. Each labeler's first segment starts at "0.0", each later segment starts where the previous one ends, and the last segment ends at "100.0".

A label has consensus on a stretch of time when more than N / 2 labelers give it that label. Combine the labelers: cut the recording at every segment boundary, give each piece its consensus label, and merge neighboring pieces that have the same label. Return the combined segments as rows [start, end, label] in time order, using the same time strings as the input.

If any piece of the recording has no consensus label, combining fails with an error. In that case, return an empty list.

Function

majorityAudioIntervals(labelers: String[][]) → List<List<String>>

Examples

Example 1

labelers = [["0.0","10.5","human","10.5","20.0","machine","20.0","100.0","silence"],["0.0","9.0","human","9.0","20.0","silence","20.0","100.0","human"],["0.0","20.0","silence","20.0","100.0","human"]]return = [["0.0","9.0","human"],["9.0","20.0","silence"],["20.0","100.0","human"]]

There are 3 labelers, so a label needs at least 2 votes. The boundaries are 9.0, 10.5, and 20.0.

  • 0.0 to 9.0: human, human, silence, so human wins.
  • 9.0 to 10.5: human, silence, silence, so silence wins.
  • 10.5 to 20.0: machine, silence, silence, so silence wins.
  • 20.0 to 100.0: silence, human, human, so human wins.

The two silence pieces touch, so they merge into 9.0 to 20.0.

Example 2

labelers = [["0.0","50.0","human","50.0","100.0","machine"],["0.0","100.0","human"]]return = []

There are 2 labelers, so a label needs both votes. From 0.0 to 50.0 both say human. From 50.0 to 100.0 one says machine and one says human, so no label has more than 1 vote. That piece has no consensus, so the answer is an empty list.

Example 3

labelers = [["0.0","40.0","machine","40.0","100.0","human"],["0.0","40.0","machine","40.0","100.0","human"],["0.0","50.0","machine","50.0","100.0","human"],["0.0","20.0","silence","20.0","100.0","human"]]return = [["0.0","40.0","machine"],["40.0","100.0","human"]]

There are 4 labelers, so a label needs at least 3 votes.

  • 0.0 to 20.0: machine, machine, machine, silence, so machine wins.
  • 20.0 to 40.0: machine, machine, machine, human, so machine wins.
  • 40.0 to 50.0: human, human, machine, human, so human wins.
  • 50.0 to 100.0: all four say human.

Merging equal neighbors gives machine from 0.0 to 40.0 and human from 40.0 to 100.0. The boundary at 20.0 disappears.

Constraints

  • 1 <= N = labelers.length <= 50
  • 3 <= labelers[i].length <= 600, and labelers[i].length is a multiple of 3.
  • Every time is a decimal string with exactly one digit after the point, from "0.0" to "100.0", with no extra leading zeros (for example "9.0" or "10.5").
  • For each labeler, the segments start at "0.0", end at "100.0", touch without gaps or overlaps, and every segment has start < end.
  • Every label is human, machine, or silence.
See Nooks hiring insights
Saved
public List<List<String>> majorityAudioIntervals(String[][] labelers) {
    // Write your code here
}
Checking account…