Кратчайшее слово в списке символов

Программирование Помощь с решением задач на Prolog Задачи на списки Кратчайшее слово в списке символов

Просмотр 1 ветки ответов
  • Автор
    Сообщения
    • #6358
      @sc32

      Добрый вечер!

      Помогите, пожалуйста, с ответом на задачу (среда SWI):

      В списке символов S1, S2, …, Sn найти самое короткое слово, если разделителем между словами является один или несколько пробелов и удалить его.

    • #6360
      @admin

      Читаете о том, как выделить в списке символов «слова» тут: Преобразование строки в список слов.

      Можно поместить все слова в список и найти в нем минимум (даже стандартной функцией можно). Ну или так:

      % возвращает список с минимальной длиной, если он не пустой
      min_by_length([], [], _Min):-!, fail.
      min_by_length([], B, B):-!.
      min_by_length(A, [], A):-!.
      min_by_length(A, B, Min):-
          length(A, ALength),
          length(B, BLength),
          ALength < BLength, !, Min = A; Min = B.
          
      % возвращает кратчайшее слово строки
      shortest_word([], []):-!.
      shortest_word(String, ShortestWord):-
          read_word(String, FirstWord, Tail), 
          shortest_word(Tail, ShortestTail), 
          min_by_length(FirstWord, ShortestTail, ShortestWord).

      Недостающие предикаты можно взять по ссылке выше. Тут я не использую функцию преобразования строки в список слов, т.к. в вашем задании ничего не сказано про пробелы — нужно их сохранять или нет. Удалять дальше слово из списка — это не совсем правильно, ведь для строки "123 4 56" должно получиться "123 56" (по центру два пробела).

      Также, для удаления не подойдут стандартные предикаты, что иллюстрирует пример:
      String = ['1', '2', '3', ' ', ' ', ' ', '2', '3'],

      Кратчайшее слово «23», но если мы попробует его удалить — то получим не "123", а "1 23". В этом проблема — при удалении нужно еще раз убедиться, что удаляем именно слово. Для этого выполним поиск слова и получим часть строки слева и справа с помощью divide_list: Функция разделения списка на части. Теперь надо проверить что слева и справа от слова находятся пробелы, напишем функцию, которая проверяет что список симвовлов начинается с пробелов:

      start_from_space([]):-!.
      start_from_space([Head|_Tail]):-
          is_space(Head).

      Для части строки «справа» — просто вызовем эту функцию, а для левой части ее нужно применить к концу подстроки — поэтому сначала перевернем левый подсписок стандартной функцией reverse:

      remove_word(String, Word, Result):-
          divide_list(String, [Left, Word, Right]),
          reverse(Left, ReverseLeft),
          start_from_space(ReverseLeft), 
          start_from_space(Right),
          append(Left, Right, Result).

      Пример использования:

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