Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- open System
- open System.IO
- open System.Net
- open System.Text
- open System.Collections.Specialized
- //========================================================================
- // Task 1
- // Получает список символов по строке
- let explode (s:string) = [for c in s -> c]
- // Проверяем, сбалансированы ли скобки
- let isBalanced str =
- // acc здесь - список только скобочных символов (изначально пустой)
- let rec isBalanced' acc str =
- // str - список символов строки
- match str with
- // Если открывающийся - добавим
- | '('::xs -> isBalanced' ('('::acc) xs
- | '['::xs -> isBalanced' ('['::acc) xs
- | '{'::xs -> isBalanced' ('{'::acc) xs
- // Иначе надо проверить, что открывающаяся скобка такого же типа лежит на вершине листа
- | ')'::xs ->
- if (List.head acc = '(') then
- // МЫ БЕРЕМ List.tail, то есть все, без первого элемента!!!
- isBalanced' (List.tail acc) xs
- else
- false
- | ']'::xs ->
- if (List.head acc = '[') then
- isBalanced' (List.tail acc) xs
- else
- false
- | '}'::xs ->
- if (List.head acc = '{') then
- isBalanced' (List.tail acc) xs
- else
- false
- // Если символ - не скобка, то пофиг
- | _::xs -> isBalanced' acc xs
- | [] -> List.isEmpty acc
- // Возвращаем такую штуку (аналог return)
- isBalanced' [] (explode str)
- let str1 = "((8)){{[]}}{900}" //Все сбалансировано
- let str2 = "((88)){]" //Все плохо
- let TASK1_1 = isBalanced str1 // Возвращает true
- let TASK1_2 = isBalanced str2 // Возвращает false
- //=============================================================================
- // Task 2 - Считаем выражение, заданное строкой
- // Используем обратную польскую запись:
- // Параметр list - список символов строки
- let calc list =
- // Сначала не смотри на эту функцию, смотри на следующую!!!!!
- let rec evaluate ops values =
- if List.isEmpty ops then
- List.head values
- else
- let a::b::xs = values
- let op::left_ops = ops
- match op with
- | '+' -> evaluate left_ops ((a + b) :: xs)
- | '-' -> evaluate left_ops ((a - b) :: xs)
- | '*' -> evaluate left_ops ((a * b) :: xs)
- | '/' -> evaluate left_ops ((a / b) :: xs)
- // Что делает это говно.
- // Параметры:
- // balance - текущий скобочный баланс
- // op_acc - список операций (задается символами +,-,..)
- // value_acc - список цифр (=чисел, так как работаем только с цифрами, но семеру это не обязательно знать)
- // list - изначальный список символов строки, который будем парсить
- // Функция называется calc', в ней есть ключевое слово rec, потому что она рекурсивная
- let rec calc' balance op_acc value_acc list =
- match list with
- | ')'::_ when balance < 0 -> (op_acc, value_acc)
- | ')'::xs -> calc' (balance - 1) op_acc value_acc xs
- | _::xs when balance <> 0 -> calc' balance op_acc value_acc xs
- | '+'::xs -> calc' balance ('+'::op_acc) value_acc xs
- | '-'::xs -> calc' balance ('-'::op_acc) value_acc xs
- | '*'::xs -> calc' balance ('*'::op_acc) value_acc xs
- | '/'::xs -> calc' balance ('/'::op_acc) value_acc xs
- | '('::xs ->
- let a, b = (calc' 0 [] [] xs)
- let result = evaluate a b
- calc' (balance + 1) op_acc (result::value_acc) xs
- | ' ':: xs -> calc' balance op_acc value_acc xs
- | x::xs -> calc' balance op_acc (((int x) - (int '0')) :: value_acc) xs
- | [] -> (op_acc, value_acc)
- let ops, values = calc' 0 [] [] list
- evaluate ops values
- let b = "3 * (1 + 2 / 2)" // Работаем только с цифрами!!! С числами не умеем!
- printfn "%A" (calc (explode b)) // Выводит 6!
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement