На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> Пролог списки , Пару вопросов
    Всем привет, вот играюсь со списками в прологе

    И вот решил спросить почему у меня не получается, того что я ожидаю от пролога

    ExpandedWrap disabled
      has(X,[_|Y]) :-
      has(X,Y). % если элемент хвоста равен искомому элементу значение будет «истина»


    Допустим мы берём элемент и список. В конечном результате у нас false
    ExpandedWrap disabled
      ?- has(2,[1,2,3]).
      не хватает граничного условия рекурсии.
      % искомый элемент совпал с головой списка
      has(H,[H|_]).
      %искомый элемент содержится в хвосте списка
      has(X,[_|T]):-
      has(X,T).
        Цитата Swetlana @
        не хватает граничного условия рекурсии.
        % искомый элемент совпал с головой списка
        has(H,[H|_]).
        %искомый элемент содержится в хвосте списка
        has(X,[_|T]):-
        has(X,T).

        Вы Светлана как всегда на высоте, а я вот хочу понять списки и написать програмки. ну пока что туго выходит :(

        Добавлено
        Суть такова проверить лист, все ли цифры у нас стоят по порядку.

        Т.е как я понимаю. Берём лист, отсекаем Head, Tail дальше сравниваем Head < Tail, дальше с отсатка Tail дальше делим Head, Tail и так проверяем пока нету в списке Head > Tail и как только первый находим делаем отсечение ! и пишем faise
          Может, вот это поможет?
          Прикреплённый файлПрикреплённый файл_____________________.rar (26,12 Кбайт, скачиваний: 1108)
            мда чего-то не распечатывает линукс файлы с русским именем, сейчас попробую через терминал

            Добавлено
            Всё распаковал иду читать спасибо
              Цитата
              Суть такова проверить лист, все ли цифры у нас стоят по порядку.


              %в пустом списке всё в порядке
              check([]).
              %в одноэлементном тоже
              check([X]).
              % рекурсивное правило для списка хотя бы из двух элементов
              check([X,Y|T]):-
              X<=Y,
              check(T).
              Сообщение отредактировано: Swetlana -
                мда задачки простые а я вот читаю, по кускам со всех сайтов и пока не понял.

                иду почитаю и постараюсь вникнуть :wall:
                  Идея простая. Если в списке выделяем голову, то имеем граничное условие для пустого списка и рекурсивное правило для непустого. Обрабатываем первый элемент, для хвоста вызываем рекурсию.

                  В вашей задаче нужно было выделить два первых элемента [X,Y|T], поэтому получилось два граничных условия - одно для обработки пустого списка, второе - для одноэлементного.
                    Хмм почему вы не преподаёте у нас в Литве :rolleyes: Было бы не плохо :)
                      у меня проблема, в первом списке повторы могут быть :(

                      ExpandedWrap disabled
                        member(X, [X|_]):-!.
                        member(X, [_|Y]):- member(X, Y).
                         
                        general([], _, []).
                        general([X|T], L2, [X|Z]):- member(X, L2), !, general(T,  L2, Z).
                        general([_|T], L4, L2):- general(T, L4, L2).


                      Как это можно было бы локализовать :wall: :whistle:
                      Сообщение отредактировано: xpoint -
                        Что локализовать? В чём заключается задание?
                          Например ?-general([a,b,c,d][b,d,e],R) вернёт R=[b,d]. Тут всё ок, а вот если в первый список добавить ещё повтор например две bb то они и будут две в списке, хоть повтора второго в спискк не будет

                          Добавлено
                          И вот этот пример не понятен find([a,c,a,b,b,b,b,a,g], 4, C). Получаем что C=b. Т.е идём рекурсивно. По два элемента провнряем если истина +1 как не мовпадает считаем кол-во и если >= 4 тогда добавляем в C else обнуляем counter и считаем дальше? Прааильно я понимаю?
                            Цитата xpoint @
                            Например ?-general([a,b,c,d][b,d,e],R) вернёт R=[b,d]. Тут всё ок, а вот если в первый список добавить ещё повтор например две bb то они и будут две в списке, хоть повтора второго в спискк не будет

                            Процедура del2 удаляет из списка все повторы, то есть каждый элемент в возвращаемый список входит ровно один раз. Поэтому после general вызывайте del2
                            general([a,b,b,c,d][b,d,e],R), del2(R,R1).

                            ExpandedWrap disabled
                              %из пустого списка повторы уже удалены
                              del2([],[]).
                              %если голова списка принадлежит хвосту, то отбрасываем её
                              del2([H|T],T1):-
                                member(H,T),!,
                                del2(T,T1).
                              %если голова списка не принадлежит хвосту, делаем ей головой целевого списка
                              del2([H|T],[H|T1]):-
                                del2(T,T1).
                               
                              member(H,[H|T]):-!.
                              member(X,[_|T]):-
                                member(X,T).


                            Добавлено
                            Цитата xpoint @
                            И вот этот пример не понятен find([a,c,a,b,b,b,b,a,g], 4, C). Получаем что C=b. Т.е идём рекурсивно. По два элемента провнряем если истина +1 как не мовпадает считаем кол-во и если >= 4 тогда добавляем в C else обнуляем counter и считаем дальше? Прааильно я понимаю?

                            Я тоже не понимаю. Напишите процедуру find тогда объясню, что она делает.
                              По сути дела если использовпть предикат del2 задание будет совмем не верно выполенно "список R состпвлен из общих элементов двкх списков"

                              А вот что спрашивал в списке S есть K последовательно идущих одинаковых эллементов, которые записывает например в E
                                xpoint, наконец, увидела задания :)
                                Вечером отвечу, сейчас нет времени.
                                  Цитата Swetlana @

                                  ок, подождём я как всегда не успеваю ..... Сегодня ещё пойду уточню, может я не так понимаю эти два задания и не так говорю

                                  вот что у меня получилось

                                  ExpandedWrap disabled
                                    member(X, [X|_]):-!.
                                    member(X, [_|Y]):- member(X, Y).
                                     
                                    %из пустого списка повторы уже удалены
                                    del2([],[]).
                                    %если голова списка принадлежит хвосту, то отбрасываем её
                                    del2([H|T],T1):-
                                      member(H,T),!,
                                      del2(T,T1).
                                    %если голова списка не принадлежит хвосту, делаем ей головой целевого списка
                                    del2([H|T],[H|T1]):-
                                      del2(T,T1).
                                     
                                    general([], _, []).
                                    general([X|T], L2, [X|Z]):- member(X, L2), !, general(T,  L2, Z).
                                    general([_|T], L4, L2):- general(T, L4, L2), del2(L2, L3), L2=L3.


                                  Результат
                                  ExpandedWrap disabled
                                    ?- general([a,b,c,d], [b,d,e], R).
                                    R = [b, d].
                                     
                                    ?- general([a,a,b,c,d], [b,d,e], R).
                                    R = [b, d].
                                     
                                    ?- general([a,a,b,c,d], [a,b,d,e], R).
                                    R = [a, a, b, d].
                                     
                                    ?- general([a,a,b,c,d], [b,a,d,e], R).
                                    R = [a, a, b, d].


                                  Например последний, первый список имеет два a, а во втором только одна, т.е ответ у нас два a. Это не решает проблему
                                    Цитата xpoint @
                                    в списке S есть K последовательно идущих одинаковых эллементов, которые записывает например в E

                                    ExpandedWrap disabled
                                      kart([], K, E).
                                      kart([_], K, E).
                                      kart([X,Y|T], K, E):- X=Y, kart(T, K, E).
                                      kart([_|T], K, E):- kart(T, K, E).


                                    перебираем, а вот как в них определить K элементов по очереди и записать в E
                                      процедура cross возвращает пересечение двух списков,
                                      для тестового примера [2,5,2,5]

                                      ExpandedWrap disabled
                                        domains
                                        list = integer*
                                        predicates
                                        del(integer,list,list)
                                        member(integer,list)
                                        cross(list,list,list)
                                         
                                        goal
                                        cross([2,5,2,5,2,5],[2,2,3,5,5],L), write(L).
                                         
                                         
                                        clauses
                                        cross([],_,[]):-!.
                                        % голова первого списка принадлежит второму списку
                                        cross([H|T],L,[H|T1]):-
                                          member(H,L),!,
                                          del(H,L,L1),% удаляем элемент из второго списка
                                          cross(T,L1,T1).
                                        % голова первого списка не принадлежит второму списку
                                        cross([H|T],L,T1):-
                                          del(H,L,L1),
                                          cross(T,L1,T1).
                                         
                                         
                                        del(_,[],[]):-!.
                                        del(H,[H|T],T):-!.
                                        del(X,[H|T],[H|T1]):-
                                          del(X,T,T1).
                                         
                                        member(H,[H|T]):-!.
                                        member(X,[_|T]):-
                                          member(X,T).
                                        Элемент списка, который идёт подряд ровно K раз
                                        В тестовом примере это 5.

                                        ExpandedWrap disabled
                                          domains
                                          list = integer*
                                          predicates
                                          find(list,integer,integer)
                                          count(integer,list,integer)
                                           
                                          goal
                                          find([2,2,5,5,5,2],3,X), write(X).
                                           
                                          clauses
                                          %в пустом списке любой элемент идёт 0 раз
                                          count(_,[],0):-!.
                                          %заданный элемент не совпадает с головой списка, значит, идёт 0 раз
                                          count(X,[H|T],0):-
                                            X<>H,!.  
                                          %заданный элемент совпадает с головой списка
                                          count(H,[H|T],K):-
                                            count(H,T,M),
                                            K=M+1.
                                            
                                          find([H|T],K,H):-
                                            count(H,[H|T],K),!.
                                          find([_|T],K,Y):-    
                                            find(T,K,Y).
                                          Спасибо вам Света, мда совсем не так думаю, как надо. Вот и проблемы :(
                                            Потому что хотите в одном правиле сделать сразу и всё. А на Прологе так не пишут. Сделали чуть-чуть, а для всего остального вызываем вспомогательную процедуру.
                                            Например.
                                            Надо найти элемент, который в списке идёт K раз подряд. Элементов много. Поэтому проверим вначале для первого, будет ли он K раз повторяться. Как это проверить внутри правила? А внутри правила не надо ничего проверять, надо вызвать вспомогательную процедуру count, она и проверит.
                                            ExpandedWrap disabled
                                              find([H|T],K,H):-
                                                count(H,[H|T],K),!.

                                            Если первый элемент списка не повторяется K раз, то удалим его. А для уменьшенного списка уже можно вызвать рекурсию.
                                            ExpandedWrap disabled
                                              find([_|T],K,Y):-    
                                                find(T,K,Y).
                                              Вот вопрос на засыпку в одном файле может быть несколько задач, если например member уже был определён до этого и второй раз пытаешся определить :rolleyes:

                                              Добавлено
                                              Цитата Swetlana @
                                              Потому что хотите в одном правиле сделать сразу и всё. А на Прологе так не пишут. Сделали чуть-чуть, а для всего остального вызываем вспомогательную процедуру.
                                              Например.
                                              Надо найти элемент, который в списке идёт K раз подряд. Элементов много. Поэтому проверим вначале для первого, будет ли он K раз повторяться. Как это проверить внутри правила? А внутри правила не надо ничего проверять, надо вызвать вспомогательную процедуру count, она и проверит.
                                              ExpandedWrap disabled
                                                find([H|T],K,H):-
                                                  count(H,[H|T],K),!.

                                              Если первый элемент списка не повторяется K раз, то удалим его. А для уменьшенного списка уже можно вызвать рекурсию.
                                              ExpandedWrap disabled
                                                find([_|T],K,Y):-    
                                                  find(T,K,Y).

                                              Да да я привык что в c++ или на каком pascal всё сразу, а теперь вот пролог нужно изучать, и получается что я хочу от него всё сразу и без проблем

                                              Добавлено
                                              Хмм а вот этот пример что мы смотрели

                                              ExpandedWrap disabled
                                                did([]).
                                                did([_]).
                                                did([X,Y|T]):- X =< Y, did(T).

                                              [/code]
                                              Как я понял проверяет например

                                              ExpandedWrap disabled
                                                ?- did([4,18,2,100]).


                                              4=<18
                                              2=<100


                                              И получаем true
                                              По сути дела тут false, так как тут 18 не меньше чем 2 :whistle:

                                              Добавлено
                                              Иду подумаю, мне кажется тут что-то не трудное :)
                                              Сообщение отредактировано: xpoint -
                                                Цитата
                                                Вот вопрос на засыпку в одном файле может быть несколько задач, если например member уже был определён до этого и второй раз пытаешся определить :rolleyes:

                                                Иногда 2 разных мембера нужно описывать.
                                                member может быть детерминированный, с отсечением, который находит только первое вхождение элемента.
                                                Может быть недетерминированный без отсечения, при возвратах будет поочерёдно все вхождения находить.
                                                Если для одной задачи нужен member детерминированный, а для другой недетерминированный, то описывать два раза, назвать member и member1.

                                                Добавлено
                                                Цитата
                                                Хмм а вот этот пример что мы смотрели

                                                Здесь ошибка, сори.
                                                Надо так
                                                did([X,Y|T]):- X =< Y, did([Y|T]).
                                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                                0 пользователей:


                                                Рейтинг@Mail.ru
                                                [ Script execution time: 0,0560 ]   [ 16 queries used ]   [ Generated: 18.07.25, 00:51 GMT ]