Search code examples
javascriptwhile-loop

Repeating song in a playlist coding test in Javascript


I'm doing practice coding interview tests and can't for the life of me figure out why my solution isn't passing.

I know this is a dupe of this, and that a python version of it is here, but I'm pretty sure my issue is one of javascript internal workings and less of algorithmic design (or maybe not). Either way, I didn't want to hijack that dupe (it was unanswered anyway) as my question is more specific.

The prompt:

A playlist is considered a repeating playlist if any of the songs contain a reference to a previous song in the playlist. Otherwise, the playlist will end with the last song which points to null. Implement a function isRepeatingPlaylist that, returns true if a playlist is repeating or false if it is not. For example, the following code prints "true" as both songs point to each other:

Code starting template:

class Song {
    name;
    nextSong;
    
    constructor(name) {
      this.name = name;
    }
  
    /**
     * @return {boolean} true if the playlist is repeating, false if not.
     */
    isRepeatingPlaylist() {
      // Your code goes here
    }
  }
  
let first = new Song("Hello");
let second = new Song("Eye of the tiger");
  
first.nextSong = second;
second.nextSong = first;
  
console.log(first.isRepeatingPlaylist());

My solution thus far. Expanded with console.log and additional songs to help me figure out what is going on. I've been running it using node in my terminal. It appears that my issue is in the line current = this.nextSong;, it just does not seem to be reassigning to the next object correctly. Thoughts?

class Song {
  name;
  nextSong;
  
  constructor(name) {
    this.name = name;
  }
  
  /**
   * @return {boolean} true if the playlist is repeating, false if not.
   */
  isInRepeatingPlaylist() {
    // Your code goes here
    let playlist = [];
    let current = this;
    while (current.name && current.nextSong) {
      console.log('playlist:', playlist);
      if (playlist.includes(current.name)) {
        console.log('in playlist')
        return true;
      } else {
        console.log('not in playlist')
        playlist.push(current.name)
        console.log('added:', current.name)
        console.log('next up:', current.nextSong)
        current = this.nextSong;
        console.log('next up assigned?:', current)
      }
    }
    return false;
  }
}

let first = new Song("Hello");
let second = new Song("Eye of the tiger");
let third = new Song("Third");
let fourth = new Song("Fourth");

first.nextSong = second;
second.nextSong = third;
third.nextSong = fourth; //not a repeating playlist, should return false
// fourth.nextSong = first;

console.log(first.isInRepeatingPlaylist());
// true

and my output:

playlist: []
not in playlist
added: Hello
next up: Song {
  name: 'Eye of the tiger',
  nextSong: Song {
    name: 'Third',
    nextSong: Song { name: 'Fourth', nextSong: undefined }
  }
}
next up assigned?: Song {
  name: 'Eye of the tiger',
  nextSong: Song {
    name: 'Third',
    nextSong: Song { name: 'Fourth', nextSong: undefined }
  }
}
playlist: [ 'Hello' ]
not in playlist
added: Eye of the tiger
next up: Song {
  name: 'Third',
  nextSong: Song { name: 'Fourth', nextSong: undefined }
}
next up assigned?: Song {
  name: 'Eye of the tiger',
  nextSong: Song {
    name: 'Third',
    nextSong: Song { name: 'Fourth', nextSong: undefined }
  }
}
playlist: [ 'Hello', 'Eye of the tiger' ]
in playlist
true

Solution

  • current = this.nextSong; keeps pointing to the same old song. Also, you can and should compare the objects directly instead of their name property.

    class Song {
      name;
      nextSong;
    
      constructor(name) {
        this.name = name;
      }
    
      /**
       * @return {boolean} true if the playlist is repeating, false if not.
       */
      isInRepeatingPlaylist() {
        // Your code goes here
        let playlist = [];
        let current = this;
        while (current && current.nextSong) {
          if (playlist.includes(current)) {
            return true;
          }
          playlist.push(current)
          
          // this was your error:
          current = current.nextSong;
        }
        return false;
      }
    }
    
    let first = new Song("Hello");
    let second = new Song("Eye of the tiger");
    let third = new Song("Third");
    let fourth = new Song("Fourth");
    
    first.nextSong = second;
    second.nextSong = third;
    third.nextSong = fourth; //not a repeating playlist, should return false
    // fourth.nextSong = first;
    
    console.log(first.isInRepeatingPlaylist());
    // true