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.

156 lines
6.9 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
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 traverseCoprime (n: int) (operation: int -> int -> int) (initialValue: int) =
[1..n]
|> List.filter (fun i -> areCoprime n i)
|> List.fold operation initialValue
let traverseCoprimeWithCondition (n: int) (condition: int -> bool) (operation: int -> int -> int) (initialValue: int) =
[1..n]
|> List.filter (fun i -> areCoprime n i && condition i)
|> List.fold operation initialValue
let eulerFunction (n: int) =
let countOperation _ acc = acc + 1
traverseCoprime n countOperation 0
let conditionalEulerFunction (n: int) (condition: int -> bool) =
[1..n]
|> List.filter (fun i -> areCoprime n i && condition i)
|> List.length
let isPrime x =
if x <= 1 then false
elif x <= 3 then true
elif x % 2 = 0 || x % 3 = 0 then false
else
let sqrtX = int(sqrt(float x))
let possibleFactors = [5..6..sqrtX] |> List.collect (fun i -> [i; i + 2])
not (possibleFactors |> List.exists (fun i -> x % i = 0))
let testTraverseCoprimeWithCondition () =
printfn "Тестирование функции обхода взаимно простых чисел с условием:"
let testCases = [10; 12; 15; 20; 30]
for n in testCases do
let testConditions = [
("Четные числа", fun x -> x % 2 = 0);
("Нечетные числа", fun x -> x % 2 <> 0);
("Числа, делящиеся на 3", fun x -> x % 3 = 0);
("Простые числа", isPrime);
("Числа > n/2", fun x -> x > n/2);
]
printfn "Для числа n = %d:" n
let allCoprimes = [1..n] |> List.filter (fun i -> areCoprime n i)
printfn " Все взаимно простые числа: %A" allCoprimes
for (conditionName, condition) in testConditions do
let filteredCoprimes = allCoprimes |> List.filter condition
let sum = traverseCoprimeWithCondition n condition (fun a b -> a + b) 0
let expectedSum = List.sum filteredCoprimes
let product = traverseCoprimeWithCondition n condition (fun a b -> a * b) 1
let expectedProduct = List.fold (fun acc x -> acc * x) 1 filteredCoprimes
let count = conditionalEulerFunction n condition
let expectedCount = List.length filteredCoprimes
printfn " Условие: %s" conditionName
printfn " Отфильтрованные взаимно простые числа: %A" filteredCoprimes
printfn " Сумма: %d (ожидаемая: %d) - %s"
sum expectedSum
(if sum = expectedSum then "OK" else "ОШИБКА")
printfn " Произведение: %d (ожидаемое: %d) - %s"
product expectedProduct
(if product = expectedProduct then "OK" else "ОШИБКА")
printfn " Количество (условная функция Эйлера): %d (ожидаемое: %d) - %s"
count expectedCount
(if count = expectedCount then "OK" else "ОШИБКА")
printfn ""
[<EntryPoint>]
let main argv =
Console.OutputEncoding <- Text.Encoding.UTF8
printfn "Задание 15. Функция обхода взаимно простых чисел с условием."
printfn ""
testTraverseCoprimeWithCondition()
printfn "Интерактивный режим:"
let rec processUserInput () =
printf "Введите число для вычисления условной функции Эйлера (или 'q' для выхода): "
let input = Console.ReadLine()
match input.ToLower() with
| "q" | "quit" | "exit" -> ()
| _ ->
match Int32.TryParse(input) with
| true, n when n > 0 ->
printfn "Выберите условие:"
printfn "1 - Только четные числа"
printfn "2 - Только нечетные числа"
printfn "3 - Только числа, делящиеся на 3"
printfn "4 - Только простые числа"
printfn "5 - Только числа > n/2"
printfn "6 - Свое условие (x > a)"
printf "Ваш выбор: "
let conditionChoice = Console.ReadLine()
let condition =
match conditionChoice with
| "1" -> (fun x -> x % 2 = 0), "четные числа"
| "2" -> (fun x -> x % 2 <> 0), "нечетные числа"
| "3" -> (fun x -> x % 3 = 0), "числа, делящиеся на 3"
| "4" -> (isPrime, "простые числа")
| "5" -> (fun x -> x > n/2), $"числа > {n/2}"
| "6" ->
printf "Введите значение a для условия (x > a): "
match Int32.TryParse(Console.ReadLine()) with
| true, a -> (fun x -> x > a), $"числа > {a}"
| _ -> (fun _ -> true), "все числа"
| _ -> (fun _ -> true), "все числа"
let (condFunc, condName) = condition
let coprimes = [1..n] |> List.filter (fun i -> areCoprime n i)
let filteredCoprimes = coprimes |> List.filter condFunc
let result = conditionalEulerFunction n condFunc
printfn "\nРезультаты для n = %d с условием: %s" n condName
printfn " Все взаимно простые числа: %A" coprimes
printfn " Отфильтрованные взаимно простые числа: %A" filteredCoprimes
printfn " Условная функция Эйлера φ'(%d) = %d" n result
let sum = traverseCoprimeWithCondition n condFunc (fun a b -> a + b) 0
printfn " Сумма: %d" sum
let product = traverseCoprimeWithCondition n condFunc (fun a b -> a * b) 1
printfn " Произведение: %d" product
printfn ""
processUserInput ()
| _ ->
printfn " Некорректный ввод. Пожалуйста, введите положительное целое число.\n"
processUserInput ()
processUserInput ()
0