File size: 1,846 Bytes
2e818da
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from collections import Counter

from app.schemas.visual_lesson import ArrayAlgorithmSpec
from app.services.array_algorithm_compiler import ArrayAlgorithmCompiler, SEARCH_ALGORITHMS


class ArrayAlgorithmValidationError(ValueError):
    pass


class ArrayAlgorithmValidator:
    def __init__(self, compiler: ArrayAlgorithmCompiler) -> None:
        self.compiler = compiler

    def validate(self, spec: ArrayAlgorithmSpec) -> None:
        if not 2 <= len(spec.input_values) <= 32 or spec.primary_algorithm not in spec.enabled_algorithms:
            raise ArrayAlgorithmValidationError("Array algorithm inputs are invalid")
        if "binary_search" in spec.enabled_algorithms and spec.input_values != sorted(spec.input_values):
            raise ArrayAlgorithmValidationError("Binary search cannot run on an unsorted array")
        claims = {claim.claim_id for claim in spec.evidence_claims}
        if not {"array-sorting", "array-search", "array-binary-precondition"} <= claims:
            raise ArrayAlgorithmValidationError("Array algorithm definitions are missing")
        compiled = self.compiler.compile_spec(spec)
        for branch in compiled.branches:
            if branch.algorithm in SEARCH_ALGORITHMS:
                expected = next((index for index, value in enumerate(spec.input_values) if value == spec.search_target), -1)
                if branch.found_index != expected and not (branch.algorithm == "binary_search" and branch.found_index >= 0 and spec.input_values[branch.found_index] == spec.search_target):
                    raise ArrayAlgorithmValidationError("Search result validation failed")
            elif branch.final_values != sorted(spec.input_values) or Counter(branch.final_values) != Counter(spec.input_values):
                raise ArrayAlgorithmValidationError("Sorting result validation failed")