diff --git a/lab 5/NumberOperationsAdvanced/Program.fs b/lab 5/NumberOperationsAdvanced/Program.fs index edc0ec4..ddc719e 100644 --- a/lab 5/NumberOperationsAdvanced/Program.fs +++ b/lab 5/NumberOperationsAdvanced/Program.fs @@ -16,9 +16,8 @@ let countDivisorsNotDivisibleByThree (n: int) = if n <= 0 then 0 else countDivisors 1 0 -// Метод 2: Найти минимальную нечетную цифру числа +// method 2: Найти минимальную нечетную цифру числа let findMinOddDigit (n: int) = - // Вспомогательная функция для поиска минимальной нечетной цифры с использованием хвостовой рекурсии let rec findMin number minDigit = if number = 0 then minDigit @@ -35,8 +34,65 @@ let findMinOddDigit (n: int) = findMin (abs n) -1 else findMin n -1 + +// общие вспомогательные функции +let rec gcd a b = + if b = 0 then abs a + else gcd b (a % b) + +let areCoprime a b = + gcd a b = 1 + +let getDigits n = + let rec extractDigits (num: int) (acc: int list) = + if num = 0 then + if acc.IsEmpty then [0] else acc + else + extractDigits (num / 10) ((num % 10) :: acc) + extractDigits (abs n) [] + +let sumDigits n = + let rec sumDigitsRec num acc = + if num = 0 then acc + else sumDigitsRec (num / 10) (acc + num % 10) + sumDigitsRec (abs n) 0 + +let productDigits n = + let rec productDigitsRec num acc = + if num = 0 then + if acc = 1 && n <> 0 then 0 else acc + else productDigitsRec (num / 10) (acc * (num % 10)) + productDigitsRec (abs n) 1 + +// method 3: Найти сумму всех делителей числа, взаимно простых с суммой цифр числа и не взаимно простых с произведением цифр числа +let sumSpecialDivisors (n: int) = + if n <= 0 then + 0 + else + let digitSum = sumDigits n + let digitProduct = productDigits n + + // Функция для проверки условия для делителя + let isSpecialDivisor divisor = + n % divisor = 0 && + areCoprime divisor digitSum && + not (areCoprime divisor digitProduct) + + // Рекурсивная функция для суммирования делителей + let rec sumDivisors current acc = + if current > n then + acc + else + let newAcc = + if isSpecialDivisor current then + acc + current + else + acc + sumDivisors (current + 1) newAcc + + sumDivisors 1 0 -// method test 1 +// test method 1 let testCountDivisorsNotDivisibleByThree () = let testCases = [1; 3; 6; 9; 10; 12; 15; 20; 30] @@ -80,13 +136,41 @@ let testFindMinOddDigit () = result expected (if result = expected then "OK" else "ОШИБКА") printfn "" +// method test 3 +let testSumSpecialDivisors () = + let testCases = [10; 12; 15; 20; 30; 36; 48; 56; 72; 96] + + printfn "Тестирование метода 3: Сумма особых делителей числа" + for n in testCases do + let digits = getDigits n + let digitsSum = sumDigits n + let digitsProduct = productDigits n + + let divisors = [1..n] |> List.filter (fun i -> n % i = 0) + let specialDivisors = divisors |> List.filter (fun d -> + areCoprime d digitsSum && not (areCoprime d digitsProduct)) + + let expected = List.sum specialDivisors + let result = sumSpecialDivisors n + + printfn "n = %d:" n + printfn " Цифры: %A" digits + printfn " Сумма цифр: %d" digitsSum + printfn " Произведение цифр: %d" digitsProduct + printfn " Все делители: %A" divisors + printfn " Особые делители: %A" specialDivisors + printfn " Результат: %d (ожидаемый: %d) - %s" + result expected (if result = expected then "OK" else "ОШИБКА") + printfn "" + [] let main argv = Console.OutputEncoding <- Text.Encoding.UTF8 printfn "Задание 16. Вариант № 5." printfn "Метод 1: Найти количество делителей числа, не делящихся на 3." - printfn "Метод 2: Найти минимальную нечетную цифру числа.\n" + printfn "Метод 2: Найти минимальную нечетную цифру числа." + printfn "Метод 3: Найти сумму всех делителей числа, взаимно простых с суммой цифр числа и не взаимно простых с произведением цифр числа.\n" printfn "=== Тестирование Метода 1 ===" testCountDivisorsNotDivisibleByThree() @@ -94,11 +178,15 @@ let main argv = printfn "=== Тестирование Метода 2 ===" testFindMinOddDigit() + printfn "=== Тестирование Метода 3 ===" + testSumSpecialDivisors() + printfn "Интерактивный режим:" let rec processUserInput () = printfn "Выберите метод:" printfn "1 - Количество делителей числа, не делящихся на 3" printfn "2 - Минимальная нечетная цифра числа" + printfn "3 - Сумма особых делителей числа" printfn "q - Выход" printf "Ваш выбор: " @@ -150,9 +238,36 @@ let main argv = processUserInput () + | "3" -> + printf "Введите число: " + match Int32.TryParse(Console.ReadLine()) with + | true, n when n > 0 -> + let result = sumSpecialDivisors n + + let digits = getDigits n + let digitsSum = sumDigits n + let digitsProduct = productDigits n + + let divisors = [1..n] |> List.filter (fun i -> n % i = 0) + let specialDivisors = divisors |> List.filter (fun d -> + areCoprime d digitsSum && not (areCoprime d digitsProduct)) + + printfn "Число: %d" n + printfn "Цифры: %A" digits + printfn "Сумма цифр: %d" digitsSum + printfn "Произведение цифр: %d" digitsProduct + printfn "Все делители: %A" divisors + printfn "Особые делители: %A" specialDivisors + printfn "Сумма особых делителей: %d" result + printfn "" + | _ -> + printfn "Некорректный ввод. Пожалуйста, введите положительное целое число.\n" + + processUserInput () + | "q" | "quit" | "exit" -> () | _ -> - printfn "Некорректный выбор. Пожалуйста, выберите 1, 2 или q." + printfn "Некорректный выбор. Пожалуйста, выберите 1, 2, 3 или q." processUserInput () processUserInput ()