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 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 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

  • Each second records speed.
  • 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 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
Ignored STOP Not stopping at a STOP sign
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
  • package cinco_kyu;
    
    
    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;
    
    public 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;
        }
    
    
    }
    
    • package cinco_kyu;
    • import java.util.ArrayList;
    • 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;
    • public 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;
    • }
    • public record Indication(int t, String type, int val) { }
    • public record Action(int spd, boolean left, boolean right) { }
    • public record Step(int time, Indication ind, Action act) { }
    • enum WaitType {
    • NONE, STOP, YIELD, REDLIGHT
    • }
    • static class State {
    • int speedLimit = Integer.MAX_VALUE;
    • int minor = 0;
    • int overSpeedStreak = 0;
    • WaitType waitType = WaitType.NONE;
    • int waitUntil = 0;
    • int waitVal = 0;
    • }
    • public static boolean evaluate(String exam, String road) {
    • List<Indication> indications = parseIndications(exam);
    • List<Action> actions = parseActions(road);
    • Map<Integer, Indication> indMap = new HashMap<>();
    • for (Indication i : indications) {
    • indMap.put(i.t(), i);
    • }
    • List<Step> steps = new ArrayList<>();
    • for (int i = 0; i < actions.size(); i++) {
    • int time = i + 1;
    • Indication ind = indMap.get(time);
    • steps.add(new Step(time, ind, actions.get(i)));
    • }
    • State st = new State();
    • for (Step s : steps) {
    • Indication ind = s.ind();
    • Action act = s.act();
    • if (ind != null) {
    • switch (ind.type()) {
    • case "SL" -> st.speedLimit = ind.val();
    • case "STOP" -> {
    • if (act.spd() > 0) return false;
    • st.waitType = WaitType.STOP;
    • st.waitVal = ind.val();
    • st.waitUntil = s.time() + 3 + 2 * ind.val() - 1;
    • }
    • case "YIELD" -> {
    • if (ind.val() > 0) {
    • if (act.spd() > 0) return false;
    • st.waitType = WaitType.YIELD;
    • st.waitVal = ind.val();
    • st.waitUntil = s.time() + 2 * ind.val() - 1;
    • }
    • }
    • case "REDLIGHT" -> {
    • if (act.spd() > 0) return false;
    • st.waitType = WaitType.REDLIGHT;
    • st.waitVal = ind.val();
    • st.waitUntil = s.time() + ind.val() - 1;
    • }
    • case "TURNL" -> {
    • if (!act.left()) {
    • st.minor++;
    • if (st.minor >= 3) return false;
    • }
    • }
    • case "TURNR" -> {
    • if (!act.right()) {
    • st.minor++;
    • if (st.minor >= 3) return false;
    • }
    • }
    • }
    • }
    • if (st.waitType != WaitType.NONE) {
    • if (s.time() <= st.waitUntil) {
    • if (act.spd() > 0) {
    • if (st.waitType == WaitType.STOP) {
    • if (st.waitVal > 0) return false;
    • else {
    • st.minor++;
    • if (st.minor >= 3) return false;
    • }
    • } else {
    • return false;
    • }
    • st.waitType = WaitType.NONE;
    • }
    • } else {
    • if (act.spd() == 0) return false;
    • st.waitType = WaitType.NONE;
    • }
    • }
    • 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));
    • }
    • if (act.spd() > st.speedLimit) {
    • if (act.spd() > st.speedLimit + 10) return false;
    • st.overSpeedStreak++;
    • if (st.overSpeedStreak == 3) {
    • st.overSpeedStreak = 0;
    • st.minor++;
    • if (st.minor >= 3) return false;
    • }
    • } else {
    • st.overSpeedStreak = 0;
    • }
    • if (act.spd() == 0 && st.waitType == WaitType.NONE) return false;
    • 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));
    • }
    • }
    • if (st.waitType != WaitType.NONE) {
    • if (st.waitType == WaitType.STOP) {
    • if (st.waitVal == 0) {
    • st.minor++;
    • if (st.minor >= 3) return false;
    • } else if (st.waitVal > 0) return false;
    • } else return false;
    • }
    • return st.minor < 3;
    • }
    • private static List<Indication> parseIndications(String exam) {
    • List<Indication> list = new ArrayList<>();
    • Pattern pattern = Pattern.compile("t=(\\d+)\\s+([A-Z]+)(\\d*)");
    • String[] parts = exam.split(";");
    • for (String s : parts) {
    • s = s.trim();
    • Matcher matcher = pattern.matcher(s);
    • if (matcher.find()) {
    • int t = Integer.parseInt(matcher.group(1));
    • String type = matcher.group(2);
    • int val = matcher.group(3).isEmpty() ? 0 : Integer.parseInt(matcher.group(3));
    • list.add(new Indication(t, type, val));
    • 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--;
    • }
    • return list;
    • }
    • private static List<Action> parseActions(String road) {
    • List<Action> actions = new ArrayList<>();
    • String[] tokens = road.trim().split("\\s+");
    • for (String s : tokens) {
    • int spd = Integer.parseInt(s.replaceAll("[<>]", ""));
    • boolean left = s.endsWith("<");
    • boolean right = s.endsWith(">");
    • actions.add(new Action(spd, left, right));
    • 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));
    • }
    • return actions;
    • indexLastSpeedLimit = time - 1;
    • }
    • }
    • private static void clearState() {
    • speedLimit = 0;
    • indexLastSpeedLimit = 1;
    • indexIndicationList = 0;
    • indexActionList = 0;
    • minorMistakes = 0;
    • isEliminated = false;
    • currentTime = 0;
    • secondsInfringement = 0;
    • }
    • }
Code
Diff
  • package cinco_kyu;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class DrivingTestEvaluator {
    
        public record Indication(int t, String type, int val) { }
        public record Action(int spd, boolean left, boolean right) { }
        public record Step(int time, Indication ind, Action act) { }
    
        enum WaitType {
            NONE, STOP, YIELD, REDLIGHT
        }
    
        static class State {
            int speedLimit = Integer.MAX_VALUE;
            int minor = 0;
            int overSpeedStreak = 0;
            WaitType waitType = WaitType.NONE;
            int waitUntil = 0;
            int waitVal = 0;
        }
    
        public static boolean evaluate(String exam, String road) {
            List<Indication> indications = parseIndications(exam);
            List<Action> actions = parseActions(road);
    
            Map<Integer, Indication> indMap = new HashMap<>();
            for (Indication i : indications) {
                indMap.put(i.t(), i);
            }
    
            List<Step> steps = new ArrayList<>();
            for (int i = 0; i < actions.size(); i++) {
                int time = i + 1;
                Indication ind = indMap.get(time);
                steps.add(new Step(time, ind, actions.get(i)));
            }
    
            State st = new State();
    
            for (Step s : steps) {
                Indication ind = s.ind();
                Action act = s.act();
    
                if (ind != null) {
                    switch (ind.type()) {
                        case "SL" -> st.speedLimit = ind.val();
                        case "STOP" -> {
                            if (act.spd() > 0) return false;
                            st.waitType = WaitType.STOP;
                            st.waitVal = ind.val();
                            st.waitUntil = s.time() + 3 + 2 * ind.val() - 1;
                        }
                        case "YIELD" -> {
                            if (ind.val() > 0) {
                                if (act.spd() > 0) return false;
                                st.waitType = WaitType.YIELD;
                                st.waitVal = ind.val();
                                st.waitUntil = s.time() + 2 * ind.val() - 1;
                            }
                        }
                        case "REDLIGHT" -> {
                            if (act.spd() > 0) return false;
                            st.waitType = WaitType.REDLIGHT;
                            st.waitVal = ind.val();
                            st.waitUntil = s.time() + ind.val() - 1;
                        }
                        case "TURNL" -> {
                            if (!act.left()) {
                                st.minor++;
                                if (st.minor >= 3) return false;
                            }
                        }
                        case "TURNR" -> {
                            if (!act.right()) {
                                st.minor++;
                                if (st.minor >= 3) return false;
                            }
                        }
                    }
                }
    
                if (st.waitType != WaitType.NONE) {
                    if (s.time() <= st.waitUntil) {
                        if (act.spd() > 0) {
                            if (st.waitType == WaitType.STOP) {
                                if (st.waitVal > 0) return false;
                                else {
                                    st.minor++;
                                    if (st.minor >= 3) return false;
                                }
                            } else {
                                return false;
                            }
                            st.waitType = WaitType.NONE;
                        }
                    } else {
                        if (act.spd() == 0) return false;
                        st.waitType = WaitType.NONE;
                    }
                }
    
    
                if (act.spd() > st.speedLimit) {
                    if (act.spd() > st.speedLimit + 10) return false;
                    st.overSpeedStreak++;
                    if (st.overSpeedStreak == 3) {
                        st.overSpeedStreak = 0;
                        st.minor++;
                        if (st.minor >= 3) return false;
                    }
                } else {
                    st.overSpeedStreak = 0;
                }
    
                if (act.spd() == 0 && st.waitType == WaitType.NONE) return false;
            }
    
            if (st.waitType != WaitType.NONE) {
                if (st.waitType == WaitType.STOP) {
                    if (st.waitVal == 0) {
                        st.minor++;
                        if (st.minor >= 3) return false;
                    } else if (st.waitVal > 0) return false;
                } else return false;
            }
            return st.minor < 3;
        }
    
        private static List<Indication> parseIndications(String exam) {
            List<Indication> list = new ArrayList<>();
            Pattern pattern = Pattern.compile("t=(\\d+)\\s+([A-Z]+)(\\d*)");
            String[] parts = exam.split(";");
            for (String s : parts) {
                s = s.trim();
                Matcher matcher = pattern.matcher(s);
                if (matcher.find()) {
                    int t = Integer.parseInt(matcher.group(1));
                    String type = matcher.group(2);
                    int val = matcher.group(3).isEmpty() ? 0 : Integer.parseInt(matcher.group(3));
                    list.add(new Indication(t, type, val));
                }
            }
            return list;
        }
    
        private static List<Action> parseActions(String road) {
            List<Action> actions = new ArrayList<>();
            String[] tokens = road.trim().split("\\s+");
            for (String s : tokens) {
                int spd = Integer.parseInt(s.replaceAll("[<>]", ""));
                boolean left = s.endsWith("<");
                boolean right = s.endsWith(">");
                actions.add(new Action(spd, left, right));
            }
            return actions;
        }
    }
    • package cinco_kyu;
    • import java.util.*;
    • import java.util.function.Consumer;
    • import java.util.ArrayList;
    • import java.util.HashMap;
    • import java.util.List;
    • import java.util.Map;
    • import java.util.regex.Matcher;
    • import java.util.regex.Pattern;
    • public class DrivingTestEvaluator {
    • static Map<String, Consumer> rules = new HashMap();
    • static int maxVelocity;
    • static int indexExam;
    • static int seconds = 0;
    • static List<String> examList;
    • static int minorInfractions = 0;
    • public Map<String,String> evaluate(String indications, String exam) {
    • int index = 0;
    • refillRules();
    • String[] indicationArray = indications.split(" ");
    • examList = Arrays.stream(exam.split(" ")).toList();
    • for (String step : indicationArray) {
    • validateStep(step);
    • }
    • return Collections.singletonMap("","");
    • public record Indication(int t, String type, int val) { }
    • public record Action(int spd, boolean left, boolean right) { }
    • public record Step(int time, Indication ind, Action act) { }
    • enum WaitType {
    • NONE, STOP, YIELD, REDLIGHT
    • }
    • private static void validateStep(String step) {
    • rules.keySet().stream().filter(step::contains).findFirst().ifPresent(key -> rules.get(key).accept(step));
    • static class State {
    • int speedLimit = Integer.MAX_VALUE;
    • int minor = 0;
    • int overSpeedStreak = 0;
    • WaitType waitType = WaitType.NONE;
    • int waitUntil = 0;
    • int waitVal = 0;
    • }
    • private void speedSituation(String velocity) {
    • Pattern pattern = Pattern.compile("\\d+");
    • Matcher matcher = pattern.matcher(velocity);
    • if (matcher.find()) {
    • maxVelocity = Integer.parseInt(matcher.group(1));
    • public static boolean evaluate(String exam, String road) {
    • List<Indication> indications = parseIndications(exam);
    • List<Action> actions = parseActions(road);
    • Map<Integer, Indication> indMap = new HashMap<>();
    • for (Indication i : indications) {
    • indMap.put(i.t(), i);
    • }
    • }
    • private void stopSituation(String stop) {
    • processStopLikeSituation(stop, 3);
    • }
    • List<Step> steps = new ArrayList<>();
    • for (int i = 0; i < actions.size(); i++) {
    • int time = i + 1;
    • Indication ind = indMap.get(time);
    • steps.add(new Step(time, ind, actions.get(i)));
    • }
    • private void yieldSituation(String yield) {
    • processStopLikeSituation(yield, 0);
    • }
    • State st = new State();
    • private void redLightSituation(String redLight) {
    • processStopLikeSituation(redLight, 0);
    • }
    • private void turnSituation(String turn) {
    • boolean exit = false;
    • boolean isRight = false;
    • try {
    • while (!exit) {
    • validSpeed();
    • String action = examList.get(indexExam);
    • if (action.length()==3) {
    • isRight = validateTurnRigth(action);
    • if (!isRight && turn.endsWith("R") || isRight && turn.endsWith("L")) minorInfractions++;
    • exit = true;
    • for (Step s : steps) {
    • Indication ind = s.ind();
    • Action act = s.act();
    • if (ind != null) {
    • switch (ind.type()) {
    • case "SL" -> st.speedLimit = ind.val();
    • case "STOP" -> {
    • if (act.spd() > 0) return false;
    • st.waitType = WaitType.STOP;
    • st.waitVal = ind.val();
    • st.waitUntil = s.time() + 3 + 2 * ind.val() - 1;
    • }
    • case "YIELD" -> {
    • if (ind.val() > 0) {
    • if (act.spd() > 0) return false;
    • st.waitType = WaitType.YIELD;
    • st.waitVal = ind.val();
    • st.waitUntil = s.time() + 2 * ind.val() - 1;
    • }
    • }
    • case "REDLIGHT" -> {
    • if (act.spd() > 0) return false;
    • st.waitType = WaitType.REDLIGHT;
    • st.waitVal = ind.val();
    • st.waitUntil = s.time() + ind.val() - 1;
    • }
    • case "TURNL" -> {
    • if (!act.left()) {
    • st.minor++;
    • if (st.minor >= 3) return false;
    • }
    • }
    • case "TURNR" -> {
    • if (!act.right()) {
    • st.minor++;
    • if (st.minor >= 3) return false;
    • }
    • }
    • if (examList.get(indexExam).equals("0")) break;
    • indexExam++;
    • }
    • } catch (ExamFailedException e) {
    • throw e;
    • }
    • }
    • private boolean validateTurnRigth(String action) {
    • return action.endsWith(">");
    • }
    • private void processStopLikeSituation(String input, int baseSeconds) {
    • boolean exit = false;
    • int secondsToStop = baseSeconds;
    • Matcher matcher = Pattern.compile("\\d+").matcher(input);
    • if (!input.contains("REDLIGHT") && matcher.find()) {
    • secondsToStop += 2 * Integer.parseInt(matcher.group());
    • }else if(matcher.find()){
    • secondsToStop = Integer.parseInt(matcher.group());
    • }
    • try {
    • while (!exit) {
    • validSpeed();
    • String action = examList.get(indexExam);
    • if (action.length() > 3) throw new ExamFailedException();
    • if (action.length() == 1) exit = hasStoppedCorrectly(secondsToStop);
    • indexExam++;
    • if (st.waitType != WaitType.NONE) {
    • if (s.time() <= st.waitUntil) {
    • if (act.spd() > 0) {
    • if (st.waitType == WaitType.STOP) {
    • if (st.waitVal > 0) return false;
    • else {
    • st.minor++;
    • if (st.minor >= 3) return false;
    • }
    • } else {
    • return false;
    • }
    • st.waitType = WaitType.NONE;
    • }
    • } else {
    • if (act.spd() == 0) return false;
    • st.waitType = WaitType.NONE;
    • }
    • }
    • } catch (ExamFailedException e) {
    • throw e;
    • }
    • }
    • private boolean hasStoppedCorrectly(int seconsToStop) {
    • boolean exit = false;
    • while (!exit) {
    • if (examList.get(indexExam).length() < 3 && Integer.parseInt(examList.get(indexExam)) == 0) {
    • seconsToStop--;
    • } else {
    • if (seconsToStop != 0) {
    • throw new ExamFailedException();
    • if (act.spd() > st.speedLimit) {
    • if (act.spd() > st.speedLimit + 10) return false;
    • st.overSpeedStreak++;
    • if (st.overSpeedStreak == 3) {
    • st.overSpeedStreak = 0;
    • st.minor++;
    • if (st.minor >= 3) return false;
    • }
    • exit = true;
    • } else {
    • st.overSpeedStreak = 0;
    • }
    • indexExam++;
    • }
    • return true;
    • }
    • private void validSpeed() {
    • Pattern pattern = Pattern.compile("^\\d+");
    • Matcher matcher = pattern.matcher(examList.get(indexExam));
    • if (Integer.parseInt(matcher.group(1)) > maxVelocity) {
    • seconds++;
    • } else {
    • seconds = 0;
    • if (act.spd() == 0 && st.waitType == WaitType.NONE) return false;
    • }
    • if (seconds > 2) minorInfractions++;
    • if (Integer.parseInt(matcher.group(1)) > maxVelocity + 10) throw new ExamFailedException();
    • }
    • private static void refillRules() {
    • if (st.waitType != WaitType.NONE) {
    • if (st.waitType == WaitType.STOP) {
    • if (st.waitVal == 0) {
    • st.minor++;
    • if (st.minor >= 3) return false;
    • } else if (st.waitVal > 0) return false;
    • } else return false;
    • }
    • return st.minor < 3;
    • }
    • private static List<Indication> parseIndications(String exam) {
    • List<Indication> list = new ArrayList<>();
    • Pattern pattern = Pattern.compile("t=(\\d+)\\s+([A-Z]+)(\\d*)");
    • String[] parts = exam.split(";");
    • for (String s : parts) {
    • s = s.trim();
    • Matcher matcher = pattern.matcher(s);
    • if (matcher.find()) {
    • int t = Integer.parseInt(matcher.group(1));
    • String type = matcher.group(2);
    • int val = matcher.group(3).isEmpty() ? 0 : Integer.parseInt(matcher.group(3));
    • list.add(new Indication(t, type, val));
    • }
    • }
    • return list;
    • }
    • static class ExamFailedException extends RuntimeException {
    • public ExamFailedException() {
    • super("Examen suspenso");
    • private static List<Action> parseActions(String road) {
    • List<Action> actions = new ArrayList<>();
    • String[] tokens = road.trim().split("\\s+");
    • for (String s : tokens) {
    • int spd = Integer.parseInt(s.replaceAll("[<>]", ""));
    • boolean left = s.endsWith("<");
    • boolean right = s.endsWith(">");
    • actions.add(new Action(spd, left, right));
    • }
    • return actions;
    • }
Code
Diff
  • package cinco_kyu;
    
    import java.util.*;
    import java.util.function.Consumer;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class DrivingTestEvaluator {
        static Map<String, Consumer> rules = new HashMap();
        static int maxVelocity;
        static int indexExam;
        static int seconds = 0;
        static List<String> examList;
        static int minorInfractions = 0;
    
        public Map<String,String>  evaluate(String indications, String exam) {
            int index = 0;
            refillRules();
            String[] indicationArray = indications.split(" ");
            examList = Arrays.stream(exam.split(" ")).toList();
            for (String step : indicationArray) {
                validateStep(step);
            }
            return Collections.singletonMap("","");
        }
    
        private static void validateStep(String step) {
            rules.keySet().stream().filter(step::contains).findFirst().ifPresent(key -> rules.get(key).accept(step));
        }
    
        private void speedSituation(String velocity) {
            Pattern pattern = Pattern.compile("\\d+");
            Matcher matcher = pattern.matcher(velocity);
            if (matcher.find()) {
                maxVelocity = Integer.parseInt(matcher.group(1));
            }
        }
    
        private void stopSituation(String stop) {
            processStopLikeSituation(stop, 3);
        }
    
        private void yieldSituation(String yield) {
            processStopLikeSituation(yield, 0);
        }
    
        private void redLightSituation(String redLight) {
            processStopLikeSituation(redLight, 0);
        }
        private void turnSituation(String turn) {
            boolean exit = false;
            boolean isRight = false;
    
    
                try {
                    while (!exit) {
                        validSpeed();
                        String action = examList.get(indexExam);
                        if (action.length()==3) {
                            isRight =  validateTurnRigth(action);
                            if (!isRight &&  turn.endsWith("R") || isRight &&  turn.endsWith("L")) minorInfractions++;
                            exit = true;
                        }
                        if (examList.get(indexExam).equals("0")) break;
                        indexExam++;
                    }
                } catch (ExamFailedException e) {
                    throw e;
                }
    
        }
    
        private boolean validateTurnRigth(String action) {
            return action.endsWith(">");
        }
    
    
        private void processStopLikeSituation(String input, int baseSeconds) {
            boolean exit = false;
            int secondsToStop = baseSeconds;
    
            Matcher matcher = Pattern.compile("\\d+").matcher(input);
            if (!input.contains("REDLIGHT") && matcher.find()) {
                secondsToStop += 2 * Integer.parseInt(matcher.group());
            }else if(matcher.find()){
                secondsToStop = Integer.parseInt(matcher.group());
            }
    
            try {
                while (!exit) {
                    validSpeed();
                    String action = examList.get(indexExam);
                    if (action.length() > 3) throw new ExamFailedException();
                    if (action.length() == 1) exit = hasStoppedCorrectly(secondsToStop);
                    indexExam++;
                }
            } catch (ExamFailedException e) {
                throw e;
            }
        }
    
    
        private boolean hasStoppedCorrectly(int seconsToStop) {
            boolean exit = false;
            while (!exit) {
                if (examList.get(indexExam).length() < 3 && Integer.parseInt(examList.get(indexExam)) == 0) {
                    seconsToStop--;
                } else {
                    if (seconsToStop != 0) {
                        throw new ExamFailedException();
                    }
                    exit = true;
                }
                indexExam++;
            }
            return true;
        }
    
        private void validSpeed() {
            Pattern pattern = Pattern.compile("^\\d+");
            Matcher matcher = pattern.matcher(examList.get(indexExam));
            if (Integer.parseInt(matcher.group(1)) > maxVelocity) {
                seconds++;
            } else {
                seconds = 0;
            }
            if (seconds > 2) minorInfractions++;
            if (Integer.parseInt(matcher.group(1)) > maxVelocity + 10) throw new ExamFailedException();
        }
    
        private static void refillRules() {
    
        }
    
        static class ExamFailedException extends RuntimeException {
            public ExamFailedException() {
                super("Examen suspenso");
            }
        }
    }
    
    • public class DrivingTestEvaluator{
    • public static boolean evaluate(String road, String exam){
    • //your code heree
    • package cinco_kyu;
    • return true;
    • import java.util.*;
    • import java.util.function.Consumer;
    • import java.util.regex.Matcher;
    • import java.util.regex.Pattern;
    • public class DrivingTestEvaluator {
    • static Map<String, Consumer> rules = new HashMap();
    • static int maxVelocity;
    • static int indexExam;
    • static int seconds = 0;
    • static List<String> examList;
    • static int minorInfractions = 0;
    • public Map<String,String> evaluate(String indications, String exam) {
    • int index = 0;
    • refillRules();
    • String[] indicationArray = indications.split(" ");
    • examList = Arrays.stream(exam.split(" ")).toList();
    • for (String step : indicationArray) {
    • validateStep(step);
    • }
    • return Collections.singletonMap("","");
    • }
    • private static void validateStep(String step) {
    • rules.keySet().stream().filter(step::contains).findFirst().ifPresent(key -> rules.get(key).accept(step));
    • }
    • private void speedSituation(String velocity) {
    • Pattern pattern = Pattern.compile("\\d+");
    • Matcher matcher = pattern.matcher(velocity);
    • if (matcher.find()) {
    • maxVelocity = Integer.parseInt(matcher.group(1));
    • }
    • }
    • private void stopSituation(String stop) {
    • processStopLikeSituation(stop, 3);
    • }
    • private void yieldSituation(String yield) {
    • processStopLikeSituation(yield, 0);
    • }
    • private void redLightSituation(String redLight) {
    • processStopLikeSituation(redLight, 0);
    • }
    • private void turnSituation(String turn) {
    • boolean exit = false;
    • boolean isRight = false;
    • try {
    • while (!exit) {
    • validSpeed();
    • String action = examList.get(indexExam);
    • if (action.length()==3) {
    • isRight = validateTurnRigth(action);
    • if (!isRight && turn.endsWith("R") || isRight && turn.endsWith("L")) minorInfractions++;
    • exit = true;
    • }
    • if (examList.get(indexExam).equals("0")) break;
    • indexExam++;
    • }
    • } catch (ExamFailedException e) {
    • throw e;
    • }
    • }
    • private boolean validateTurnRigth(String action) {
    • return action.endsWith(">");
    • }
    • private void processStopLikeSituation(String input, int baseSeconds) {
    • boolean exit = false;
    • int secondsToStop = baseSeconds;
    • Matcher matcher = Pattern.compile("\\d+").matcher(input);
    • if (!input.contains("REDLIGHT") && matcher.find()) {
    • secondsToStop += 2 * Integer.parseInt(matcher.group());
    • }else if(matcher.find()){
    • secondsToStop = Integer.parseInt(matcher.group());
    • }
    • try {
    • while (!exit) {
    • validSpeed();
    • String action = examList.get(indexExam);
    • if (action.length() > 3) throw new ExamFailedException();
    • if (action.length() == 1) exit = hasStoppedCorrectly(secondsToStop);
    • indexExam++;
    • }
    • } catch (ExamFailedException e) {
    • throw e;
    • }
    • }
    • private boolean hasStoppedCorrectly(int seconsToStop) {
    • boolean exit = false;
    • while (!exit) {
    • if (examList.get(indexExam).length() < 3 && Integer.parseInt(examList.get(indexExam)) == 0) {
    • seconsToStop--;
    • } else {
    • if (seconsToStop != 0) {
    • throw new ExamFailedException();
    • }
    • exit = true;
    • }
    • indexExam++;
    • }
    • return true;
    • }
    • private void validSpeed() {
    • Pattern pattern = Pattern.compile("^\\d+");
    • Matcher matcher = pattern.matcher(examList.get(indexExam));
    • if (Integer.parseInt(matcher.group(1)) > maxVelocity) {
    • seconds++;
    • } else {
    • seconds = 0;
    • }
    • if (seconds > 2) minorInfractions++;
    • if (Integer.parseInt(matcher.group(1)) > maxVelocity + 10) throw new ExamFailedException();
    • }
    • private static void refillRules() {
    • }
    • static class ExamFailedException extends RuntimeException {
    • public ExamFailedException() {
    • super("Examen suspenso");
    • }
    • }