Amazon Interview Question for Software Engineer / Developers


Country: United States
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
1
of 1 vote

Elevator
        private int weightApplied
        private int passengerNumber;
        private String elevatorID;
        private int floorNumber
        private int capacity
        private boolean started
        private String direction
        private String state
        private boolean goingUp
        private boolean doorsOpen
        private PriorityQueue pq//PQ that gives priority to different floors based on floorNumber, non-preemptive priority scheduling

        void go_up(int floorNumber);
        void go_down(int floorNumber);
        boolean isStarted(boolean start);
        boolean setStarted(boolean start);
        void load_passengers();
        void unload_passengers();
        etc...
        getters and setters for all instance variables...
    Passenger extends Elevator
        private int destinationFloor;

        int current_destination(int destinationFloor)

There's probably something else I'm missing but I think I have some idea...

- Anonymous February 11, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

My idea is to make Elevator implement Runnable, and constantly check a queue (linkedList). A Controller class will assign which floor to go in the queue. When the queue is empty, the run() method will wait (queue.wait() ), when a floor is assigned to this elevator, it will call queue.notify() to wake up the run() method, and run() method will call goToFloor(queue.pop())

- Guy February 11, 2014 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 votes

Agree to the most part .Only thing is that Passenger cannot extend from Elevator

- ami February 11, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I just figured my approach of having each elevator to have a queue and trying to synchronize and taking timing issue (the time for an elevator to get to a floor) will make this problem very complex. I tried to write it on paper, but dont think it works. It seems like we don't really need to take concurrency or timing issue into account here, but we do need to somehow use a queue to distribute the control. Any suggestion?

- Guy February 11, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

(I'm OP)

Some fixes:
boolean isStarted();
Passenger

Yeah, I guess you could use synchronization for this as well.

- Johnb February 11, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Given your solution doesn't handle synchronization and timing, which I believe is good enough for a 45-min interview, how do you distribute the control? Like how does your system notify the closest or the first available found elevator to go to certain floor, and how do you use the priorityQueue?

- Guy February 11, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I think you can use the priority queue in this way: Let the elevator be at floor 5 going down. If one were on the second floor trying to go up and another on the tenth floor who want to go down, the elevator would choose the second floor first because it has a higher priority in the queue than someone who wants to go up. The processes are not pre-empted because if someone hit the button on the first floor, it would still go to the second floor first, even though the first may have a higher priority. The elevator just adds new processes to the ready queue.

So, you can add a floorNumber with a certain priority whenever the passenger wants to go somewhere.

I don't think the system needs to notify other elevators of anything?

- Johnb February 11, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

I agree mostly about all.
But I think we should have a class call ElevatorSystem that has a Set of Elevators.
ElevatorSystem must be a singleton object where you control each Elevator.

Additional business rules could be:
-> There are a window of time where the elevator are very crowded, so If there are N Elevators and M floors. It could be good to N/2 elevators only server requests for floors from 0 to M/2 and the rest from M/2 + 1 to M
-> If 2 elevators at floor 10 are going down, and there is a request at floor 5th, then one of them will have to attend the request, but not both. which one? Well It may be one that is carries less people perhaps.
-> Each Elevator must contain a priority attribute that can be use to take decisions of requests.

We want to avoid any synchronization issue, so access to Queue<Request> reqs must be synchronized.

We can even make the system distributed and treat each elevator as a Peer, Host or Computer. So we can send messages back and forth.
For example:

Request at floor 5:
->Send broadcast to all Elevators
-> Each elevator that receives the messages, sent back with an reply message with Its state ( location, occupation, weight, etc etc ) And let the System decide which one to call.

We can discuss a lot about this type of questions. I think It is good to share ideas as much as possible.

- .·´¯`·.´¯`·.¸¸.·´¯`·.¸><(((º> February 18, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

*repose with format corrected*

public class Elevator {
	
	public static final int MAX_FLOORS = 50;
	
	// upward floor queue
	private PriorityQueue<Integer> floors_up = new PriorityQueue<Integer>(MAX_FLOORS);
	
	// downward floor queue
	private PriorityQueue<Integer> floors_down = new PriorityQueue<Integer>(MAX_FLOORS, new Comparator<Integer>(){
		public int compare(Integer arg0, Integer arg1) {
			return arg1.compareTo(arg0);
		}
	});
	
	// effective floor queue
	private PriorityQueue<Integer> floors = floors_up;
	
	// current floor
	private int current = 0;

	public void userCallAt(int where) {
		setTarget(where);
	}
	
	public void setTarget(int target) {
		
		// ignore if target is current
		if (target == current) {
			return;
		}
		
		// add target to right queue
		if (floors == floors_up) {
			if (target < current) {
				floors_down.offer(target);
			} else {
				floors_up.offer(target);
			}
		} else {
			if (target > current) {
				floors_up.offer(target);
			} else {
				floors_down.offer(target);
			}
		}
		
		// swap queue to turn around the elevator
		if (floors.isEmpty()) {
			floors = (floors == floors_up ? floors_down : floors_up);
		}
	}
	
	public int getTarget() {
		
		if (!floors.isEmpty()) {
			return floors.peek();
		}
		
		if (floors_up.isEmpty() && floors_down.isEmpty()) {
			return current;
		}
		
		floors = (floors == floors_up ? floors_down : floors_up);
		return floors.peek();
	}
	
	public int getCurrent() {
		return current;
	}
	
	public void step(int target) {
		if (target > current) {
			current++;
		} else {
			current--;
		}
	}
	
	public void stop() {
		floors.poll();
	}
	
	public void move() {
		
		while (getCurrent() != getTarget()) {
			do {
				step(getTarget());
			} while (getCurrent() != getTarget());
			stop();
		}
		
	}
	
}

- Anonymous February 22, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

I think instead of having 2 priority queues, you can just use combination of direction and vector<floor> where floor could be integer/boolean type.
if direction is up, you serve floors in increasing order otherwise decreasing.
Someone requests elevator on floor X, set value at index X in vector to ON
Also, when elevator stops at some floor and people getting in to the elevator request for target floor. People (already)inside an elevator can request floor at any time.
(Also with each floor, we can link # of ppl requested for particular floor at any given time)
As you serve floors, reset it in vector to OFF. If people inside an elevator are linked to a floor, then clear that list now.

I look at it as a producer/consumer problem. So as others mentioned, synchronization is required.

- aks October 14, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

I think we dont need so much variables and methods ... as per my approach

we need
enum Motion
{
Going_Up, Going_Down, Stoped
}

Class Lift
{
int current Floor;
int priorityQueue nextFloorToStop;
int LiftId;
}

Class LiftController
{
array of lifts;
queue Allrequests;

public void CallLift(int floorIndex)
{

}

public void int NearestLift(int floorIndex)
{

}

public void bool IsMovingInSameDirection(int liftId, int FloorIndex)
{

}
}

If No lift is available to take request then add that request in AllRequest queue else add it in lift's queue.
When when lift comes to stop (after completing its all floor stops) then it will notify controller class to
check if there is any request pending in "allRequest Queue".

- Mac February 15, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

2 more improvement need to be done
1. Finding nearest elevator from where request is generated
2. in CallLift(int floorIndex) method we need one more input parameter to provide user's choice of going up or going down.

- Mohit February 15, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

public class Elevator {

public static final int MAX_FLOORS = 50;

// upward floor queue
private PriorityQueue<Integer> floors_up = new PriorityQueue<Integer>(MAX_FLOORS);

// downward floor queue
private PriorityQueue<Integer> floors_down = new PriorityQueue<Integer>(MAX_FLOORS, new Comparator<Integer>(){
public int compare(Integer arg0, Integer arg1) {
return arg1.compareTo(arg0);
}
});

// effective floor queue
private PriorityQueue<Integer> floors = floors_up;

// current floor
private int current = 0;

public void userCallAt(int where) {
setTarget(where);
}

public void setTarget(int target) {

// ignore if target is current
if (target == current) {
return;
}

// add target to right queue
if (floors == floors_up) {
if (target < current) {
floors_down.offer(target);
} else {
floors_up.offer(target);
}
} else {
if (target > current) {
floors_up.offer(target);
} else {
floors_down.offer(target);
}
}

// swap queue to turn around the elevator
if (floors.isEmpty()) {
floors = (floors == floors_up ? floors_down : floors_up);
}
}

public int getTarget() {

if (!floors.isEmpty()) {
return floors.peek();
}

if (floors_up.isEmpty() && floors_down.isEmpty()) {
return current;
}

floors = (floors == floors_up ? floors_down : floors_up);
return floors.peek();
}

public int getCurrent() {
return current;
}

public void step(int target) {
if (target > current) {
current++;
} else {
current--;
}
}

public void stop() {
floors.poll();
}

public void move() {

while (getCurrent() != getTarget()) {
do {
step(getTarget());
} while (getCurrent() != getTarget());
stop();
}

}

}

*code for demo idea*

- KewpieWang February 22, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Direction {
	UP, DOWN
}

Elevator {
	Elevator id;
	Direction currentDirection;
	int currentLevel;
        List<MovementPlan> pendingPlans;
	MovementPlan currentPlan;

	// Definite stop in route. Create a new plan if required.
        public void addStoppage(int level) {
		boolean isPossibleInCurrentPlan = currentPlan.addStop(level, currentDirection);
		if (isPossibleInCurrentPlan) {
			return;
		}

		// try to see if it can fit in other plans
		for (MovementPlan plan : pendingPlans) {
			isPossibleInPending = plan.addStop(level, currentDirection);
			if(isPossibleInPending) return;
		}

		// Make a new plan. Current plan didn't work means request is of opposite direction
		Direction oppositeDirection = direction.equals(UP)?DOWN:UP;
		Integer firstStop = currentPlan.getLast(); // last stop there is first stop here
		Set<Integer> stops = {firstStop, level};
		MovementPlan newPlan = new MovementPlan(stops, oppositeDirection);
		plans.add(newPlan);
	}

	public boolean isIdle() { // if currentPlan==null && pendingPlans.isEmpty() }

	// Should keep executing asynchronously
        public void move() {
                while(true) {	
			moveTo(currentPlan.getNext());
			refreshCurrentLevel();

			// assuming movement completed
			currentPlan.reachedNextStop();

			if (currentPlan.isCompleted()) {
				if (pendingPlans.isEmpty()) {
					// wait for new plan
				} else {
					currentPlan = pendingPlans.get(0);
				}
			}
		}
	}
}

MovementPlan {
	Direction direction;
	Set<Integer> assignedStoppages;

	public ElevationPlan(Set<Integer assignedStops, Direction direction) {
		// keep assigned stops in sorted order.
		// ascending if direction is UP, else descending if direction is DOWN
	}        

	public Integer getNext() {
		assignedStoppages.get(0);
	}

	public Integer getLast() {
		assignedStoppages.get(assignedStoppages.size() -1);
	}

	// Adds if new stop falls in the way. Else returns false
	public boolean addStop(int newStop, Direction direction) {
		// is elevator moving in same direction 
		boolean isAlignedWithPlan = ((direction.equals(UP) && newStop > getNext()) 
				|| (direction.equals(DOWN)&& newStop < getNext()))


		if ((!isCompleted()) && this.direction.equals(direction) && isAlignedWithPlan)
               		assignedStoppages.add(newStop);
		else 
			return false;
	}

	public Integer reachedNextStop() {
		Integer next = getNext();
		assignedStoppages.remove(next);
	}

	public boolean isCompleted() {
		return assignedStoppages.isEmpty();
	}
}	

ExternalController {
	List<Elevator> elevators;
	initialize(Set<Elevator> elevators) {
		// initialize
	}

	public void addPickRequest(int stopAtLevel, Direction direction) {
		// get all current movement plans from all elevators
		// Check if already assigned to one of the elevators
		// else pick up next idle elevator and call addStoppage there
		// else if no elevator is idle
			// pick one elevator and call addStoppage there. will internally create new movement plan if necessary
	}	
}

- Harsh May 18, 2014 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More