|
|
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
|
|
|
|
|
|
// method 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
|
|
|
|
|
|
// общие вспомогательные функции
|
|
|
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
|
|
|
|
|
|
// test method 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 ""
|
|
|
|
|
|
// 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: Найти минимальную нечетную цифру числа."
|
|
|
printfn "Метод 3: Найти сумму всех делителей числа, взаимно простых с суммой цифр числа и не взаимно простых с произведением цифр числа.\n"
|
|
|
|
|
|
printfn "=== Тестирование Метода 1 ==="
|
|
|
testCountDivisorsNotDivisibleByThree()
|
|
|
|
|
|
printfn "=== Тестирование Метода 2 ==="
|
|
|
testFindMinOddDigit()
|
|
|
|
|
|
printfn "=== Тестирование Метода 3 ==="
|
|
|
testSumSpecialDivisors()
|
|
|
|
|
|
printfn "Интерактивный режим:"
|
|
|
let rec processUserInput () =
|
|
|
printfn "Выберите метод:"
|
|
|
printfn "1 - Количество делителей числа, не делящихся на 3"
|
|
|
printfn "2 - Минимальная нечетная цифра числа"
|
|
|
printfn "3 - Сумма особых делителей числа"
|
|
|
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 ()
|
|
|
|
|
|
| "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, 3 или q."
|
|
|
processUserInput ()
|
|
|
|
|
|
processUserInput ()
|
|
|
0 |