"""
Brainfuck checker: interprets Brainfuck code and checks if output is "42".

Safe sandboxed interpreter with instruction limit to prevent infinite loops.
"""


def _interpret_bf(code, max_steps=100000):
    """Interpret Brainfuck code and return output string.

    Returns None if execution fails or exceeds step limit.
    """
    # Filter to valid BF instructions only
    valid = set("+-<>.,[]")
    instructions = [ch for ch in code if ch in valid]

    if not instructions:
        return None

    # Pre-compute bracket matching
    brackets = {}
    stack = []
    for i, ch in enumerate(instructions):
        if ch == "[":
            stack.append(i)
        elif ch == "]":
            if not stack:
                return None  # unmatched
            j = stack.pop()
            brackets[j] = i
            brackets[i] = j
    if stack:
        return None  # unmatched

    # Execute
    tape = [0] * 30000
    ptr = 0
    ip = 0
    output = []
    steps = 0

    while ip < len(instructions):
        steps += 1
        if steps > max_steps:
            return None  # too many steps

        ch = instructions[ip]
        if ch == "+":
            tape[ptr] = (tape[ptr] + 1) % 256
        elif ch == "-":
            tape[ptr] = (tape[ptr] - 1) % 256
        elif ch == ">":
            ptr += 1
            if ptr >= len(tape):
                return None
        elif ch == "<":
            ptr -= 1
            if ptr < 0:
                return None
        elif ch == ".":
            output.append(chr(tape[ptr]))
        elif ch == ",":
            tape[ptr] = 0  # no input
        elif ch == "[":
            if tape[ptr] == 0:
                ip = brackets[ip]
        elif ch == "]":
            if tape[ptr] != 0:
                ip = brackets[ip]
        ip += 1

    return "".join(output)


def check(value):
    """Check if value is Brainfuck code that outputs '42'."""
    if not isinstance(value, str):
        return None

    s = value.strip()
    if not s:
        return None

    # Must contain at least some BF instructions
    bf_chars = set("+-<>.,[]")
    bf_count = sum(1 for ch in s if ch in bf_chars)
    if bf_count < 3:
        return None

    # Only try if most characters are BF instructions (avoid false positives)
    if bf_count / len(s) < 0.5:
        return None

    output = _interpret_bf(s)
    if output is not None:
        output_stripped = output.strip()
        if output_stripped == "42":
            return f"Brainfuck: program outputs '42'"
        # Also check if output is the number 42 as a single character (ASCII 42 = '*')
        # But user said no ASCII * detection, so skip this.

    return None
