4

Recently I answered My Online Interview test Wherein I was asked Following question

A TrainComposition is built by attaching and detaching wagons from the left and the right sides.

For example, if we start by attaching wagon 7 from the left followed by attaching wagon 13, again from the left, we get a composition of two wagons (13 and 7 from left to right). Now the first wagon that can be detached from the right is 7 and the first that can be detached from the left is 13. Implement a TrainComposition that models this problem.

I used doubly linked list to solve the issue

class Node

{
    protected int data;
    protected Node next, prev;
    /* Constructor */
    public Node()
    {
        next = null;
        prev = null;
        data = 0;
    }

    /* Constructor */

    public Node(int d, Node n, Node p)
    {
        data = d;
        next = n;
        prev = p;
    }

    /* Function to set link to next node */
    public void setLinkNext(Node n) {
        next = n;
    }
    /* Function to set link to previous node */
    public void setLinkPrev(Node p) {
        prev = p;
    }

    /* Funtion to get link to next node */

    public Node getLinkNext() {
        return next;
    }

    /* Function to get link to previous node */

    public Node getLinkPrev() {
        return prev;
    }

    /* Function to set data to node */
    public void setData(int d) {
        data = d;
    }

    /* Function to get data from node */

    public int getData() {
        return data;
    }
}

public class SortedSearch {
    protected Node start;
    protected Node end;
    public int size;
    /* Constructor */
    public SortedSearch()
    {
        start = null;
        end = null;
        size = 0;
    }
    public boolean isEmpty()
    {
        return start == null;
    }

    public int getSize()
    {
        return size;
    }

    public void attachWagonFromLeft(int wagonId) {
        Node nptr = new Node(wagonId, null, null);
        if (start == null)
        {
            start = nptr;
            end = start;
        }
        else
        {
            start.setLinkPrev(nptr);
            nptr.setLinkNext(start);
            start = nptr;
        }
        size++;
    }
    public void attachWagonFromRight(int wagonId) {
        Node nptr = new Node(wagonId, null, null);
        if (start == null)
        {
            start = nptr;
            end = start;
        }
        else
        {
            nptr.setLinkPrev(end);
            end.setLinkNext(nptr);
            end = nptr;
        }
        size++;
    }
    public int detachWagonFromLeft() {
        int value=0;
        if (size == 1)
        {
            value = start.getData();
            start = null;
            end = null;
            size = 0;
            return value;

        }
        value = start.getData();
        start = start.getLinkNext();
        start.setLinkPrev(null);
        size--;
        return value;
    }

    public int detachWagonFromRight() {
        int value=0;
            value = end.getData();
            end = end.getLinkPrev();
            end.setLinkNext(null);
            size-- ;
            return value;
    }

    public static void main(String[] args) {
        SortedSearch tree = new SortedSearch();
        tree.attachWagonFromLeft(7);
        tree.attachWagonFromLeft(13);
        tree.attachWagonFromLeft(12);
        tree.attachWagonFromLeft(10);
        tree.attachWagonFromLeft(6);
        tree.attachWagonFromLeft(4);
        tree.attachWagonFromLeft(3);
        tree.attachWagonFromLeft(2);
        System.out.println(tree.detachWagonFromRight()); // 7
        System.out.println(tree.detachWagonFromRight()); // 13
        System.out.println(tree.detachWagonFromRight()); // 7
        System.out.println(tree.detachWagonFromRight()); // 13
        System.out.println(tree.detachWagonFromRight()); // 7
        System.out.println(tree.detachWagonFromRight()); // 13

    }
}

And tested it accordingly. But when submitted it said failed internal test cases, and the answer was marked wrong. Can you please tell which is the best solution for this problem.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
Suyash
  • 331
  • 1
  • 4
  • 20
  • 1
    I think you should look into using a Deque https://docs.oracle.com/javase/7/docs/api/java/util/Deque.html. Basically it is a stack that can be pushed/popped from both sides, and therefore looks like it could be perfect for this problem. – mdewit Mar 31 '17 at 07:55

5 Answers5

5

Why not just use this simple implementation?

private static class TrainComposition {

  private final Deque<Integer> wagons = new LinkedList<>();

  public void attachLeft(int wagonNumber) {
    wagons.addFirst(wagonNumber);
  }

  public void attachRight(int wagonNumber) {
    wagons.addLast(wagonNumber);
  }

  public void detachLeft() {
    if (!wagons.isEmpty()) {
      wagons.removeFirst(); // Alternative if exception should not be bubbled up: wagons.pollFirst()
    } else {
      throw new IndexOutOfBoundsException("No wagons available");
    }
  }

  public void detachRight() {
    if (!wagons.isEmpty()) {
      wagons.removeLast(); // Alternative if exception should not be bubbled up: wagons.pollLast()
    } else {
      throw new IndexOutOfBoundsException("No wagons available");
    }
  }
}
JDC
  • 4,247
  • 5
  • 31
  • 74
  • 1
    just fyi, you need to check the `wagons` first before attempting to use `.removeFirst()` or `.removeLast()` or you will get an exception if the `wagons` is empty. A better approach is to use eg [`pollFirst()`](https://docs.oracle.com/javase/7/docs/api/java/util/Deque.html#pollFirst()) – KarelG Mar 31 '17 at 08:09
  • This is true of course, but exception handling was not mentioned inside the question, I just wanted to show the basic approach. Of course you could wrap this using an emptiness check or something and handle the case accordingly by throwing an exception. As you correctly state, pollFirst() would be an option of handling empty queue :) – JDC Mar 31 '17 at 08:12
  • *but exception handling was not mentioned inside the question* seems a poor excuse. Sorry :) There are online programming tests for solicitation which are evaluated manually by the recruiter too. That person would think that you won't care about the exception problems. Always write your code as if it's production-ready. But gave a vote since this is how I would implement anyways... – KarelG Mar 31 '17 at 08:16
3

It seems that the detachWagonFromRight lacks the check that detachWagonFromLeft has:

public int detachWagonFromLeft() {
    int value=0;
    if (size == 1)
    {
        value = start.getData();
        start = null;
        end = null;
        size = 0;
        return value;

    }
    value = start.getData();
    start = start.getLinkNext();
    start.setLinkPrev(null);
    size--;
    return value;
}

public int detachWagonFromRight() {
    int value=0;
        value = end.getData();
        end = end.getLinkPrev();
        end.setLinkNext(null);
        size-- ;
        return value;
}

So the case when you are removing the last wagon from the right side, start still points to it

Pablo Lozano
  • 10,122
  • 2
  • 38
  • 59
  • yes you are right!! but is this a good solution or should have used dequeue? – Suyash Mar 31 '17 at 09:08
  • Well, I don't know the requiremens or constraints you have: In real life I wouldn't reinvent the wheel, but you can find tests or exams where you are not allowed to use java collections because the examiner wants to see how you can implement something from scratch – Pablo Lozano Mar 31 '17 at 10:55
0

Looks a bit "long", your solution. I would define an object, called "train" which has a object.value=number_of_wagons (a list). Then define 2 methods:

  • train.attach(site,number): using the append command or the insert command for attaching the new number from the desired side
  • train.detach(site): deleting the element of the list and maybe printing you the number.

However, for my understanding (also the description of the problem is not very detailed, so i dont know what should be the expected answer) you can only attach wagons from one side as the engine is on the other) ;)

Marcus
  • 85
  • 9
  • Offtopic comment: Nowadays there are trains where every wagon is also the engine, in subways comes very handy not needing to turn the train when you arrive to the end of the line – Pablo Lozano Mar 31 '17 at 08:50
-1

I hope you are doing well, because I made the problem, and my solution for C# would be the following:

using System;
using System.Collections.Generic;

public class TrainComposition
{
    public List <int> wagon = new List <int> ();

    public void AttachWagonFromLeft(int wagonId)
    {
        wagon.Add(wagonId);
        //throw new NotImplementedException("Waiting to be implemented.");
    }

    public void AttachWagonFromRight(int wagonId)
    {
        wagon.Insert(0, wagonId);
        //throw new NotImplementedException("Waiting to be implemented.");
    }

    public int DetachWagonFromLeft()
    {
        int elem = 0;
        int indexValue = 0;

        elem = wagon[wagon.Count - 1]; // Get the value of the last element

        indexValue = wagon.LastIndexOf(elem); //Get the index the last value

        wagon.RemoveAt(indexValue);// This will remove the part at index 

        return elem;
        //throw new NotImplementedException("Waiting to be implemented.");
    }

    public int DetachWagonFromRight()
    {
        int elem = 0;

        elem = wagon[0];

        wagon.RemoveAt(0);

        return elem;
        //throw new NotImplementedException("Waiting to be implemented.");
    }

    public static void Main(string[] args)
    {
        TrainComposition tree = new TrainComposition();
        tree.AttachWagonFromLeft(7);
        tree.AttachWagonFromLeft(13);
        Console.WriteLine(tree.DetachWagonFromRight()); // 7 
        Console.WriteLine(tree.DetachWagonFromLeft()); // 13
    }
}
zx485
  • 28,498
  • 28
  • 50
  • 59
  • You are the author and I have seen this question flagged as "linkedlist" but you are not using a linked list implementation at all... – Tallmaris Jan 08 '20 at 11:08
-3
import java.util.*;
public class TrainComposition {
    LinkedList<Integer> wagons = new LinkedList<Integer>();
  public static void main(String[] args) {



    TrainComposition tree = new TrainComposition();
    tree.attachWagonFromLeft(7);
    tree.attachWagonFromLeft(13);
    System.out.println(tree.detachWagonFromRight()); // 7
    System.out.println(tree.detachWagonFromLeft()); // 13
}

public void attachWagonFromLeft(int wagonId) {
    wagons.addFirst(wagonId);
   // throw new UnsupportedOperationException("Waiting to be implemented.");
}

public void attachWagonFromRight(int wagonId) {
    wagons.addLast(wagonId);
   // throw new UnsupportedOperationException("Waiting to be implemented.");
}

public int detachWagonFromLeft() {
    if (!wagons.isEmpty()) {
  return wagons.removeFirst();

   } else {
  throw new IndexOutOfBoundsException("No wagons available");
}
}    
 public int detachWagonFromRight() {
    if (!wagons.isEmpty()) {
  return wagons.removeLast();

   } else {
  throw new IndexOutOfBoundsException("No wagons available");
}

}
Vit
  • 793
  • 4
  • 17