[room] Вопрос по Lisp

Alexey Voinov =?iso-8859-1?q?voins_=CE=C1_voins=2Eprogram=2Eru?=
Сб Янв 27 14:28:26 MSK 2007


Денис Смирнов <mithraen на altlinux.ru> writes:

> Так и не смог нормально в Lisp решить задачу:
>
> Имеется массив с числами. Надо для него сделать что-то вроде trim --
> получить второй массив, который бы не содержал завершающих нулей.
>
> Я понимаю как её решить тупо (одним циклом для поиска новой длины, потом
> создать новый массив, и также циклом перенести данные), но это же кошмар а
> не код!
Не, ты не понимаешь. :) Тупо - это вот так  (используем srfi-1):

(define (trim-zeroes-right data)
  (reverse (drop-while zero? (reverse data)))

Здесь по сути два полных прохода по списку и один проход только по
нулям в хвосте. Памяти требует немного (оно tail-recursive).

Можно это сократить до гарантированных двух проходов, за счёт
несколько более громоздкого кода:

(define (trim-zeroes-right data)
  (let loop ((data   data)
             (result '())
             (zeroes '()))
    (cond ((null? data)       (reverse result))
          ((zero? (car data)) (loop (cdr data)
                                    result
                                    (cons 0 zeroes)))
          ((null? zeroes)     (loop (cdr data)
                                    (cons (car data) result)
                                    zeroes))
          (else               (loop (cdr data)
                                    (cons (car data)
                                          (append zeroes result))
                                    '())))))

А если данные к нам приходят вектором, то получаем один проход по
нулям и одно копирование субвектора (используем srfi-43):

(define (trim-zeroes-right data)
  (let loop ((newlen (vector-length data)))
    (let ((index (- newlen 1)))
      (cond ((zero? newlen)
             '#())
            ((zero? (vector-ref data index))
             (loop index))
            (else
             (vector-copy data 0 newlen))))))

Т.е. последняя функция осуществляет всего один полный проход по всем
элементам. В чём оно принципиально отличается от решения на C, я не
вижу, честно говоря.


> Можно ли такое решить на голом лиспе, или нужно таки не выпендриваться и
> написать на C?

> ----------------------------------------------------------------------------
> <Voins> посади дебианщика за alt так он сразу локали сломает! :)))
Это ты специально фортунку со мной в такое письмо вставил? :))

-- 
Voins


Подробная информация о списке рассылки smoke-room