open System

// method 1: Найти количество делителей числа, не делящихся на 3
let countDivisorsNotDivisibleByThree (n: int) =
    let rec countDivisors current count =
        if current > n then 
            count
        else
            // является ли текущее число делителем n и не делится ли оно на 3
            let newCount = 
                if n % current = 0 && current % 3 <> 0 then
                    count + 1
                else
                    count
            countDivisors (current + 1) newCount
    
    if n <= 0 then 0 else countDivisors 1 0

// Метод 2: Найти минимальную нечетную цифру числа
let findMinOddDigit (n: int) =
    // Вспомогательная функция для поиска минимальной нечетной цифры с использованием хвостовой рекурсии
    let rec findMin number minDigit =
        if number = 0 then
            minDigit
        else
            let digit = number % 10
            let newMin =
                if digit % 2 <> 0 && (minDigit = -1 || digit < minDigit) then
                    digit
                else
                    minDigit
            findMin (number / 10) newMin
    
    if n < 0 then
        findMin (abs n) -1
    else
        findMin n -1
        
// method test 1
let testCountDivisorsNotDivisibleByThree () =
    let testCases = [1; 3; 6; 9; 10; 12; 15; 20; 30]
    
    printfn "Тестирование метода 1: Количество делителей числа, не делящихся на 3"
    for n in testCases do
        let divisors = [1..n] |> List.filter (fun i -> n % i = 0)
        let divisorsNotDivByThree = divisors |> List.filter (fun i -> i % 3 <> 0)
        
        let expected = divisorsNotDivByThree.Length
        let result = countDivisorsNotDivisibleByThree n
        
        printfn "n = %d:" n
        printfn "  Все делители: %A" divisors
        printfn "  Делители, не делящиеся на 3: %A" divisorsNotDivByThree
        printfn "  Результат: %d (ожидаемый: %d) - %s" result expected (if result = expected then "OK" else "ОШИБКА")
        printfn ""

// method test 2
let testFindMinOddDigit () =
    let testCases = [0; 2; 8; 13; 25; 42; 123; 456; 789; 2468; 1359; 12345]
    
    printfn "Тестирование метода 2: Минимальная нечетная цифра числа"
    for n in testCases do
        let digits = 
            n.ToString()
            |> Seq.map (fun c -> int c - int '0')
            |> Seq.toList
        
        let oddDigits = digits |> List.filter (fun d -> d % 2 <> 0)
        
        let expected = 
            if oddDigits.IsEmpty then -1
            else List.min oddDigits
            
        let result = findMinOddDigit n
        
        printfn "n = %d:" n
        printfn "  Цифры: %A" digits
        printfn "  Нечетные цифры: %A" oddDigits
        printfn "  Минимальная нечетная цифра: %d (ожидаемая: %d) - %s" 
            result expected (if result = expected then "OK" else "ОШИБКА")
        printfn ""

[<EntryPoint>]
let main argv =
    Console.OutputEncoding <- Text.Encoding.UTF8
    
    printfn "Задание 16. Вариант № 5."
    printfn "Метод 1: Найти количество делителей числа, не делящихся на 3."
    printfn "Метод 2: Найти минимальную нечетную цифру числа.\n"
    
    printfn "=== Тестирование Метода 1 ==="
    testCountDivisorsNotDivisibleByThree()
    
    printfn "=== Тестирование Метода 2 ==="
    testFindMinOddDigit()
    
    printfn "Интерактивный режим:"
    let rec processUserInput () =
        printfn "Выберите метод:"
        printfn "1 - Количество делителей числа, не делящихся на 3"
        printfn "2 - Минимальная нечетная цифра числа"
        printfn "q - Выход"
        
        printf "Ваш выбор: "
        match Console.ReadLine().ToLower() with
        | "1" ->
            printf "Введите число: "
            match Int32.TryParse(Console.ReadLine()) with
            | true, n when n > 0 ->
                let result = countDivisorsNotDivisibleByThree n
                let divisors = [1..n] |> List.filter (fun i -> n % i = 0)
                let divisorsNotDivByThree = divisors |> List.filter (fun i -> i % 3 <> 0)
                
                printfn "Число: %d" n
                printfn "Все делители: %A" divisors
                printfn "Делители, не делящиеся на 3: %A" divisorsNotDivByThree
                printfn "Количество делителей, не делящихся на 3: %d" result
                printfn ""
            | _ ->
                printfn "Некорректный ввод. Пожалуйста, введите положительное целое число.\n"
            
            processUserInput ()
            
        | "2" ->
            printf "Введите число: "
            match Int32.TryParse(Console.ReadLine()) with
            | true, n ->
                let result = findMinOddDigit n
                
                printfn "Число: %d" n
                
                let digits = 
                    (abs n).ToString()
                    |> Seq.map (fun c -> int c - int '0')
                    |> Seq.toList
                
                let oddDigits = digits |> List.filter (fun d -> d % 2 <> 0)
                
                printfn "Цифры: %A" digits
                printfn "Нечетные цифры: %A" oddDigits
                
                if result = -1 then
                    printfn "В числе нет нечетных цифр."
                else
                    printfn "Минимальная нечетная цифра: %d" result
                
                printfn ""
            | _ ->
                printfn "Некорректный ввод. Пожалуйста, введите целое число.\n"
                
            processUserInput ()
            
        | "q" | "quit" | "exit" -> ()
        | _ ->
            printfn "Некорректный выбор. Пожалуйста, выберите 1, 2 или q."
            processUserInput ()
    
    processUserInput ()
    0