Design an elevator system


  • 8
    R

    How do you notify the elevator that it needs to move up/down? You could also have a centralized class to control this. Define all the entities and behavior and clearly state your assumptions.


  • 1
    W
    public interface IElevator()
    {
         public boolean GoUP();
         public boolean GoDown();
         public int GetLevel();
         public void SetLevel(int level);
         public boolean CanAddLevel(int level);
    
    }
    
    public enum Directions {up, down};
    
    public enum Levels {1,2,3,4};
    
    // this is a normal elevator. We can also implement maintenance elevators or other kinds in similar way 
    public class Elevator extends IElevator()
    {
         // Implement Go up
         // Implement Go Down
    
        Queue<Integer> elevQ = new LinkedList<Integer>();
        
    // Method to set level
         public void SetLevel(int level)
         {
                   elevQ .add(level);
         }
    
    // method to get level
         public int GetLevel(int level)
         {
                   elevQ .peek();
         }
    
    // Method to check if a level can be added
    // we can either do this check on controller or give it to the elevators
          public boolean CanAddLevel(int level)
          {
                  if(Direction.up && elevQ .peek() < level)
                         return true;
                  else if(Direction.down && elevQ .peek() > level)
                         return true;
            return false
          } 
    }
    
    public class ElevatorController()
    {
    // contains logic to decide which elevator can be called from a particular floor
    // Contains a list of elevator
    }

  • 0
    G

    Guys, this is my thought process. Please give your feedback. :)

     
    class ELEVATOR_CONTROLLER {
      List<ELEVATOR>
      LIST<FLOORS>
      processRequest();
    }
    
    interface BUTTON{
       placeRequest();
    }
    class FloorButton implements BUTTON {
      direction
      placeRequest();
    }
    class ElevatorButton implements BUTTON {
       direction
       placeRequest();
    }
    
    class ELEVATOR {
      STATES: [IDLE, MAINTENANCE, LOADING, UNLOADING, MOVING ]
      direction: UP, Down
      current_floor:
      min_floor:
      max_floor:
      prohibited_floors: [...]
      currentRequest: 
      NextRequest:
    }
    
    class REQUEST {
     direction:
     floor:
    }
    
    class ELEVATOR_REQUEST {
      LIST<REQUEST>
      addRequest();
      removeRequest();
    }
    

    Wanted to upload the ER diagram image that I worked out on a notepad but Leetcode is giving some error.


  • 2
    B

    I have developed sample code in Kotlin under following constraints -
    i) I am running single lift
    ii) I am not handling maximum weight lift can bear

    Using this class i am starting lift using main method-

    import kotlin.concurrent.thread
    
    fun main(args: Array<String>) {
    
        val liftModel = LiftModel(0, Floor.GROUND, Direction.NONE)
        val liftController = LiftController(liftModel)
        thread(true, false, null, "Thread1", -1, { startLiftFirstThread(liftController) })
        thread(true, false, null, "Thread2", -1, { startLiftSecondThread(liftController) })
        liftController.addFloor(Floor.FIRST)
    }
    
    fun startLiftFirstThread(liftController: LiftController) {
        Thread.sleep(500)
        liftController.addFloor(Floor.GROUND)
        liftController.addFloor(Floor.SECOND)
        liftController.addFloor(Floor.FOURTH)
    }
    
    fun startLiftSecondThread(liftController: LiftController) {
        Thread.sleep(2000)
        liftController.addFloor(Floor.FIRST)
        Thread.sleep(5000)
        liftController.addFloor(Floor.THIRD)
    }
    

    Lift Controller class -

    enum class Floor {GROUND, FIRST, SECOND, THIRD, FOURTH, FIFTH }
    enum class Direction {UP, DOWN, NONE }
    
    class LiftController(liftModel: LiftModel) {
        private val mUpLiftFloorsList: MutableList<Floor> = mutableListOf<Floor>()
        private val mDownLiftFloorsList: MutableList<Floor> = mutableListOf<Floor>()
        private var mLiftModel: LiftModel = liftModel
    
        fun startLift() {
            mLiftModel.currentDirection = getLiftDirection()
    
            if (mLiftModel.currentDirection == Direction.UP) {
                moveLiftUp()
            } else if (mLiftModel.currentDirection == Direction.DOWN) {
                moveLiftDown()
            }
        }
    
        fun addFloor(newFloor: Floor) {
            //println("Adding Floor:$newFloor Current Ordinal ${mLiftModel.currentFloor.ordinal}, new Ordinal ${newFloor.ordinal}")
    
            if (mLiftModel.currentFloor.ordinal > newFloor.ordinal) {
                mDownLiftFloorsList.add(newFloor)
                mDownLiftFloorsList.sort()
                mDownLiftFloorsList.reverse()
                //println("Adding to Down List size=${mDownLiftFloorsList.size} and Floor $newFloor")
            } else if (mLiftModel.currentFloor.ordinal < newFloor.ordinal) {
                mUpLiftFloorsList.add(newFloor)
                mUpLiftFloorsList.sort()
                //println("Adding to Up List size=${mUpLiftFloorsList.size} and Floor $newFloor")
            }
    
            if (mLiftModel.currentDirection == Direction.NONE) {
                startLift()
            }
        }
    
        private fun removeVisitingFloor() {
            when (mLiftModel.currentDirection) {
                Direction.UP -> mUpLiftFloorsList.remove(mLiftModel.currentFloor)
                Direction.DOWN -> mDownLiftFloorsList.remove(mLiftModel.currentFloor)
                else -> {
                    //print("Do nothing")
                }
            }
        }
    
        private fun moveLiftUp() {
            do {
                val currentFloor: Floor = mUpLiftFloorsList.get(0)
                mLiftModel.currentFloor = currentFloor
                removeVisitingFloor()
                println("Lift Going Up to Floor: $currentFloor")
                Thread.sleep(1000); // The time in which lift moves up
            } while (mUpLiftFloorsList.size > 0)
    
            if (mDownLiftFloorsList.size > 0) {
                mLiftModel.currentDirection = Direction.DOWN
                moveLiftDown()
            } else {
                mLiftModel.currentDirection = Direction.NONE
            }
        }
    
        private fun moveLiftDown() {
            do {
                val currentFloor = mDownLiftFloorsList.get(0)
                mLiftModel.currentFloor = currentFloor
                removeVisitingFloor()
                println("Lift Going Down to Floor: $currentFloor")
                Thread.sleep(1000) // The time in which lift moves up
            } while (mDownLiftFloorsList.size > 0)
    
            if (mUpLiftFloorsList.size > 0) {
                mLiftModel.currentDirection = Direction.UP
                moveLiftUp()
            } else {
                mLiftModel.currentDirection = Direction.NONE
            }
        }
    
        private fun getLiftDirection(): Direction {
            if (mUpLiftFloorsList.size > 0) return Direction.UP
            else if (mDownLiftFloorsList.size > 0) return Direction.DOWN
            else return Direction.NONE
        }
    }
    

    Lift Model class to store data -

    data class LiftModel(var currentWeight: Int, var currentFloor: Floor, var currentDirection: Direction) {
        val TOP = Floor.FIFTH
        val GROUND = Floor.GROUND
    }
    

    Here is the output of my program -

    Lift Going Up to Floor: FIRST
    Lift Going Up to Floor: SECOND
    Lift Going Up to Floor: FOURTH
    Lift Going Down to Floor: FIRST
    Lift Going Down to Floor: GROUND
    Lift Going Up to Floor: THIRD
    
    

  • 0
    M

    In my approach in Java I calculated the waiting time of the elevator user by letting the elevator wait at the floor from which it has been called the most.
    Further ideas and improvements are very welcome :)

    /**
     * Creates an {@link Elevator} object and calls the {@link Elevator#callElevator} method
     */
    class LiftController {
    
        public static void main(String... aArgs) {
    
            Elevator elevator = new Elevator();
    
            elevator.callElevator(Floor.FIRST, Floor.SIXT);
            elevator.callElevator(Floor.THIRD, Floor.SEVENTH);
            elevator.callElevator(Floor.FIRST, Floor.SECOND);
            elevator.callElevator(Floor.FIRST, Floor.SEVENTH);
            elevator.callElevator(Floor.FIRST, Floor.FIFTH);
            elevator.callElevator(Floor.SECOND, Floor.SEVENTH);
            elevator.callElevator(Floor.SEVENTH, Floor.GROUND);
            elevator.callElevator(Floor.THIRD, Floor.FOURTH);
            elevator.callElevator(Floor.SECOND, Floor.GROUND);
            elevator.callElevator(Floor.SEVENTH, Floor.GROUND);
            elevator.callElevator(Floor.FIRST, Floor.FIFTH);
    
        }
    }
    
    import java.util.*;
    
    public class Elevator {
    
        private static Floor waitingFloorPosition;
        protected static boolean firstUsage = true;
        private static Map<Floor,Integer> usageMap;
        
        /**
         * If the elevator is called for the first time, the {@link #initializeElevator()} is called
         * Writes the console output with the waiting time computed by {@link #computeWaitingTime(Floor calledFrom)}
         * Sets the {@link #waitingFloorPosition} based on the most called calledFrom floor, computed by computeWaitingTime(Floor calledFrom)
         *
         * @param calledFrom
         * @param calledTo
         */
        public void callElevator(Floor calledFrom, Floor calledTo){
            if(firstUsage) {
                initializeElevator();
            }
    
            System.out.println("Drove from "+ calledFrom.toString() + " floor to "+ calledTo.toString() + " floor. The waiting time was " + computeWaitingTime(calledFrom));
            computeWaitingFloorPosition(calledFrom);
    
        }
        
        /**
         * Puts the floors and the number this floors have been called from into a Map<Floor,Integer>
         * Calls {@link MapUtils#sortByValue} to sort the map by its values
         * Sets the last entry in the sorted {@link #usageMap} as {@link #waitingFloorPosition}
         *
         * @param calledFrom
         */
        private void computeWaitingFloorPosition(Floor calledFrom) {
            if(usageMap.containsKey(calledFrom)){
                usageMap.put(calledFrom,usageMap.get(calledFrom) + 1);
            }
            else if (!usageMap.containsKey(calledFrom)){
                usageMap.put(calledFrom,1);
            }
            usageMap = MapUtils.sortByValue(usageMap);
    
            waitingFloorPosition = MapUtils.getLast(usageMap).getKey();
        }
    
        /**
         * Calculates the waiting time of the elevator user by substracting the {@link #waitingFloorPosition} from the calledFrom floor position
         * @param calledFrom
         * @return Long the waiting time
         */
        private Long computeWaitingTime(Floor calledFrom){
            return Math.abs(getNumericValueOfFloor(calledFrom) - getNumericValueOfFloor(waitingFloorPosition));
        }
    
        /**
         * Assigns a long value to every floor so its possible to compute a waiting time
         *
         * @param floor
         * @return
         */
        private Long getNumericValueOfFloor(Floor floor){
            Long numericValue = 0l;
    
            switch (floor) {
                case GROUND:  numericValue = 0l;
                    break;
                case FIRST: numericValue = 1l;
                    break;
                case SECOND: numericValue = 2l;
                    break;
                case THIRD: numericValue = 3l;
                    break;
                case FOURTH: numericValue = 4l;
                    break;
                case FIFTH: numericValue = 5l;
                    break;
                case SIXT: numericValue = 6l;
                    break;
                case SEVENTH: numericValue = 7l;
                    break;
                default: numericValue = 0l;
                    break;
            }
            return numericValue;
        }
        
        /**
         * If the elevator is called for the first time:
         * The {@link #waitingFloorPosition} is set to {@link Floor#GROUND}
         * A new instance of {@link #usageMap} Map<Floor,Integer> is created
         * The static boolean {@link #firstUsage} is set to false so that the elevator can't be initialized a second time
         */
        private void initializeElevator() {
            waitingFloorPosition = Floor.GROUND;
            usageMap = new HashMap<>();
            firstUsage = false;
        }
        
    }
    
    
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.LinkedHashMap;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    
    /**
     * Contains static methods for:
     *
     * - Sorting a map by its values
     * - Returning the last element of a map
     */
    public class MapUtils {
    
        /**
         * Returns the last entry in a Map<K, V>
         * @param map
         * @param <K>
         * @param <V>
         * @return Map.Entry<K, V>
         */
        public static <K,V> Map.Entry<K,V> getLast(Map<K,V> map) {
            Iterator<Map.Entry<K,V>> iterator = map.entrySet().iterator();
            Map.Entry<K, V> result = null;
            while (iterator.hasNext()) {
                result = iterator.next();
            }
            return result;
        }
    
        /**
         * Sorts a map by its values
         * @param map
         * @param <K>
         * @param <V>
         * @return Map<K, V>
         */
        public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
            List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(map.entrySet());
            Collections.sort( list, new Comparator<Map.Entry<K, V>>() {
                public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
                    return (o1.getValue()).compareTo( o2.getValue() );
                }
            });
    
            Map<K, V> result = new LinkedHashMap<K, V>();
            for (Map.Entry<K, V> entry : list) {
                result.put(entry.getKey(), entry.getValue());
            }
            return result;
        }
    }
    
    /** Enum class with all possible floors the elevator can go to or be called from*/
    public enum Floor {
        GROUND, FIRST, SECOND, THIRD, FOURTH, FIFTH, SIXT, SEVENTH
    }
    

Log in to reply
 

Looks like your connection to LeetCode Discuss was lost, please wait while we try to reconnect.