Нахождение самой дорогой игрушки (Prolog)

Просмотр 3 веток ответов
  • Автор
    Сообщения
    • #6875
      @bananchik
      StudLance.ru

      Создайте базу данных об игрушках: название, стоимость. Получите названия всех наиболее дорогих игрушек (цены которых отличаются от самой дорогой не более, чем на 100 рублей).

      Помогите пожалуйста решить задание

      :- dynamic igr/3, count/2.
       
      title :-
       
              nl, nl,
              writeln('--- БД игрушек ---'),
              nl.
       
      load :-
              retractall(igr(_, _, _)),
              exists_file('base.txt'),
              !,
              consult('base.txt').
      load :-
              writeln('ОШИБКА: отсутствует файл base.txt').
              
      save :-
              tell('base.txt'),
              listing(igr/3),
              told,
              writeln('База сохранена').
              
      menu :-
              repeat, 
              writeln('1. Загрузка базы данных'),
              writeln('2. Добавление записи в базу данных'),
              writeln('3. Удаление записи из базы данных'),
              writeln('4. Название наиболее дорогих игрушек'),
              writeln('5. Выход'),
              write('Введите номер пункта: '),
              read(Answer),
              process(Answer),
              Answer == 5.
              
      readdata(F, I, Y) :-    
              write('Название: '), read(F),
              write('Стоймость: '), read(I),
              write('Возрастные границы: '), read(Y).
              
      printdata(F, I, Y) :-   
              write(F), write(' '), write(I), write(', '), write(Y), nl.  
              
      deletedata(F, I, Y) :-  
              retract(igr(F, I, Y)),
              !,
              writeln('---- Запись удалена');
              writeln('---- Запись не найдена').
              
      printall :-     
              igr(F, I, Y),
              printdata(F, I, Y),
              fail.
      printall :-     
              writeln('---- Конец списка').
              
      /*
      Кусок для кода 4 пункта.
      */
       
      process(1) :-
              !,
              writeln('---- Просмотр базы данных'),
              printall.
              
      process(2) :-
              !,
              writeln('---- Добавление записи'),
              readdata(F,I,Y),
              assert(igr(F, I, Y)),
              writeln('---- Запись добавлена').
              
      process(3) :-
              !,
              writeln('---- Удаление записи'),
              readdata(F,I,Y),
              deletedata(F, I, Y).
       
      /*process(4) :-
              !,
              writeln('---- Название наиболее дорогих игрушек),
      */
              
      process(5) :-
              !,
              writeln('Программа завершает работу').  
              
      process(_) :-
              writeln('Введен неправильный номер пункта меню').       
              
      run :-
          title,
              load,
              menu,
              save.
       
      :-run.

      StudLance.ru

    • #6877
      @admin

      1. Непонятно как этот код связан с вашей задачей. В задаче сказано, что игрушка имеет имя и цену, почему у вас в игрушке 3 поля — мне не понятно. Зачем в базе записи типа count тоже не понятно (про них в задании ничего не сказано).

      2. Ваш код ужасен, я так и не смог понять какие поля у ваших игрушек, для этого нужно смотреть файл с базой данных. Почему? — Потому что однобуквенные имена igr(F, I, Y) и попробуй догадайся что такое F, I и Y. Почитайте, пожалуйста, тут правила оформления кода на Prolog (да и на всех других языках правила похожие).

      3. Я не нашел где вы пытались решить задачу и я не знаю как встроить мое решение в ваш код (потому что не понимаю его). Но я бы решал так:

      В базе данных записи такого типа:

      toy('bear', 623).
      toy('mouse', 444).
      toy('small house', 555).
      toy('small bear', 456).
      toy('big house', 700).

      Сначала мне надо найти самую дорогую игрушку — то есть такую, дороже которой нет. Для этого я пишу вспомогательный предикат, который возвращает по очереди игрушки с базы, цена которых выше заданной:

      more_expensive_then(Cost, toy(ToyName, ToyCost)):-
        toy(ToyName, ToyCost),
        ToyCost > Cost.

      Просто, не правда ли? — Теперь с его помощью нахожу самую дорогую:

      most_expensive(toy(ExpensiveName, ExpensiveCost)):-
        toy(ExpensiveName, ExpensiveCost),
        \+more_expensive_then(ExpensiveCost, _Other), !.

      Тут записано следующее:
      1) найди в базе игрушку с некоторыми параметрами: toy(ExpensiveName, ExpensiveCost);
      2) эти параметры должны быть такими, чтобы не оказалось в базе игрушки с ценой выше чем
      ExpensiveCost. Тут используется оператор \+ — это оператор NOT.

      Итак, я нашел самую дорогую игрушку, а мне требуется найти все игрушки с ценой не ниже ExpensiveCost-100, использую для этого описанный в самом начале предикат и findall (по ссылке для детей описано как работает этот самый findall):

      expensive_toys(Delta, Toys):-
        most_expensive(toy(_ExpensiveName, ExpensiveCost)),
        MinCost is ExpensiveCost-Delta, 
        findall(Toy, more_expensive_then(MinCost, Toy), Toys).

      Я думаю понятно, что функция найдет самую дорогую вещь с помощью most_expensive, затем посчитает минимальную интересующую нас стоимость игрушки (Delta = 100 в вашем условии) и соберет все игрушки с интересной ценой.

      Запускал программу я в онлайн компиляторе с разными параметрами Delta, результаты такие:

    • #7050
      @bananchik

      Здравствуйте еще раз. Спасибо за наставление «Ваш код ужасен, я так и не смог понять какие поля у ваших игрушек, для этого нужно смотреть файл с базой данных.»
      Решил исправиться и сделать по другому. Но после добавления игрушки перестает работать пункт 4, помоги пожалуйста.

      :-dynamic igr/2.
      
      %...............................................................................
      
      igr:- 
        consult('BD.txt'),
        repeat,
        writeln("Выберите один из следующих пунктов меню:"),
        writeln("1 - Просмотреть содержимое динамической памяти;"),
        writeln("2 - Добавление записей;"),
        writeln("3 - Удаление записей;"),
        writeln("4 - Получение названия всех наиболее дорогих игрушек;"),
        writeln("5 - Выход (с сохранением)."),
        read(Choice),
        Choice < 6,
        proccess(Choice),
        Choice=5,!.
      
      %...............................................................................
      
      proccess(1):- 
        %write("Введите имя базы данных: "),
        %read(NameBD),
        findall((Name,Cost), igr(Name,Cost), IgrList),
        write_bd(IgrList).
      
      proccess(2):- 
        nl,writeln("Добавление игрушки:"),
        repeat,
        write("Название игрушки"),
        read(Name),
        write("Стоимость"),
        read(Cost),
        assertz(igr(Name,Cost)),
        nl,writeln("Хотите добавить еще запись? (y - да; n - нет): "),
        read(Answ),nl,
        check_answer(Answ),!.
      
      proccess(3):- 
        nl,writeln("Удаление записей."),nl,
        repeat,
        writeln("Введите название удаляемой игрушки: "),
        read(Name),
        writeln("Введите стоимость удаляемой игрушки: "),
        read(Cost),
        remove_record(Name,Cost),
        findall((Name,Cost), igr(Name,Cost), IgrList),
        write_bd(IgrList),
        nl,writeln("Хотите удалить еще что-то? (y - да; n - нет): "),
        read(Answ),nl,
        check_answer(Answ),!.
      
      proccess(4):- 
        nl,writeln("Наиболее дорогие игрушки:"),nl,
        most_expensive_igr.
      
      proccess(5):- 
        findall((Name,Cost), igr(Name,Cost), IgrList),
        open("BD.txt", write, F),
        set_output(F),
        write_in_file(IgrList),
        close(F).
      
      %...............................................................................
      %1
      write_bd([]):- !.
      write_bd([H|T]):- 
        writeln(H),
        write_bd(T),!.
      
      %...............................................................................
      %2
      %Add
      
      check_answer(y):- 
        fail.
      check_answer(n):- 
        write("Готово"),nl.
      
      %...............................................................................
      %3
      %Delete
      
      remove_record(Name, Cost):- 
        findall((Name,Cost),
        igr(Name,Cost),ListT),
      write_elem(ListT).
      
      write_elem([]):- 
        nl,writeln("Sorry, but I can't to find it"),nl.
      write_elem([(N,C)|[]]):- 
        retract(igr(N,C)).
      write_elem([(N,C)|T]):- 
        retract(igr(N,C)),
        write_elem(T),!.
      
      %...............................................................................
      %4
      %Наиболее дорогие игрушки
      
      most_expensive_igr:- 
        findall(C, igr(_,C), IgrListN),
        msort(IgrListN, IgrListN2),
        reverse(IgrListN2,IgrListN3),
        remove_excess(IgrListN3, IgrListN4),
        nth0(0,IgrListN4,Max),
        condition(IgrListN4, Max, _, _, IgrList),
        write_bd(IgrList),nl.
      
      condition([],_, IgrList, _, IgrList):- !.
      condition([H|T], Max, IgrListBefore, IgrListAfter, IgrList):- 
        (Max-1000)=< H,
        findall((Name,H), igr(Name,H), TmpList),
        append(IgrListBefore, TmpList, IgrListAfter),
        condition(T, Max, IgrListAfter, _, IgrList),!.
      condition([H|[H|T]], Max, IgrListBefore, _, IgrList):- 
        condition(T, Max, IgrListBefore, _, IgrList),!.
      condition([_|_], _,IgrList,_,IgrList):- !.
      
      remove_excess([],_):-!.
      remove_excess([H|[L|T]], ListNew):- 
        H\=L,
        remove_excess(T,ListNew1),
        append([H,L],ListNew1, ListNew), !.
      remove_excess([H|[_|T]],ListNew):- 
        remove_excess(T,ListNew1),
        append([H],ListNew1, ListNew), !.
      
      %...............................................................................
      %5
      
      write_in_file([]):- !.
      write_in_file([(Name,Cost)|T]):- 
        write('igr("'),write(Name),
        write('",'),write(Cost),
        write(').'),nl,
        zwrite_in_file(T),!.

      • #7051
        @admin

        Ваш код как был ужасен, так и остался. Посмотри насколько твой код к пункту 4 сложнее чем мой и, самое главное, я не понимаю — мой то код чем не подошел?

        Я запустил вашу программу с пустым файлом базы данных. Выбрал пункт 4 получил ошкбку:

        Ну ладно… добавил в базу игрушки, запустил, ничего не получил (выводит лишь фразу «Наиболее дорогие игрушки») и открывает опять меню.

        По коду пункта 4. Я понял, что ты поместил все игрушки в список, отсортировал его, перевернул.

    • #7053
      @bananchik

      Преподователя не устроил, этот код она посчитала приемлемым, только не работает 4 пункт после добавления, вот я и попросил помощи

      • #7055
        @admin

        Что делает remove_excess? — я вот не понимаю. Получил ты список упорядоченный список цен и передаешь его в эту функцию.

        Первое правило этой функции срабатывает если список пустой, при этом функция возвращает неинициализированный объект:
        remove_excess([],_):-!.
        Именно это правило срабатывало когда я запуска программу с пустой базой и именно поэтому падала с ошибкой. А что ты хотел сказать этим кодом?

        Ну ладно, идем дальше. Если список не пуст, происходит это:
        remove_excess([H|[L|T]], ListNew):-

        Не читая тело функции можно сказать что работать это не будет. Это правило ожидает, что на вход будет подан список списков, типа [1, [2, [3, []]]], но ты то подал на вход обычный список цен. Что ты хотел сделать этим кодом — я не понимаю.

        При этом я очень понятно описал как без каких-то сложных конструкций решить твою проблему. И что не так в моем решении?

Просмотр 3 веток ответов
  • Для ответа в этой теме необходимо авторизоваться.
×