Machine Coding Problem

Online Judge (LeetCode-lite)

maco60macoAlleducationsandbox-strategyobserver-patternthread-safe-judge-poolleaderboard-aggregation
Commonly Asked By:GoogleMicrosoftHackerRank

Functional Scope (In-Scope)

  • Sandbox Execution Strategies (Strategy Pattern): Dynamic code evaluation matching code dialects (Python, Java) via clean sandbox interfaces.
  • Aggregate Test Case Evaluation: Evaluate sandboxed stdout/stderr output against expected outcomes, yielding AC, WA, TLE, or RE results.
  • Asynchronous Execution Worker Pools: Offload judge tasks asynchronously using multi-threaded pools to prevent main-thread blockages.
  • Leaderboard & Stats Pipelines (Observer Pattern): Push real-time stats updates and award points upon successful execution.

Explicit Boundaries (Out-of-Scope)

  • No Automatic Anti-Plagiarism Scanner: Bypasses complex lexical analysis matching structural tokens or abstract syntax trees (ASTs).
  • No Advanced Peer Review Forum: Out-of-scope to build social commenting forums or collaborative code reviews.

Clean reference designs demonstrating sandbox runner abstractions in Java and Python:

// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;

enum JudgeResult { AC, WA, TLE, MLE, RE }

class TestCase {
    private final String input;
    private final String expectedOutput;

    public TestCase(String input, String expectedOutput) {
        this.input = input;
        this.expectedOutput = expectedOutput;
    }

    public String getInput() { return input; }
    public String getExpectedOutput() { return expectedOutput; }
}

class Problem {
    private final String id;
    private final String title;
    private final List<TestCase> testCases;
    private final long timeLimitMs;

    public Problem(String id, String title, List<TestCase> testCases, long timeLimitMs) {
        this.id = id;
        this.title = title;
        this.testCases = testCases;
        this.timeLimitMs = timeLimitMs;
    }

    public String getId() { return id; }
    public String getTitle() { return title; }
    public List<TestCase> getTestCases() { return testCases; }
    public long getTimeLimitMs() { return timeLimitMs; }
}

class ExecutionResult {
    private final String output;
    private final boolean isSuccess;
    private final long timeUsedMs;

    public ExecutionResult(String output, boolean isSuccess, long timeUsedMs) {
        this.output = output;
        this.isSuccess = isSuccess;
        this.timeUsedMs = timeUsedMs;
    }

    public String getOutput() { return output; }
    public boolean isSuccess() { return isSuccess; }
    public long getTimeUsedMs() { return timeUsedMs; }
}

// ─── STRATEGY PATTERN (SANDBOX EXECUTOR) ─────────────────────────────────────
interface CodeRunner {
    ExecutionResult execute(String code, String input, long timeoutMs);
}

class PythonRunner implements CodeRunner {
    @Override
    public ExecutionResult execute(String code, String input, long timeoutMs) {
        if (code.contains("syntax_error")) {
            return new ExecutionResult("SyntaxError: invalid syntax", false, 10);
        }
        if (code.contains("infinite_loop")) {
            return new ExecutionResult("Timeout", false, timeoutMs + 50);
        }
        // Simulating matching output
        return new ExecutionResult(input.trim(), true, 45);
    }
}

class JavaRunner implements CodeRunner {
    @Override
    public ExecutionResult execute(String code, String input, long timeoutMs) {
        if (code.contains("compile_error")) {
            return new ExecutionResult("Compilation failed", false, 5);
        }
        return new ExecutionResult(input.trim(), true, 30);
    }
}

class Submission {
    private final String id;
    private final String userId;
    private final String problemId;
    private final String code;
    private final String language;
    private JudgeResult result = JudgeResult.WA;

    public Submission(String id, String userId, String problemId, String code, String language) {
        this.id = id;
        this.userId = userId;
        this.problemId = problemId;
        this.code = code;
        this.language = language;
    }

    public String getId() { return id; }
    public String getUserId() { return userId; }
    public String getProblemId() { return problemId; }
    public String getCode() { return code; }
    public String getLanguage() { return language; }
    public JudgeResult getResult() { return result; }
    public void setResult(JudgeResult result) { this.result = result; }
}

// ─── OBSERVER PATTERN (LEADERBOARDS & STATS) ─────────────────────────────────
interface SubmissionObserver {
    void onSubmissionJudged(Submission submission);
}

class LeaderboardUpdater implements SubmissionObserver {
    private final Map<String, Integer> userPoints = new ConcurrentHashMap<>();

    @Override
    public void onSubmissionJudged(Submission submission) {
        if (submission.getResult() == JudgeResult.AC) {
            userPoints.merge(submission.getUserId(), 10, Integer::sum);
            System.out.println(String.format("[Leaderboard] User %s scored +10 points! Total: %d", 
                    submission.getUserId(), userPoints.get(submission.getUserId())));
        }
    }
}

class UserStatManager implements SubmissionObserver {
    private final Map<String, Set<String>> userSolvedProblems = new ConcurrentHashMap<>();

    @Override
    public void onSubmissionJudged(Submission submission) {
        if (submission.getResult() == JudgeResult.AC) {
            userSolvedProblems.computeIfAbsent(submission.getUserId(), k -> ConcurrentHashMap.newKeySet())
                    .add(submission.getProblemId());
            System.out.println(String.format("[Stats] User %s has now solved %d unique problem(s).",
                    submission.getUserId(), userSolvedProblems.get(submission.getUserId()).size()));
        }
    }
}

class JudgeEngine {
    private final Map<String, Problem> problems = new ConcurrentHashMap<>();
    private final Map<String, CodeRunner> runners = new ConcurrentHashMap<>();
    private final List<SubmissionObserver> observers = new CopyOnWriteArrayList<>();
    private final ExecutorService evaluationExecutor = Executors.newFixedThreadPool(4);

    public JudgeEngine() {
        runners.put("python", new PythonRunner());
        runners.put("java", new JavaRunner());
    }

    public void addProblem(Problem p) { problems.put(p.getId(), p); }
    public void addObserver(SubmissionObserver obs) { observers.add(obs); }

    public void submit(Submission submission) {
        System.out.println("[JudgeEngine] Submission " + submission.getId() + " queued for execution...");
        evaluationExecutor.submit(() -> evaluate(submission));
    }

    private void evaluate(Submission submission) {
        Problem problem = problems.get(submission.getProblemId());
        CodeRunner runner = runners.get(submission.getLanguage().toLowerCase());

        if (problem == null || runner == null) {
            submission.setResult(JudgeResult.RE);
            notifyObservers(submission);
            return;
        }

        JudgeResult finalResult = JudgeResult.AC;
        for (TestCase tc : problem.getTestCases()) {
            ExecutionResult execRes = runner.execute(submission.getCode(), tc.getInput(), problem.getTimeLimitMs());

            if (!execRes.isSuccess()) {
                if (execRes.getOutput().contains("Timeout")) {
                    finalResult = JudgeResult.TLE;
                } else {
                    finalResult = JudgeResult.RE;
                }
                break;
            }

            if (execRes.getTimeUsedMs() > problem.getTimeLimitMs()) {
                finalResult = JudgeResult.TLE;
                break;
            }

            if (!execRes.getOutput().equals(tc.getExpectedOutput())) {
                finalResult = JudgeResult.WA;
                break;
            }
        }

        submission.setResult(finalResult);
        System.out.println(String.format("[JudgeEngine] Submission %s judged: %s", submission.getId(), finalResult));
        notifyObservers(submission);
    }

    private void notifyObservers(Submission submission) {
        for (SubmissionObserver obs : observers) {
            obs.onSubmissionJudged(submission);
        }
    }

    public void shutdown() {
        evaluationExecutor.shutdown();
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== Online Judge Simulation ===");
        JudgeEngine engine = new JudgeEngine();
        
        LeaderboardUpdater leaderboard = new LeaderboardUpdater();
        UserStatManager stats = new UserStatManager();
        engine.addObserver(leaderboard);
        engine.addObserver(stats);

        List<TestCase> testCases = Arrays.asList(
            new TestCase("2 3", "5"),
            new TestCase("10 20", "30")
        );
        Problem sumProblem = new Problem("PROB-1", "Sum of Two Numbers", testCases, 1000);
        engine.addProblem(sumProblem);

        // Client Submissions
        Submission sub1 = new Submission("SUB-101", "User-A", "PROB-1", "def sum(a,b): return a+b", "python");
        Submission sub2 = new Submission("SUB-102", "User-A", "PROB-1", "while True: pass # infinite_loop", "python");

        engine.submit(sub1);
        engine.submit(sub2);

        Thread.sleep(1000);
        engine.shutdown();
    }
}