|
|
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 |