1. Куча / Говнокод #7208

    +129

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    ;;; Returns a string and 'T' if the list is in a desc. or asc. order, and NIL otherwise
    
    (defun ordered (list)
    (let ((list-dec (copy-list list)))
    (let ((list-inc (copy-list list)))
    (let ((alist (sort list-inc #'<)))
    (let ((dlist (sort list-dec #'>)))
    (cond
      ((equal list dlist)
       (format nil "~%The numbers in ~a are in a descending order. ~%T" list))
    
      ((equal list alist)
       (format nil "~%The numbers in ~a are in an ascending order. ~%T" list))))))))

    Задача была следующей: функция должна возвращать t (истина), если в списке все элементы либо в восходящем, либо в нисходящем порядкe, и соответсвенно nil (ложь), если нет. Думаю, вполне сгодится сюда :)
    http://www.lispforum.com/viewtopic.php?f=2&t=1275

    Запостил: wvxvw, 08 Июля 2011

    Комментарии (28) RSS

    • такая странная постановка задачи может быть только в лабе.
      Ответить
      • Инспектор L раскрыл все карты этого дела. Больше нечего добавить. Минусую.
        Ответить
      • Лаба, конечно, но решение писал не студент, а советсчик с форума, на то и ссылка.
        Ответить
    • Чушь какая-то. Половина let'ов не нужна, у cond'а нет умолчательной ветки, функция вместо того, чтобы возвращать T или NIL выводит какие-то письмена.
      Это что, опаскаленного учат языку программирования?

      UPD Вру, ни один let не нужен. И cond не нужен. И говнокод этот тут не нужен, ибо уныл.
      Ответить
      • Почему? Если не принимать во внимание недочеты реализации, то говнозадумка автора не так частво тут встречалась (я так вообще ни разу не видел). По-моему идея отсортировать список, а потом сравнить с исходником, вместо того, чтобы проверить исходный список вполне достойна этого сайта, вне зависимости от языка.
        Ответить
        • Идея-то плюс-минус нормальная, позволяет решить проблему за пару строчек тупого понятного кода. KISS во всей своей красе.
          Уродство в имплементации: 4 уровня let'ов, cond без t-случая. Говно в том, что на неплохую задумку осуществили через задницу. Это не весело и красиво, это грустно и уродливо (и при этом не на PHP).
          Ответить
    • Поскольку в условии фигурирует "list of numbers", то решение такое:
      (defun ordered-p (l) (or (apply #'< l) (apply #'> l)))
      Ответить
      • Это красивше, но в зависимости от реализации будут ограничения на длину списка. Т.е. По стандарту не сказано сколько именно максимально параметров может принимать функция, но, практически наверняка, если в списке будет ~1000 елементов, такой код не будет работать.
        Ответить
        • Похвалю Конфуция с lispforum'а и себя любимого заодно. Это решение основано на двух полезных фишках: apply и семантике функций < и >. Постижению дао юными дарованиями очень помогает.
          Ну а длинные списки - это да, тут не отвертеться.
          Ответить
      • Ах, да, и кроме того, вы не подумали о том, что в принципе '(1 2 2 3) тоже может удовлетворять условию задачи.
        Ответить
        • Подумал. Там сказано "ascending or descending order". Т.е. "в возрастающем или убывающем порядке". Там не сказано "в неубывающем или невозрастающем порядке".
          Ответить
          • Не забывайте, тут есть еще такой момент, что у вашего варианта есть худший и лучший случаи, худший, это когда: '(1 1 1 1 1 1 1 1 ... 2) то обе ветки (or ...) переберут почти весь список с самого начала ;)
            Собственно вот, вариант конечно гораздо длиннее, но так же учитывает этот момент:
            (defun asc-or-desc (x)
              (if (cdr x)
                  (progn
            	(do ((i (cdr x) (cdr x)))
            	    ((/= (first x) (first i)) x)
            	  (setf x i))
            	(funcall 
            	 (lambda (y pred)
            	   (every (lambda (z)
            		    (when (funcall pred y z)
            		      (setf y z))) (cdr x)))
            	 (first x)
            	 (if (> (first x) (second x)) '>= '<=))) t))
            
            (asc-or-desc '(1 2 3 4)) ; T
            (asc-or-desc '(4 3 2 1)) ; T
            (asc-or-desc '(4 3 1 2)) ; NIL
            (asc-or-desc '(1 1 1 1 2 3)) ; T
            (asc-or-desc '(1 1 1 0 -1 -1)) ; T
            (asc-or-desc '(1 1 1 0 1 1)) ; NIL
            Ответить
            • (asc-or-desc '(1 1))?

              Нельзя ли просто рекурсивно вызвать `asc-or-desc' если car = cadr? И поцчему t в ядренях, а не под if.

              зы... на хаскеле читабельнее (впрочем, полагаю, что и на схеме тоже).
              Ответить
              • 1. А вы как думаете? (я честно не знаю).
                2. Потому что маловероятно, что именно эта ветка будет выбиратся чаще.
                3. CL не гарантирует оптимизации рекурсии, зачем рисковать? :)
                Ответить
                • 1. внутренний цикл рассчитывает определиться со знаком, в случае '(1 1) будет проблема (сначала проверил на `elisp', подтвердил `sbcl').
                  2. Пожалуй, да. Зато симпотичней.
                  3. CL (и стандарты) знаю плохо, но об этом в курсе, впрочем есть и `sbcl'... И вообще, схема же для лаб адекватнее.
                  Ответить
                  • Ну это как деление на ноль - я не знаю, что должно получится, вот и нет ответа :) Вы можете сказать, расположены ли все элементы списка состоящего только из одинаковых элементов в восходящем или нисходящем порядке? Кстати, я вот подумал на счет моего предыдущего коментария по поводу пустого списка - это, в общем, та же ситуация, так что наверное лучше ошибку, чем как-нибудь ответ.
                    На чем писать я не выбирал, да и вообще, язык на котором это написано тут ни при чем, напишите то же самое на Си, тот же эффект будет.

                    ЗЫ. SBCL - Steel Bank Common Lisp - т.е. одна из реализаций CL (Common Lisp).
                    Ответить
                    • > я не знаю, что должно получится, вот и нет ответа :)
                      > (if ... '>= '<=)
                      > asc-or-desc
                      непоследовательно (не нужно asc или desc отдельно, нужно or), этот случай-таки имелся ввиду при написании? ;)

                      > SBCL - Steel Bank Common Lisp - т.е. одна из реализаций CL (Common Lisp)
                      спасибо, но `sbcl' и приводился как пример открытой реализации с "tail-call optimization"
                      Ответить
                      • Как вы можете утверждать, что суждение соответстует хотя бы одному из двух предположений, когда нет возможности установить, что оно наверняка соответствует либо первому, либо второму? Это, как по мне, классический случай нул-гипотезы (т.е., когда отрицание отрицания утверждения не делает утверждение истинным). :)
                        Ответить
                        • Хорошая мина при плохой игре?... ну блин, (asc-or-dsc '(1)) -> t (в вашем варианте)
                          Ответить
                          • А это, я согласен, не правильно :)
                            Ответить
                            • 1. Используется немотонный порядок
                              2. Возвращаемый тип -- Bool
                              (конкретно в этом подходе; можно было бы возвращать 'eq | 'asc | 'desc, не знаю есть ли готовый тип)
                              '(1 1) - упорядочен и по неубыванию, и невозрастанию, имхо, пользующийся функцией ожидал бы t.
                              Ответить
                              • чорт, s/немотонный/нестрогий/
                                Ответить
                              • Кстати, меня тут по этому поводу просветили знающие люди: http://en.wikipedia.org/wiki/Vacuous_truth Из чего следует, что на вопрос "упорядочена ли последовательность из одинаковых чисел (в том числе и пустая последовательность) в восходящем порядке, или нисходящем порядке?" можно ответить утвердительно. Но мне это все равно не нравится :)
                                Ответить
          • Да, и еще, а что если список пустой? Конечно, банальный случай, но будет ошибка.
            Ответить
    • Объясните мне физический смысл данной задачи?
      Ответить
      • Лаба.
        Все функциональные боги считают, что на лиспе лаб не бывает.
        Ответить
        • CL не более функциональный язык, чем JavaScript... И как бы странно было бы игнорировать лабы, если большинство кода, который пишется сегодня на любом из Лиспов, это академия тем или иным образом, а для IT / web / desktop программирования его очень редко используют...
          Ответить

    Добавить комментарий