Ad

Driving Test Examiner on an Alien Planet

Problem Description

You work as a driving test examiner on an alien planet. Your task is to evaluate whether an examinee has passed the exam based on the data you receive and the rules described below.


Input Data

You receive two strings:

  1. Indications: Represents the signs and instructions encountered during the exam.
    Format: "t=time SYMBOL;"
    Example: "t=30 STOP;" means a STOP sign was encountered at second 30.

  2. Actions: The examinee's registered actions every second, showing speed and turns if any.
    Format: Speeds and turns separated by spaces.
    Example: "29 28 28< 27 29 27 0 0 0 0 23> 24 ..."


Legend of Indications and Expected Behavior

Indication Symbol Expected Behavior
STOP STOP Stop at least 3 seconds with no cars passing
STOP with cars STOP3 (3 cars) Stop 3 seconds + 2 seconds for each passing car
YIELD YIELD Stop ONLY if there are cars passing (2 seconds per car)
YIELD with cars YIELD2 (2 cars) Stop according to number of cars (2 seconds per car)
Speed Limit SL50 Do not exceed the speed limit until another SL appears
Turn TURNL, TURNR Turn left or right as indicated
Red Light REDLIGHT3 Stop for the specified number of seconds

Format of Actions

  • Data is recorded each and every second of the exam.
  • Turns are represented by < (left) and > (right).
    Example: 78> means at speed 78, a right turn was made.

Infractions and Evaluation

Minor Infractions (3 minors disqualify)

Infraction Description
Speeding Driving over speed limit for 3 consecutive seconds
Wrong turn Not turning, turning when not indicated or turning in the wrong direction

Eliminatory Infractions (1 eliminates immediately)

Infraction Description
Running a red light Not stopping or moving before the light turns green
STOP related infraction Not stopping at a STOP sign or stopping for less time than required
Running into traffic Not waiting necessary time for cars to pass at STOP or YIELD
Reckless driving Exceeding speed limit by more than 10 units at any time

Important Notes

  • There will always be a speed limit sign at t=1.
  • Inputs are always valid, no validation required.
  • Return true if the examinee passes the test, false otherwise.

Example Input

indications = "t=1 SL30 ; t=7 YIELD2 ; t=13 SL90 ; t=15 TURNR; t=21 REDLIGHT8 ; t=30 STOP;"
actions = "29 28 28 27 29 27 0 0 0 0 23 24 67 72 78> 85 87 86 84 89 0 0 0 0 0 0 0 0 25 0 0 0 34 56"
Code
Diff
  • import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.function.BiConsumer;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    class DrivingTestEvaluator {
    	static Map<String, BiConsumer<Integer, String>> rules = new HashMap();
    	static int speedLimit = 0;
    	static int indexLastSpeedLimit = 1;
    	static int indexIndicationList = 0;
    	static int indexActionList = 0;
    	static int minorMistakes = 0;
    	static boolean isEliminated = false;
    	static int currentTime = 0;
    	static int secondsInfringement = 0;
    	static List<String> indicationList;
    	static List<String> actionList;
    
    	public static boolean evaluate(String indications, String actions) {
    		clearState();
    
    		indicationList = Arrays.stream(indications.split(";")).toList();
    
    		actionList = Arrays.stream(actions.split(" ")).toList();
    
    		refillRules();
    		for (String indication : indicationList) {
    			processIndication(indication);
    		}
    		return 3 > minorMistakes && !isEliminated;
    	}
    
    	private static void refillRules() {
    		rules.put("STOP", (DrivingTestEvaluator::processStop));
    		rules.put("SL", (DrivingTestEvaluator::processSpeedLimit));
    		rules.put("YIELD", (DrivingTestEvaluator::processYield));
    		rules.put("TURN", (DrivingTestEvaluator::processTurn));
    		rules.put("REDLIGHT", (DrivingTestEvaluator::processRedLight));
    	}
    
    	private static void processIndication(String indication) {
    		Pattern pattern = Pattern.compile("t=(\\d+)\\s+(\\S+)");
    		Matcher matcher = pattern.matcher(indication);
    		if (matcher.find()) {
    			Integer time = Integer.valueOf(matcher.group(1));
    			String instruction = matcher.group(2);
    			rules.keySet().stream().filter(instruction::contains).findFirst()
    					.ifPresent(key -> rules.get(key).accept(time, indication));
    		}
    	}
    
    	private static void processTurn(Integer t, String signal) {
    		String direction = "";
    		Pattern pattern = Pattern.compile("TURN([A-Z])");
    		Matcher matcher = pattern.matcher(signal);
    		if (matcher.find()) {
    			direction = matcher.group(1);
    		}
    		if (actionList.get(t - 1).endsWith(">") || actionList.get(t - 1).endsWith("<")) {
    			if (actionList.get(t - 1).endsWith(">") && direction.equals("L")
    					|| actionList.get(t - 1).endsWith("<") && direction.equals("R"))
    				minorMistakes++;
    		} else {
    			minorMistakes++;
    		}
    	}
    
    	private static void processRedLight(Integer time, String signal) {
    		Pattern pattern = Pattern.compile("REDLIGHT(\\d+)");
    		Matcher matcher = pattern.matcher(signal);
    		if (matcher.find()) {
    			processCorrectlyStopped(time, Integer.valueOf(matcher.group(1)));
    		}
    	}
    
    	private static void processYield(Integer time, String signal) {
    		Integer secondsToStop = 0;
    		Pattern pattern = Pattern.compile("YIELD(\\d+)");
    		Matcher matcher = pattern.matcher(signal);
    		if (matcher.find()) {
    			secondsToStop += (2 * Integer.valueOf(matcher.group(1)));
    			processCorrectlyStopped(time, secondsToStop);
    		} else {
    			if (Integer.parseInt(actionList.get(time - 1)) == 0)
    				isEliminated = true;
    		}
    
    	}
    
    	private static void processStop(Integer time, String signal) {
    		Integer secondsToStop = 3;
    		Pattern pattern = Pattern.compile("STOP(\\d+)");
    		Matcher matcher = pattern.matcher(signal);
    		if (matcher.find()) {
    			secondsToStop += Integer.parseInt(matcher.group(1)) * 2;
    		}
    		processCorrectlyStopped(time, secondsToStop);
    
    	}
    
    	private static void processCorrectlyStopped(Integer time, Integer secondsToStop) {
    		if (Integer.parseInt(actionList.get(time - 1)) > 0) {
    			isEliminated = true;
    			return;
    		}
    
    		while (secondsToStop != 0) {
    			if (time > actionList.size() || Integer.parseInt(actionList.get(time - 1)) > 0) {
    				isEliminated = true;
    				return;
    			}
    			time++;
    			secondsToStop--;
    		}
    	}
    
    	private static void processSpeedLimit(Integer time, String signal) {
    		Integer digits = 0;
    		for (int i = indexLastSpeedLimit; i < time; i++) {
    			String velocity = actionList.get(i);
    			Pattern pattern = Pattern.compile("(\\d+)");
    			Matcher matcher = pattern.matcher(velocity);
    			if (matcher.find()) {
    				digits = Integer.parseInt(matcher.group(1));
    			}
    
    			if (digits > speedLimit) {
    				secondsInfringement++;
    			} else {
    				secondsInfringement = 0;
    			}
    			if (secondsInfringement > 2)
    				minorMistakes++;
    		}
    		Pattern pattern = Pattern.compile("SL(\\d+)");
    		Matcher matcher = pattern.matcher(signal);
    		if (matcher.find()) {
    			speedLimit = Integer.valueOf(matcher.group(1));
    		}
    		indexLastSpeedLimit = time - 1;
    	}
    
    	private static void clearState() {
    		speedLimit = 0;
    		indexLastSpeedLimit = 1;
    		indexIndicationList = 0;
    		indexActionList = 0;
    		minorMistakes = 0;
    		isEliminated = false;
    		currentTime = 0;
    		secondsInfringement = 0;
    	}
    
    }
    
    • import java.util.Arrays;
    • import java.util.HashMap;
    • import java.util.List;
    • import java.util.Map;
    • import java.util.function.BiConsumer;
    • import java.util.regex.Matcher;
    • import java.util.regex.Pattern;
    • class DrivingTestEvaluator {
    • static Map<String, BiConsumer<Integer, String>> rules = new HashMap();
    • static int speedLimit = 0;
    • static int indexLastSpeedLimit = 1;
    • static int indexIndicationList = 0;
    • static int indexActionList = 0;
    • static int minorMistakes = 0;
    • static boolean isEliminated = false;
    • static int currentTime = 0;
    • static int secondsInfringement = 0;
    • static List<String> indicationList;
    • static List<String> actionList;
    • public static boolean evaluate(String indications, String actions) {
    • clearState();
    • indicationList = Arrays.stream(indications.split(";")).toList();
    • actionList = Arrays.stream(actions.split(" ")).toList();
    • refillRules();
    • for (String indication : indicationList) {
    • processIndication(indication);
    • }
    • return 3 > minorMistakes && !isEliminated;
    • }
    • private static void refillRules() {
    • rules.put("STOP", (DrivingTestEvaluator::processStop));
    • rules.put("SL", (DrivingTestEvaluator::processSpeedLimit));
    • rules.put("YIELD", (DrivingTestEvaluator::processYield));
    • rules.put("TURN", (DrivingTestEvaluator::processTurn));
    • rules.put("REDLIGHT", (DrivingTestEvaluator::processRedLight));
    • }
    • private static void processIndication(String indication) {
    • Pattern pattern = Pattern.compile("t=(\\d+)\\s+(\\S+)");
    • Matcher matcher = pattern.matcher(indication);
    • if (matcher.find()) {
    • Integer time = Integer.valueOf(matcher.group(1));
    • String instruction = matcher.group(2);
    • rules.keySet().stream().filter(instruction::contains).findFirst()
    • .ifPresent(key -> rules.get(key).accept(time, indication));
    • }
    • }
    • private static void processTurn(Integer t, String signal) {
    • String direction = "";
    • Pattern pattern = Pattern.compile("TURN([A-Z])");
    • Matcher matcher = pattern.matcher(signal);
    • if (matcher.find()) {
    • direction = matcher.group(1);
    • }
    • if (actionList.get(t - 1).endsWith(">") || actionList.get(t - 1).endsWith("<")) {
    • if (actionList.get(t - 1).endsWith(">") && direction.equals("L")
    • || actionList.get(t - 1).endsWith("<") && direction.equals("R"))
    • minorMistakes++;
    • } else {
    • minorMistakes++;
    • }
    • }
    • private static void processRedLight(Integer time, String signal) {
    • Pattern pattern = Pattern.compile("REDLIGHT(\\d+)");
    • Matcher matcher = pattern.matcher(signal);
    • if (matcher.find()) {
    • processCorrectlyStopped(time, Integer.valueOf(matcher.group(1)));
    • }
    • }
    • private static void processYield(Integer time, String signal) {
    • Integer secondsToStop = 0;
    • Pattern pattern = Pattern.compile("YIELD(\\d+)");
    • Matcher matcher = pattern.matcher(signal);
    • if (matcher.find()) {
    • secondsToStop += (2 * Integer.valueOf(matcher.group(1)));
    • processCorrectlyStopped(time, secondsToStop);
    • } else {
    • if (Integer.parseInt(actionList.get(time - 1)) == 0)
    • isEliminated = true;
    • }
    • }
    • private static void processStop(Integer time, String signal) {
    • Integer secondsToStop = 3;
    • Pattern pattern = Pattern.compile("STOP(\\d+)");
    • Matcher matcher = pattern.matcher(signal);
    • if (matcher.find()) {
    • secondsToStop += Integer.parseInt(matcher.group(1)) * 2;
    • }
    • processCorrectlyStopped(time, secondsToStop);
    • }
    • private static void processCorrectlyStopped(Integer time, Integer secondsToStop) {
    • if (Integer.parseInt(actionList.get(time - 1)) > 0) {
    • isEliminated = true;
    • return;
    • }
    • while (secondsToStop != 0) {
    • if (time > actionList.size() || Integer.parseInt(actionList.get(time - 1)) > 0) {
    • isEliminated = true;
    • return;
    • }
    • time++;
    • secondsToStop--;
    • }
    • }
    • private static void processSpeedLimit(Integer time, String signal) {
    • Integer digits = 0;
    • for (int i = indexLastSpeedLimit; i < time; i++) {
    • String velocity = actionList.get(i);
    • Pattern pattern = Pattern.compile("(\\d+)");
    • Matcher matcher = pattern.matcher(velocity);
    • if (matcher.find()) {
    • digits = Integer.parseInt(matcher.group(1));
    • }
    • if (digits > speedLimit) {
    • secondsInfringement++;
    • } else {
    • secondsInfringement = 0;
    • }
    • if (secondsInfringement > 2)
    • minorMistakes++;
    • }
    • Pattern pattern = Pattern.compile("SL(\\d+)");
    • Matcher matcher = pattern.matcher(signal);
    • if (matcher.find()) {
    • speedLimit = Integer.valueOf(matcher.group(1));
    • }
    • indexLastSpeedLimit = time - 1;
    • }
    • private static void clearState() {
    • speedLimit = 0;
    • indexLastSpeedLimit = 1;
    • indexIndicationList = 0;
    • indexActionList = 0;
    • minorMistakes = 0;
    • isEliminated = false;
    • currentTime = 0;
    • secondsInfringement = 0;
    • }
    • public class DrivingTestEvaluator {
    • static int knockoutFoul;
    • static int mildFoul;
    • static List<String> actions;
    • static int currentIndex;
    • public static boolean evaluate(String exam, String road) {
    • knockoutFoul = 0;
    • mildFoul = 0;
    • currentIndex = 0;
    • actions = Arrays.asList(exam.trim().split("\\s+"));
    • List<String> rules = Arrays.asList(road.trim().split("\\s+"));
    • for (String rule : rules) {
    • if (rule.startsWith("SL")) {
    • comprobateSpeedLimit(rule);
    • } else if (rule.startsWith("STOP")) {
    • comprobateStop(rule);
    • } else if (rule.startsWith("YIELD")) {
    • comprobateYield(rule);
    • } else if (rule.startsWith("TURN")) {
    • comprobateTurn(rule);
    • } else if (rule.startsWith("R")) {
    • comprobateRedLight(rule);
    • }
    • if (knockoutFoul > 0) return false;
    • }
    • return mildFoul < 3;
    • }
    • public static void comprobateSpeedLimit(String rule) {
    • String[] parts = rule.substring(2).split("_");
    • int speedLimit = Integer.parseInt(parts[0]);
    • int duration = Integer.parseInt(parts[1]);
    • int overLimitCounter = 0;
    • boolean minorCounted = false;
    • for (int i = 0; i < duration && currentIndex + i < actions.size(); i++) {
    • int speed = extractSpeed(actions.get(currentIndex + i));
    • if (speed > speedLimit + 10) {
    • knockoutFoul++;
    • return;
    • }
    • if (speed > speedLimit) {
    • overLimitCounter++;
    • } else {
    • overLimitCounter = 0;
    • }
    • if (overLimitCounter >= 3 && !minorCounted) {
    • mildFoul++;
    • minorCounted = true;
    • }
    • }
    • currentIndex += Math.min(duration, actions.size() - currentIndex);
    • }
    • public static void comprobateStop(String rule) {
    • int cars = rule.length() > 4 ? Integer.parseInt(rule.substring(4)) : 0;
    • int requiredStop = 3 + (2 * cars);
    • int stopCount = 0;
    • while (currentIndex < actions.size() && extractSpeed(actions.get(currentIndex)) == 0) {
    • stopCount++;
    • currentIndex++;
    • }
    • if (stopCount == 0) {
    • knockoutFoul++;
    • } else if (stopCount < requiredStop) {
    • if (stopCount >= 2 * cars) mildFoul++;
    • else knockoutFoul++;
    • }
    • }
    • public static void comprobateYield(String rule) {
    • int cars = rule.length() > 5 ? Integer.parseInt(rule.substring(5)) : 0;
    • int requiredStop = 2 * cars;
    • int stopCount = 0;
    • while (currentIndex < actions.size() && extractSpeed(actions.get(currentIndex)) == 0) {
    • stopCount++;
    • currentIndex++;
    • }
    • if (cars == 0) {
    • if (stopCount >= 2) knockoutFoul++;
    • } else {
    • if (stopCount < requiredStop) {
    • knockoutFoul++;
    • } else if (stopCount < requiredStop + 3) {
    • mildFoul++;
    • }
    • }
    • }
    • public static void comprobateTurn(String rule) {
    • String requiredDirection = rule.equals("TURNR") ? ">" : "<";
    • boolean turned = false;
    • for (int i = currentIndex; i < actions.size(); i++) {
    • if (actions.get(i).endsWith(requiredDirection)) {
    • turned = true;
    • currentIndex = i + 1;
    • break;
    • }
    • }
    • if (!turned) {
    • mildFoul++;
    • }
    • }
    • public static void comprobateRedLight(String rule) {
    • int duration = Integer.parseInt(rule.substring(1));
    • boolean failed = false;
    • for (int i = 0; i < duration && currentIndex + i < actions.size(); i++) {
    • if (extractSpeed(actions.get(currentIndex + i)) != 0) {
    • failed = true;
    • }
    • }
    • if (failed) {
    • knockoutFoul++;
    • }
    • currentIndex += Math.min(duration, actions.size() - currentIndex);
    • }
    • public static int extractSpeed(String action) {
    • if (action.endsWith("<") || action.endsWith(">")) {
    • return Integer.parseInt(action.substring(0, action.length() - 1));
    • }
    • return Integer.parseInt(action);
    • }
    • }

You work as a driving test examiner in an alien planet. Your task is to evaluate whether an examinee has passed the exam based on the exam data you receive and the rules described below.

You receive the exam data in two Strings, the first one represents all the indications the driver has received during the exam, from road signals and the examiner. The second String represents the actions of the examinee which are registered every second from the start to the end of the exam.

The format of the strings is the following:

  • indications: String of indications separated by ";" which include the time they were encountered and the indication symbol following the legend below:
"t=30 STOP;"
//An stop sign was encountered at second 30
Indication Symbol Expected Behaviour
STOP STOP -> No cars passing by
STOP3 -> 3 cars passing by
Stop at least 3 seconds + 2 seconds for each passing car
YIELD YIELD -> No cars passing by
YIELD2 -> 2 cars passing by
Stop ONLY if there are cars passing by (2 seconds/car)
SPEED LIMIT SL50 -> Sets a speed limit of 50 until another SL is encountered Don't go over the set speed limit
TURN TURNL -> Turn left
TURNR -> Turn right
Turn as indicated
Red light REDLIGHT3 -> Red light for 3 seconds Stop for the given amount of time
  • actions: String of symbols separated by " " which contains the speed of the vehicle and the turn, if any, taken at each second of the exam. Turns are represented with "<" (left) and ">" (right).

Input example:

indications = "t=1 SL30 ; t=7 YIELD2 ; t=13 SL90 ; t=15 TURNR; t=21 REDLIGHT8 ; t=30 STOP;"
actions     = "29 28 28 27 29 27 0 0 0 0 23 24 67 72 78> 85 87 86 84 89 0 0 0 0 0 0 0 0 25 0 0 0 34 56"

Infractions

There are minor and eliminatory infractions. Three minor infractions or one eliminatory infraction will disqualify the examinee.

Minor Infraction Description
Speed limit Examinee drives over the speed limit for three consecutive seconds.
Insufficient stop time (no cars) Examinee stops at STOP signal but does so for less than three seconds (no cars passing by).
Insufficient stop time (cars) Examinee waits the necessary time for all cars to pass by but does not wait or waits partially the mandatory 3 seconds.
Wrong Turn Examinee does not turn when indicated or turns the wrong way.

Eliminatory Infraction Description
Unnecessary stopping Examinee stops for no reason at all. This includes stopping for longer than required at stops, yields, or red lights and stopping at yields when there are no cars passing by.
Running a red light Examinee doesn't stop or starts moving before a red light turns green.
Ignored STOP Examinee doesn't stop at all at a stop sign.
Running into traffic. Examinee doesn't wait the necessary time at a STOP or yield sign for other cars to pass by.
Reckless driving Examinee goes over the speed limit for over 10 speed units at any given time.

Notes

  • There will always be a speed sign at second t=1.
  • All inputs will be valid so no validation is required.
  • You can see more examples in the sample tests.

You must return true if the examinee has passed the test and false if they haven't.

Code
Diff
  • import java.util.Arrays;
    import java.util.List;
    
    public class DrivingTestEvaluator {
        static int knockoutFoul;
        static int mildFoul;
        static List<String> actions;
        static int currentIndex;
    
        public static boolean evaluate(String exam, String road) {
            knockoutFoul = 0;
            mildFoul = 0; 
            currentIndex = 0;
    
            actions = Arrays.asList(exam.trim().split("\\s+"));
            List<String> rules = Arrays.asList(road.trim().split("\\s+"));
    
            for (String rule : rules) {
                if (rule.startsWith("SL")) {
                    comprobateSpeedLimit(rule);
                } else if (rule.startsWith("STOP")) {
                    comprobateStop(rule);
                } else if (rule.startsWith("YIELD")) {
                    comprobateYield(rule);
                } else if (rule.startsWith("TURN")) {
                    comprobateTurn(rule);
                } else if (rule.startsWith("R")) {
                    comprobateRedLight(rule);
                }
    
                if (knockoutFoul > 0) return false;
            }
    
            return mildFoul < 3;
        }
    
        public static void comprobateSpeedLimit(String rule) {
            String[] parts = rule.substring(2).split("_");
            int speedLimit = Integer.parseInt(parts[0]);
            int duration = Integer.parseInt(parts[1]);
    
            int overLimitCounter = 0;
            boolean minorCounted = false;
    
            for (int i = 0; i < duration && currentIndex + i < actions.size(); i++) {
                int speed = extractSpeed(actions.get(currentIndex + i));
    
                if (speed > speedLimit + 10) {
                    knockoutFoul++;
                    return;
                }
    
                if (speed > speedLimit) {
                    overLimitCounter++;
                } else {
                    overLimitCounter = 0;
                }
    
                if (overLimitCounter >= 3 && !minorCounted) {
                    mildFoul++;
                    minorCounted = true;
                }
            }
    
            currentIndex += Math.min(duration, actions.size() - currentIndex);
        }
    
        public static void comprobateStop(String rule) {
            int cars = rule.length() > 4 ? Integer.parseInt(rule.substring(4)) : 0;
            int requiredStop = 3 + (2 * cars);
    
            int stopCount = 0;
            while (currentIndex < actions.size() && extractSpeed(actions.get(currentIndex)) == 0) {
                stopCount++;
                currentIndex++;
            }
    
            if (stopCount == 0) {
                knockoutFoul++;
            } else if (stopCount < requiredStop) {
                if (stopCount >= 2 * cars) mildFoul++;
                else knockoutFoul++;
            }
        }
    
        public static void comprobateYield(String rule) {
            int cars = rule.length() > 5 ? Integer.parseInt(rule.substring(5)) : 0;
            int requiredStop = 2 * cars;
    
            int stopCount = 0;
            while (currentIndex < actions.size() && extractSpeed(actions.get(currentIndex)) == 0) {
                stopCount++;
                currentIndex++;
            }
    
            if (cars == 0) {
                if (stopCount >= 2) knockoutFoul++;
            } else {
                if (stopCount < requiredStop) {
                    knockoutFoul++;
                } else if (stopCount < requiredStop + 3) {
                    mildFoul++;
                }
            }
        }
    
        public static void comprobateTurn(String rule) {
            String requiredDirection = rule.equals("TURNR") ? ">" : "<";
            boolean turned = false;
    
            for (int i = currentIndex; i < actions.size(); i++) {
                if (actions.get(i).endsWith(requiredDirection)) {
                    turned = true;
                    currentIndex = i + 1;
                    break;
                }
            }
    
            if (!turned) {
                mildFoul++;
            }
        }
    
        public static void comprobateRedLight(String rule) {
            int duration = Integer.parseInt(rule.substring(1));
            boolean failed = false;
    
            for (int i = 0; i < duration && currentIndex + i < actions.size(); i++) {
                if (extractSpeed(actions.get(currentIndex + i)) != 0) {
                    failed = true;
                }
            }
    
            if (failed) {
                knockoutFoul++;
            }
    
            currentIndex += Math.min(duration, actions.size() - currentIndex);
        }
    
        public static int extractSpeed(String action) {
            if (action.endsWith("<") || action.endsWith(">")) {
                return Integer.parseInt(action.substring(0, action.length() - 1));
            }
            return Integer.parseInt(action);
        }
    }
    
    • import java.util.Arrays;
    • import java.util.List;
    • public class DrivingTestEvaluator {
    • static int knockoutFoul;
    • static int mildFoul;
    • static List<String> actions;
    • static int currentIndex;
    • public static boolean evaluate(String exam, String road) {
    • knockoutFoul = 0;
    • mildFoul = 0;
    • mildFoul = 0;
    • currentIndex = 0;
    • actions = Arrays.asList(exam.trim().split("\\s+"));
    • List<String> rules = Arrays.asList(road.trim().split("\\s+"));
    • for (String rule : rules) {
    • if (rule.startsWith("SL")) {
    • comprobateSpeedLimit(rule);
    • } else if (rule.startsWith("STOP")) {
    • comprobateStop(rule);
    • } else if (rule.startsWith("YIELD")) {
    • comprobateYield(rule);
    • } else if (rule.startsWith("TURN")) {
    • comprobateTurn(rule);
    • } else if (rule.startsWith("R")) {
    • comprobateRedLight(rule);
    • }
    • if (knockoutFoul > 0) return false;
    • }
    • return mildFoul < 3;
    • }
    • public static void comprobateSpeedLimit(String rule) {
    • String[] parts = rule.substring(2).split("_");
    • int speedLimit = Integer.parseInt(parts[0]);
    • int duration = Integer.parseInt(parts[1]);
    • int overLimitCounter = 0;
    • boolean minorCounted = false;
    • for (int i = 0; i < duration && currentIndex + i < actions.size(); i++) {
    • int speed = extractSpeed(actions.get(currentIndex + i));
    • if (speed > speedLimit + 10) {
    • knockoutFoul++;
    • return;
    • }
    • if (speed > speedLimit) {
    • overLimitCounter++;
    • } else {
    • overLimitCounter = 0;
    • }
    • if (overLimitCounter >= 3 && !minorCounted) {
    • mildFoul++;
    • minorCounted = true;
    • }
    • }
    • currentIndex += Math.min(duration, actions.size() - currentIndex);
    • }
    • public static void comprobateStop(String rule) {
    • int cars = rule.length() > 4 ? Integer.parseInt(rule.substring(4)) : 0;
    • int requiredStop = 3 + (2 * cars);
    • int stopCount = 0;
    • while (currentIndex < actions.size() && extractSpeed(actions.get(currentIndex)) == 0) {
    • stopCount++;
    • currentIndex++;
    • }
    • if (stopCount == 0) {
    • knockoutFoul++;
    • } else if (stopCount < requiredStop) {
    • if (stopCount >= 2 * cars) mildFoul++;
    • else knockoutFoul++;
    • }
    • }
    • public static void comprobateYield(String rule) {
    • int cars = rule.length() > 5 ? Integer.parseInt(rule.substring(5)) : 0;
    • int requiredStop = 2 * cars;
    • int stopCount = 0;
    • while (currentIndex < actions.size() && extractSpeed(actions.get(currentIndex)) == 0) {
    • stopCount++;
    • currentIndex++;
    • }
    • if (cars == 0) {
    • if (stopCount >= 2) knockoutFoul++;
    • } else {
    • if (stopCount < requiredStop) {
    • knockoutFoul++;
    • } else if (stopCount < requiredStop + 3) {
    • mildFoul++;
    • }
    • }
    • }
    • public static void comprobateTurn(String rule) {
    • String requiredDirection = rule.equals("TURNR") ? ">" : "<";
    • boolean turned = false;
    • for (int i = currentIndex; i < actions.size(); i++) {
    • if (actions.get(i).endsWith(requiredDirection)) {
    • turned = true;
    • currentIndex = i + 1;
    • break;
    • }
    • }
    • if (!turned) {
    • mildFoul++;
    • }
    • }
    • public static void comprobateRedLight(String rule) {
    • int duration = Integer.parseInt(rule.substring(1));
    • boolean failed = false;
    • for (int i = 0; i < duration && currentIndex + i < actions.size(); i++) {
    • if (extractSpeed(actions.get(currentIndex + i)) != 0) {
    • failed = true;
    • }
    • }
    • if (failed) {
    • knockoutFoul++;
    • }
    • currentIndex += Math.min(duration, actions.size() - currentIndex);
    • }
    • public static int extractSpeed(String action) {
    • if (action.endsWith("<") || action.endsWith(">")) {
    • return Integer.parseInt(action.substring(0, action.length() - 1));
    • }
    • return Integer.parseInt(action);
    • }

You work as a driving test examiner in an alien planet. Your task is to evaluate whether an examinee has passed the exam based on the exam data you receive and the rules described below.

You receive the exam data in two Strings, the first one represents all the indications the driver has received during the exam, from road signals and the examiner. The second String represents the actions of the examinee which are registered every second from the start to the end of the exam.

The format of the strings is the following:

indications: String of symbols separated by " " which represent one indication each following the following legend.

Indication Symbol Expected Behaviour
STOP STOP -> No cars passing by
STOP3 -> 3 cars passing by
Stop at least 3 seconds + 2 seconds for each passing car
YIELD YIELD -> No cars passing by
YIELD2 -> 2 cars passing by
Stop ONLY if there are cars passing by (2 seconds/car)
SPEED LIMIT SL50_100 -> Sets a speed limit of 50 for the next 100 seconds
SL35_60 -> Sets a speed limit of 35 for the next 60 seconds
Don't go over the set speed limit
TURN TURNL -> Turn left
TURNR -> Turn right
Turn as indicated
Red light R3 -> Red light for 3 seconds
R20 -> Red light for 20 seconds
Stop for the given amount of time

actions: String of symbols separated by " " which contain the speed of the vehicle and the turn, if any, taken each second of the exam. Turns are represented with "<" (left) and ">" (right).

Input example:

indications = "SL30_5 YIELD2 SL25_40 R8 YIELD TURNR STOP "
actions = "29 15 0 0 0 0 25 28 35 24 0 0 0 0 0 0 0 0 13 24 35 38> 35 37 36 24 12 0 0 0"

The Rules

  • There are minor and eliminatory infractions. Three minor infractions or one eliminatory infraction will disqualify the examinee.
  • As the information you received is incomplete (there is no way to know when each of the indications were encountered) you must assume the examinee does the correct thing UNLESS there is no other possibility. For example:
    Infractions
    | Minor Infraction | Description |
    |---|---|
    | Speed limit | Examinee drives over the speed limit for three consecutive seconds. |
    | Insufficient stop time (no cars) | Examinee stops at STOP signal but does so for less than three seconds (no cars passing by). |
    | Insufficient stop time (cars) | Examinee waits the necessary time for all cars to pass by but does not wait or waits partially the mandatory 3 seconds. |
    | Not turning | Examinee does not turn when indicated. |

Eliminatory Infraction Description
Unnecessary stopping Examinee stops for no reason at all.
Running a red light Examinee doesn't stop or starts moving before a red light turns green.
Ignoring STOP Examinee doesn't stop at all at a STOP sign.
Running into traffic. Examinee doesn't wait the necessary time at a STOP or yield sign for other cars to pass by.
Reckless driving Examinee goes over the speed limit for over 10 speed units at any given time.

All inputs will be valid so no validation is required.
You must return true if the examinee has passed the exam and false if they haven't.

Code
Diff
  • public class DrivingTestEvaluator{
      public static boolean evaluate(String road, String exam){
        //your code heree
    
        return true;
        }
    }
    • public class DrivingTestEvaluator{
    • public static boolean evaluate(String road, String exam){
    • //your code here
    • //your code heree
    • return true;
    • }
    • }

You work as a driving test examiner in an alien planet. Your task is to evaluate whether an examinee has passed the exam based on the exam data you receive and the rules described below.

public class DrivingTestEvaluator{
  public static boolean evaluate(String road, String exam){
    //your code here

    return true;
    }
}