RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1166073
Accepted
J Mas
J Mas
Asked:2020-08-15 00:02:30 +0000 UTC2020-08-15 00:02:30 +0000 UTC 2020-08-15 00:02:30 +0000 UTC

电梯模拟器挑战

  • 772

电梯模拟器的任务,任务解决了,一切正常,但被我需要收紧算法的话拒绝了。这是什么意思,还有什么办法可以解决这个问题?


/**
 * Написать программу «симулятор лифта».
 * Программа запускается из коммандной строки, в качестве параметров задается:
 *      кол-во этажей в подъезде - N (от 5 до 20);
 *      высота одного этажа;
 *      скорость лифта при движении в метрах в секунду (ускорением пренебрегаем, считаем, что когда лифт едет - он сразу едет с определенной скоростью);
 *      время между открытием и закрытием дверей.
 *
 * После запуска программа должна постоянно ожидать ввода от пользователя и выводить действия лифта в реальном времени.
 * События, которые нужно выводить:
 * лифт проезжает некоторый этаж;
 * лифт открыл двери;
 * лифт закрыл двери.
 *
 * Возможный ввод пользователя:
 *       вызов лифта на этаж из подъезда;
 *       нажать на кнопку этажа внутри лифта.
 *
 * Считаем, что пользователь не может помешать лифту закрыть двери.
 * Все данные, которых не хватает в задаче можно выбрать на свое усмотрение.
 * В результате должен получиться компилируемый код (в случае с java предлагается писать код в одном файле).
 */

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Elevator elevator = new Elevator(20, 3, 2, 2);
        elevator.init();
    }

    private static class Elevator {
        private static final long MILLISECONDS = 100; //1000
        private final int doorTime;
        private final int floors;
        private final long floorSpeedSeconds;
        private int currentFloor = 1;

        private Elevator(int floors, int height, int speed, int doorTime) {
            this.doorTime = doorTime;
            this.floors = floors;
            floorSpeedSeconds = height / speed * MILLISECONDS;
        }

        private void init() throws InterruptedException {
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNext()) {
                Command command = new Command(scanner.nextLine());
                if (command.targetFloor > floors) {
                    System.out.println("Target floor should be less than " + floors);
                    continue;
                }
                if (command.targetFloor > currentFloor) {
                    moveUp(command);
                } else if (command.targetFloor < currentFloor) {
                    moveDown(command);
                }
                currentFloor = command.targetFloor;
                openAndCloseDoor(doorTime);
            }
        }

        private void printCurrentFloor(int i) {
            System.out.println("Current floor is " + i);
        }

        private void openAndCloseDoor(int doorTime) throws InterruptedException {
            System.out.println("Open door");
            Thread.sleep(doorTime * MILLISECONDS);
            System.out.println("Close door");
        }

        private void moveDown(Command command) throws InterruptedException {
            for (int i = currentFloor; i >= command.targetFloor; i--) {
                Thread.sleep(floorSpeedSeconds);
                printCurrentFloor(i);
            }
        }

        private void moveUp(Command command) throws InterruptedException {
            for (int i = currentFloor; i <= command.targetFloor; i++) {
                Thread.sleep(floorSpeedSeconds);
                printCurrentFloor(i);
            }
        }
    }

    private static class Command {
        private final PressType type;
        private final int targetFloor;

        private Command(String type) {
            String[] commands = type.split(" ");
            this.type = PressType.type(commands[0]);
            this.targetFloor = parseInt(commands[1]);
        }
    }

    private enum PressType {
        IN("in"),
        OUT("out");

        private final String type;

        PressType(String type) {
            this.type = type;
        }

        private static PressType type(String s) {
            return valueOf(s);
        }
    }

}
java
  • 4 4 个回答
  • 10 Views

4 个回答

  • Voted
  1. Best Answer
    tym32167
    2020-08-15T12:34:04Z2020-08-15T12:34:04Z

    我会做一些不同的事情。

    对于初学者来说,有一个关于实时的说法,即理论上电梯应该按自己的流程运行。

    如果电梯在自己的流程中并且仍然接受命令,那么同步问题就出现了。如果命令在命令链中排列,这很容易解决。怎么做?利用Executors.newSingleThreadExecutor()

    此外,按下按钮并不意味着电梯会突然冲到那个楼层。按下按钮时电梯可能已经在移动,并且可能正在向相反方向移动。也就是说,理论上,按下按钮只是让电梯知道它,但是当电梯运行时,会有一个单独的问题。

    当然,理想情况下,还必须考虑到一个人想去哪里(上或下)——这可能是从入口/电梯按下的意思。这很容易做到,但我不想让这个例子复杂化。

    事实上,最简单的选择是这样的:当你点击按钮时,只需标记楼层并添加电梯的任务来驱动所有标记的楼层。如果电梯已经在移动并到达标记的楼层,它将停止并打开门。

    代码看起来像这样(我不太擅长java,如果有问题,请见谅)

    class Elevator {
        private final long floorInterval;
        private final long waitingInterval;
        private int currentFloor = 0;
        private boolean[] floorButtons;
    

    我们的 ExecutorService

        private ExecutorService executor = Executors.newSingleThreadExecutor();
    
        public Elevator(int floors, long floorInterval, long waitingInterval) {
            this.floorInterval = floorInterval;
            this.waitingInterval = waitingInterval;
            this.floorButtons = new boolean[floors];
        }
    

    按钮

        public void buttonPressedForFloor(final int floor) {
            floorButtons[floor] = true;
            executor.submit(() -> {
                try {
                    this.moveUp();
                    this.moveDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    

    检查是否需要向上移动

        private void moveUp() throws InterruptedException {
            for (int i = currentFloor; i < floorButtons.length; i++)
                if (floorButtons[i]) {
                    moveTo(i);
                    return;
                }
        }
    

    检查是否需要向下移动

        private void moveDown() throws InterruptedException {
            for (int i = currentFloor; i > 0; i--)
                if (floorButtons[i]) {
                    moveTo(i);
                    return;
                }
        }
    

    运动本身

        private void moveTo(int targetFloor) throws InterruptedException {
            int step = 1;
            if (targetFloor < currentFloor) step = -1;
            while (currentFloor != targetFloor) {
                Thread.sleep(floorInterval);
                currentFloor += step;
                sendMessage("CURRENT FLOOR: " + currentFloor);
                if (floorButtons[currentFloor]) {
                    floorButtons[currentFloor] = false;
                    doorOpenClose();
                }
            }
        }
    

    辅助代码

        private void doorOpenClose() throws InterruptedException {
            sendMessage("DOORS OPENED");
            Thread.sleep(waitingInterval);
            sendMessage("DOORS CLOSED");
        }
    
        private static void sendMessage(String message) {
            System.out.println(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_TIME) + " " + message);
        }
    
        public void stop() {
            executor.shutdown();
        }
    }
    

    你可以这样开始这种快乐

    public static void main(String[] args) {
    
        Scanner scanner = new Scanner(System.in);
    
        System.out.println("input number of floors: ");
        int numOfFlors = scanner.nextInt();
    
        System.out.println("input floor height (m): ");
        double floorHeight = scanner.nextDouble();
    
        System.out.println("input floor velocity (m/s): ");
        double floorVelocity = scanner.nextDouble();
    
        System.out.println("input floor doors time (seconds): ");
        long waitingInterval = scanner.nextLong() * 1000;
    
        long floorTime = (long) (1000.0 * floorHeight / floorVelocity);
    
        Elevator elevator = new Elevator(numOfFlors, floorTime, waitingInterval);
    
        scanner.nextLine();
    
        while (true) {
            String line = scanner.nextLine();
            if ("q".equals(line)) {
                elevator.stop();
                return;
            }
            try {
                int nextFloor = Integer.parseInt(line);
                if (nextFloor < 1 || nextFloor > numOfFlors) {
                    System.out.println("Wrong floor. Try again.");
                } else {
                    elevator.buttonPressedForFloor(nextFloor);
                }
            } catch (Exception e) {
                System.out.println(line + " not a number");
            }
        }
    }
    

    原来是这样的

    ...

    • 3
  2. Roman-Stop RU aggression in UA
    2020-08-15T01:19:11Z2020-08-15T01:19:11Z

    我认为,关于条件下实时的短语表明您需要能够在当前命令已经被执行时接受新命令。那些。“读取命令 - 执行”的方法并不好。考虑到新的传入命令,有必要优化电梯的运行。从这个意义上的算法的角度来看,这个问题更有趣也更困难。

    • 1
  3. Aziz Umarov
    2020-08-15T01:05:01Z2020-08-15T01:05:01Z

    我个人认为应该阅读 SOLID 和模式。并按照单一职责的第一原则去做。并查看命令方向和其他行为方向的模式。出于某种原因,您本身就有一部电梯,它正在等待命令并移动。使程序可以通过最小的更改从空间中的控制台接收来自文件的命令。关于算法,我不认为它们是从这项任务开始的。

    • 0
  4. Perfect Voyage
    2020-08-15T04:59:13Z2020-08-15T04:59:13Z

    我会以不同的方式完成这项工作。我会创建一个电梯类,从该类继承到楼层的呼叫按钮的 2 个类,以及机舱本身的按钮。电梯只有一种方法——移动(向上或向下)。所有从按钮接收到的命令,驱动到某个堆栈并依次执行。如果移动方向与调用重合,则在该楼层停止并从堆栈中移除。

    • 0

相关问题

  • wpcap 找不到指定的模块

  • 如何以编程方式从桌面应用程序打开 HTML 页面?

  • Android Studio 中的 R.java 文件在哪里?

  • HashMap 初始化

  • 如何使用 lambda 表达式通过增加与原点的距离来对点进行排序?

  • 最大化窗口时如何调整元素大小?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5