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 eulerFunction (n: int) = let countOperation _ acc = acc + 1 traverseCoprime n countOperation 0 let eulerFunctionFormula (n: int) = let isPrime n = if n <= 1 then false elif n <= 3 then true elif n % 2 = 0 || n % 3 = 0 then false else let sqrt_n = int (sqrt (float n)) let rec checkDivisors i = if i > sqrt_n then true elif n % i = 0 || n % (i + 2) = 0 then false else checkDivisors (i + 6) checkDivisors 5 let rec getUniquePrimeFactors n divisor factors = if n <= 1 then factors elif n % divisor = 0 then let newFactors = if List.contains divisor factors then factors else divisor :: factors getUniquePrimeFactors (n / divisor) divisor newFactors else getUniquePrimeFactors n (divisor + 1) factors if n = 1 then 1 else let primeFactors = if isPrime n then [n] else let factors = getUniquePrimeFactors n 2 [] factors |> List.filter isPrime |> List.sort let result = primeFactors |> List.fold (fun acc p -> acc * (1.0 - 1.0 / float p)) (float n) int result let testTraverseCoprime () = printfn "Тестирование функции traverseCoprime:" let testCases = [2; 5; 10; 12; 15; 20; 30] for n in testCases do let coprimes = [1..n] |> List.filter (fun i -> areCoprime n i) let sum = traverseCoprime n (fun a b -> a + b) 0 let expectedSum = List.sum coprimes let product = traverseCoprime n (fun a b -> a * b) 1 let expectedProduct = List.fold (fun acc x -> acc * x) 1 coprimes let count = traverseCoprime n (fun _ acc -> acc + 1) 0 let expectedCount = List.length coprimes printfn "n = %d, взаимно простые числа: %A" n coprimes 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 "" let testEulerFunction () = printfn "Тестирование функции Эйлера (phi):" let expectedValues = [ (1, 1); (2, 1); (3, 2); (4, 2); (5, 4); (6, 2); (7, 6); (8, 4); (9, 6); (10, 4); (12, 4); (15, 8); (20, 8); (30, 8); (36, 12); (48, 16); (60, 16); (100, 40) ] for (n, expected) in expectedValues do let result = eulerFunction n printfn " φ(%2d) = %2d (ожидаемое: %2d) - %s" n result expected (if result = expected then "OK" else "ОШИБКА") printfn "" let compareEulerFunctions () = printfn "Сравнение двух способов вычисления функции Эйлера:" let testCases = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 12; 15; 20; 30; 36; 48; 60; 100] for n in testCases do let result1 = eulerFunction n let result2 = eulerFunctionFormula n printfn " n = %3d: φ(n) = %3d (через обход), φ(n) = %3d (по формуле) - %s" n result1 result2 (if result1 = result2 then "СОВПАДАЕТ" else "РАЗЛИЧАЕТСЯ") printfn "" [] let main argv = Console.OutputEncoding <- Text.Encoding.UTF8 printfn "Задание 14. Тестирование функции обхода взаимно простых чисел и вычисление функции Эйлера." printfn "" testTraverseCoprime() testEulerFunction() compareEulerFunctions() printfn "Интерактивный режим:" let tryAgain = ref true while !tryAgain do printf "Введите число для вычисления функции Эйлера (или 'q' для выхода): " let input = Console.ReadLine() match input.ToLower() with | "q" | "quit" | "exit" -> tryAgain := false | _ -> match Int32.TryParse(input) with | true, n when n > 0 -> let startTime1 = DateTime.Now let phi1 = eulerFunction n let endTime1 = DateTime.Now let startTime2 = DateTime.Now let phi2 = eulerFunctionFormula n let endTime2 = DateTime.Now printfn " φ(%d) = %d" n phi1 printfn " Через обход: %A" (endTime1 - startTime1) printfn " По формуле: %A" (endTime2 - startTime2) if n <= 30 then let coprimes = [1..n] |> List.filter (fun i -> areCoprime n i) printfn " Взаимно простые числа с %d: %A" n coprimes printfn "" | _ -> printfn " Некорректный ввод. Пожалуйста, введите положительное целое число.\n" 0