skip to Main Content

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

2

Answers


  1. 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
    Login or Signup to reply.
  2. A playlist is considered a repeating playlist if any of the songs contain a reference to a previous song in the playlist

    • A playlist containing two songs with the same name is not considered a repeating playlist, so using name is a bad idea.
    • You seems to be mistaken a while loop with a recursive version because this in current = this.nextSong is referred to first every loop.
    • This has to be a set problem, I’m using weakset to store the song reference.
    class Song {
      name;
      nextSong;
    
      constructor(name) {
        this.name = name;
      }
    
      /**
       * @return {boolean} true if the playlist is repeating, false if not.
       */
      isRepeatingPlaylist() {
        const playedSongs = new WeakSet();
        playedSongs.add(this);
        let nextSong = this.nextSong;
        while (nextSong) {
          if (playedSongs.has(nextSong)) return false;
          playedSongs.add(nextSong);
          nextSong = nextSong.nextSong;
        }
        return true;
      }
    }
    
    let first = new Song('Hello');
    let second = new Song('Eye of the tiger');
    
    first.nextSong = second;
    second.nextSong = first;
    
    console.log(first.isRepeatingPlaylist());
    

    Working sample: https://stackblitz.com/edit/vitejs-vite-vmyf8u?file=main.js&terminal=dev

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search