![]() |
|
|
![]()
|
|
| Vokunya |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 73 Регистрация: 7.12.2008 Где: Беларусь Репутация: 1 Всего: 1 |
Не буду врать о том, что пытался разобраться - потраченное время дороже. Надо сделать эти задачи и забыть все, как страшный сон
1. Дана последовательность символов s1 , s2 , ..., sn (n>=2 и заранее неизвестно). Получить последовательность символов, содержащую только последние вхождения каждого символа в строку с сохранением их исходного взаимного порядка. 2. а) удалить из списка все повторяющиеся подсписки; б) подсчитать количество положительных чисел в списке; в) подсчитать сумму положительных и произведение отрицательных элементов списка; г) подсчитать число повторяющихся элементов списка. 3. Подсчитать количество вхождений в дерево данной метки 4. Разработать программу для определения и вывода на экран неотрицательных значений функции f(x) = lg((m!)^3 – 1/n!) . Значения n, m ввести с клавиатуры Если у кого есть наработки - буду благодарен, если кто готов взяться за решение, то пишите - договоримся З. Ы. Модераторы, переместите пожалуйста в ветку Функциональные языки... только сейчас заметил, что есть такой раздел Это сообщение отредактировал(а) Vokunya - 27.3.2011, 11:15 |
|||
|
||||
| Void |
|
||||||||||||||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 1 Всего: 173 |
Решения в виде отдельной функции. Как там у вас принято ввод-вывод организовывать, неизвестно. Подразумевается import Data.List.
1.
2.а. Непонятно условие, на входе список списков (тип Eq a => [[a]]) или плоский список, из которого надо выделять возможные подсписки? В последнем случае, если не ограничить длину подсписка снизу, получается странное. 2.б.
Можно без Ord, раздутость Num поможет:
2.в
Аналогично 2.б, partition (>= 0) можно поменять на partition ((/= -1) . signum) 2.г.
Или, если напрягает лишний констрейнт Ord, то только на списках и Eq с квадратичной сложностью:
3. Просто дерево?
4. f(x), а где справа x? Выражение читать как lg((m!)^3 - (1/n!)) или lg(((m!)^3 - 1) / n!)? Что делать с отрицательными значениями функции? -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
||||||||||||||
|
|||||||||||||||
| k0rvin |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 442 Регистрация: 24.1.2010 Репутация: нет Всего: 5 |
эээ, вроде (-) всегда имел меньший приоритет, чем (/) -------------------- “Object-oriented design is the roman numerals of computing.” — Rob Pike All software sucks |
|||
|
||||
| Vokunya |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 73 Регистрация: 7.12.2008 Где: Беларусь Репутация: 1 Всего: 1 |
Собственно, раз пошла такая пьянка, то мне уже даже самому захотелось разобраться
По поводу 2а: на входе список списков, т.е. имеем, например [[1,2],[3,5,7],[1,8,1,9],[1,2],[1,2], [3,5,7]], получим [[1,2],[3,5,7],[1,8,1,9]] Думаю, что здесь достаточно будет nub? Или я ошибаюсь? просто сейчас нет возможности проверить 2в: я очень прошу Void снабдить сие дело комментариями, или подскажи откуда это почитать 2г: а можно так?
3. бинарное дерево, и если можно тоже комментов 4.
с X разберусь; читать как первый вариант, и по этой задаче я тоже кое-чего сам набрасал, только с ошибками не могу справиться )) позже покажу код - осбудим |
||||
|
|||||
| Void |
|
||||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 1 Всего: 173 |
Ну больно несоразмерные члены получались, захотелось убедиться, что это не ошибка небрежного копипаста. Да, Eq a => Eq [a], т.е. если тип элемента списка реализует сравнение на равенство, то сравнение списков реализуется автоматически естественным образом.
Гм, если предыдущие были понятны, то что в этой функции особенного? sum, product, partition. partition делит список на две части: соответствующие предикату и нет. Функции надо искать в Hoogle, он рулит. Не упорядоченное? Можно со списками оставить, можно новый тип специально для бинарного дерева состряпать:
Что конкретно прокомментировать? АДТ (алгебраический тип данных) понятен? Тип функции? К записи функции вопросы? Просто создаётся впечатление, что некое знакомство с Haskell уже есть и объяснять всё с нуля не имеет смысла, но где именно проходит граница понимания, неясно. Ждём. -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
||||
|
|||||
| Vokunya |
|
||||||||||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 73 Регистрация: 7.12.2008 Где: Беларусь Репутация: 1 Всего: 1 |
Что вы, увольте ))) я даже на hаskell.org залез уже после того, как здесь тему создал ) Теперь по делу: Задача 1: че-то код для символов не работает, а только для чисел. Потом, как организовать ввод n и ввод символов количества n, для которых потом применим эту функцию? могу сделать что-то такое
а как потом n привести к числу (я же правильно понимаю, что сейчас это строка?)
вроде не работает... или я что-то не так делаю и как потом организовать ввод списка элементов? Теперь по комментам:
Вот что это строчка делает? Словами можете рассказать? Для чего нужна "."? ну т.е reverse - перевернули список, а потом что с ним? ) Задача 3:
непонятно как вот это работает
но пока не говорите )) я еще сам в коде поковыряюсь, потом, когда возникнут конкретные вопросы - дам знать... единственное, что значит знак "$" вот в этом?
Задача 4: здесь такие изменения в условии - это не функция, просто задаем m и n, устанавливаем диапазон их изменения и шак изменения - 1 вопросы остается как и для первой задачи: как ввести m, n, шаг и диапазон и как их привести к числовому типу... и напрашивается для реализации какой-нибудь while {}, но что-то мне подсказывает, что это совсем не "гуд" для функциональных языков... но что-то тяжко приспособится к новой парадигме )) поэтому промойте мне мозг, пожалуйста |
||||||||||||||
|
|||||||||||||||
| Void |
|
||||||||||||||||||||||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 1 Всего: 173 |
Точка — это композиция функций. Т.е. (f . g)(x) = f(g(x)). Нашу функцию можно записать развёрнуто:
nub удаляет из списка дублирующиеся элементы, но оставляет от каждого первое вхождение, а не последнее, как нам нужно. Поэтому мы сначала разворачиваем список, чтобы nub оставила последние вхождения, а потом переворачиваем результат обратно. Не понял. Для всего он работает, лишь бы равенство для этого типа было определено. Пример с ошибкой можно?
readLn читает сразу в нужном типе (какой выведет из контекста или явно указанный):
Но направление мысли с read тоже правильное. Для того чтобы считать строку без обработки в System.IO есть getLine:
Дальше, что есть символ в условиях задачи? char? В таком случае вводить число символов, а потом ещё вводить их по одному выглядит издевательством над пользователем. Строка в Haskell — уже список символов (тип [Char]). Но для иллюстрации, пожалуйста, ввод n и списка длиной n, обобщённый в виде функции:
replicateM живёт в Control.Monad. Эта фукнция берёт монадическое действие, повторяет его n раз и возвращает собранные результаты в виде списка. Увы, ввод-вывод в Haskell неразрывно связан с монадами, и объяснять их в одном посте я не возьмусь. Конкретно монада IO инкапсулирует в себе все вычисления с побочными эффектами, и вырвать результат такого вычисления из неё невозможно. IO a — это действие с побочными эффектами, приводящее к вычислению значения типа a. $ — это оператор применения функции. f $ x = f(x). Из-за правой ассоциативности и минимального приоритета он позволяет экономить скобки в цепочке вызовов: f $ g $ h x эквивалентно f(g(h(x))). В общем случае цикл в функциональном языке превращается в рекурсию. Но, как правило, рекурсия — слишком примитивный инструмент и вместо неё можно использовать заготовленные в языке и библиотеках абстракции. В Haskell цикл очень часто превращается в «построй список и что-то сделай с его элементами». Куча функций [высшего порядка] есть для того чтобы списки строить и преобразовывать. Для конкретного случая целых чисел есть очень удобный синтаксис: [m..n] — это список от m до n с шагом 1. (Это работает не только для чисел, но и для любых типов, реализующих класс Enum). Применить функцию к каждому элементу списка можно с помощью map: map f [a1, a2, ... an] = [f(a1), f(a2), ... f(an)]. В случае функции двух аргументов запись получается тяжеловесная:
К счастью, в Haskell есть синтаксический сахарок как раз для таких случаев — list comprehensions. Предыдущая запись с ними превращается в
Разница в том, что list comprehensions результирующий список сливают, делают плоским. При использовании map получился бы список списков. Следующий вопрос: нам функцию нужно не просто вычислить, а вывести, табулировать. Можно затащить вывод внутрь comprehension, получит на выходе [IO a] (список действий вывода) и актуализировать его с помощью sequence_ из Control.Monad:
Подчёркивание в конце функции, как правило, обозначает, что она выкидывает результат, т.е. выполняется только ради побочных действий и возвращает IO (). printf живёт в Text.Printf. Можно наоборот, вытащить наружу аргументы вместе с результатами (в виде кортежа) и применить к ним вывод:
forM живёт в Control.Monad. Собственно, название функции намекает. С ней можно сделать совсем похоже на императивный цикл:
-------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
||||||||||||||||||||||
|
|||||||||||||||||||||||
| Vokunya |
|
||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 73 Регистрация: 7.12.2008 Где: Беларусь Репутация: 1 Всего: 1 |
Код такой:
|
||||||
|
|||||||
| Void |
|
||||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 1 Всего: 173 |
Хаскель — это не Лисп всё-таки
Можно даже так:
Это сообщение отредактировал(а) Void - 3.4.2011, 14:53 -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
||||
|
|||||
| Vokunya |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 73 Регистрация: 7.12.2008 Где: Беларусь Репутация: 1 Всего: 1 |
мдя... что-то я совсем затупил (( выходные плохо влияют на работу мозга )) |
|||
|
||||
| Vokunya |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 73 Регистрация: 7.12.2008 Где: Беларусь Репутация: 1 Всего: 1 |
Меня убивает 4-ая задача...
и в forM_ прокатит ли [n..n+steps]? |
||||
|
|||||
| Void |
|
||||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 1 Всего: 173 |
Тут проблемы со структурой программы. Получился несвязанный набор объявлений, никем не используемых. Выражения на верхнем уровне недопустимы, только объявления. В Haskell, как и в ряде «обычных» языков, точка входа в программу называется main. Эта функция должна иметь тип IO a (Как правило, просто IO (), потому что возвращаемое значение нигде не используется. Код возврата программы можно установить с помощью функций из модуля System.Exit). Кроме того, если модуль не безымянный, и не называется Main, то GHC надо явно указать, в каком модуле находится точка входа с помощью опции -main-is:
Соответственно, код будет выглядеть примерно так:
И ещё, смысл вот этого объявления до меня не доходит: -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
||||
|
|||||
| Shaggie |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 570 Регистрация: 21.12.2006 Где: outer space Репутация: нет Всего: 72 |
Неудачная запись для хаскеля. Теперь ещё отрицательные значения отсекать придётся отдельным условием на каждом шаге. Лучше получить все результаты одним списком, а потом обработать:
Если нужна отладочная запись, можно собрать результаты в тупл (пример ниже) или, для удобства, завести отдельный рекорд
|
||||||
|
|||||||
| Vokunya |
|
||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 73 Регистрация: 7.12.2008 Где: Беларусь Репутация: 1 Всего: 1 |
Выдает:
Читал про то, что вроде как надо использовать fromIntegral и floor, но не помогло, но скорее всего я не так что-то делал А если поменять на простую функцию, например:
то *** Exception: Printf.printf: bad argument (вводил значения 3 2 1) |
||||||
|
|||||||
| Void |
|
||||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 1 Всего: 173 |
Можно fromIntegral или realToFrac: my (fromIntegral i) (fromIntegral j) ... Но тогда возникнет ещё одна ошибка из-за того, что конкретный тип возвращаемого значения my не определён и не выводится из констрейнтов. Обходится явной декларацией типа my: my :: Double -> Double -> Double В таком виде всё работает.
%f требует вещественного аргумента. При my a b = a + b все типы выводились как целые. Вот, кстати, проблема printf: убивает типизацию. -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
||||
|
|||||
![]()
|
| Правила форума «Функциональные языки: общие вопросы» | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Void. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Функциональные языки: общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |