Aquí podría ser tu PUBLICIDAD


¿Cómo se calculan correctamente las diferencias por parejas en Scheme?

votos
2

Dada una lista de números, digamos, (1 3 6 10 0)¿cómo calcula las diferencias (x i - x i-1 ), siempre que tenga x -1 = 0?

(el resultado en este ejemplo debería ser (1 2 3 4 -10))

He encontrado que esta solución es correcta:

(define (pairwise-2 f init l)
  (primero 
   (foldl
    (λ (x acc-data)
      (let ([lista de resultados (primeros datos de acc)]
            [prev-x (segundo acc-data)])
        (lista 
         (añadir lista de resultados (list (fx prev-x)))
         X))) 
    (lista vacía 0)
    l)))

(pairwise-2 - 0 '(1 3 6 10 0))
;; => (1 2 3 4 -10)

Sin embargo, creo que debería haber una solución más elegante aunque no menos flexible. Es feo.

Soy nuevo en la programación funcional y me gustaría escuchar sugerencias sobre el código.

Gracias.

Publicado el 12/03/2009 a las 15:46
fuente por usuario ansgri
En otros idiomas...        العربية       

7 respuestas

votos
2

maptoma múltiples argumentos Entonces solo lo haría

(define (butlast l)
  (reverse (cdr (reverse l))))
(let ((l '(0 1 3 6 10)))
  (map - l (cons 0 (butlast l)))

Si quieres envolverlo en una función, di

(define (pairwise-call f init l)
  (map f l (cons init (butlast l))))

Esto es, por supuesto, no la Pequeña Schemer manera, pero la forma que se evite la repetición de escribir usted mismo. Elija la manera que más le guste.

Respondida el 13/03/2009 a las 03:36
fuente por usuario Nathan Shively-Sanders


Aquí podría ser tu PUBLICIDAD


votos
1

¿Acaso el mapa no termina tan pronto como la lista de argumentos más corta se agota, de todos modos?

(define (pairwise-call diversión init-element lst)
  (mapa divertido lst (cons init-element lst)))

editar : jleedev me informa que este no es el caso en al menos una implementación del Esquema. Esto es un poco molesto, ya que no hay una operación O (1) para cortar el final de una lista.

Quizás podamos usar reduce:

(define (pairwise-call diversión init-element lst)
  (reverso (cdr (reducir (lambda (ab)
                          (append (list b (- b (coche a))) (cdr a)))
                        (contras (lista elemento-init) lst)))))

(Descargo de responsabilidad: hack rápido, no probado)

Respondida el 13/03/2009 a las 03:53
fuente por usuario Svante

votos
1

Haskell me dice que use zip;)

(define (zip-with f xs ys)
  (cond ((or (null? xs) (null? ys)) null)
        (else (cons (f (car xs) (car ys))
                    (zip-with f (cdr xs) (cdr ys))))))
(define (pairwise-diff lst) (zip-with - (cdr lst) lst))

(pairwise-diff (list 1 3 6 10 0))
; gives (2 3 4 -10)
Respondida el 13/03/2009 a las 03:51
fuente por usuario Josh Lee

votos
1

Después de la refinación y la adaptación a PLT Scheme zócalo 's código , creo que la solución casi perfecta sería la siguiente:

(define (pairwise-apply f l0 l)
  (si (¿vacío? l)
      '()
      (let ([l1 (first l)])
        (cons (f l1 l0) (pairwise-apply f l1 (rest l))))))
Respondida el 12/03/2009 a las 04:49
fuente por usuario ansgri

votos
1

No he hecho planes en los años de perro, pero esto me parece un problema típico de tipo poco sensible.

Empecé con una definición básica (ignore la colocación incorrecta de parens; no tengo un intérprete de Scheme a mano:

(define pairwise-diff
    (lambda (list)
      (cond
       ((null? list) '())
       ((atom? list) list)
       (t (pairwise-helper 0 list)))))

Esto maneja los casos de basura nula y atómica y luego delega la caja de carne a un ayudante:

(define pairwise-helper
    (lambda (n list)
       (cond
         ((null? list) '())
         (t
            (let ([one (car list)])
               (cons (- one n) (pairwise-helper one (cdr list))))
         ))))

Podrías reescribir esto usando "si", pero estoy cableado para usar cond.

Aquí hay dos casos: lista nula, que es fácil y todo lo demás. Para todo lo demás, tomo el encabezado de la lista y contrasta esta diferencia con el caso recursivo. No creo que sea mucho más simple.

Respondida el 12/03/2009 a las 04:12
fuente por usuario plinth

votos
0
(define (f l res cur)
  (if (null? l)
    res
    (let ((next (car l)))
      (f (cdr l) (cons (- next cur) res) next))))

(define (do-work l)
  (reverse (f l '() 0)))

(do-work '(1 3 6 10 0))

==> (1 2 3 4 -10)
Respondida el 06/04/2009 a las 01:43
fuente por usuario Fabien

votos
0

Esta es la forma más simple:

(define (solution ls)
  (let loop ((ls (cons 0 ls)))
    (let ((x (cadr ls)) (x_1 (car ls)))
      (if (null? (cddr ls)) (list (- x x_1))
          (cons (- x x_1) (loop (cdr ls)))))))

(display (equal? (solution '(1)) '(1))) (newline)
(display (equal? (solution '(1 5)) '(1 4))) (newline)
(display (equal? (solution '(1 3 6 10 0)) '(1 2 3 4 -10))) (newline)

Escriba la expansión del código para cada uno de los ejemplos para ver cómo funciona.

Si está interesado en comenzar con FP, asegúrese de consultar el Programa de diseño de How. Claro está escrito para gente nueva en programación, pero tiene un montón de buenos modismos de FP dentro.

Respondida el 27/03/2009 a las 07:36
fuente por usuario grettke