You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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