|
|
|
@ -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 ""
|
|
|
|
|
|
|
|
|
|
[<EntryPoint>]
|
|
|
|
|
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 ()
|
|
|
|
|