Декартово произведение в схеме - PullRequest
5 голосов
/ 21 марта 2010

Я пытался создать функцию, которая возвращает декартово произведение n наборов, в Dr Scheme наборы представлены в виде списка списков, я застрял в этом весь день, хотелось бы несколько руководство, как с чего начать.

---- ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ -----

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

Ответы [ 5 ]

6 голосов
/ 15 декабря 2013

Вот краткая реализация, которая также разработана, чтобы минимизировать размер получающейся структуры в памяти, разделяя хвосты списков компонентов. Использует SRFI-1.

(define (cartesian-product . lists)
  (fold-right (lambda (xs ys)
                (append-map (lambda (x)
                              (map (lambda (y)
                                     (cons x y))
                                   ys))
                            xs))
              '(())
              lists))
4 голосов
/ 21 марта 2010
;compute the list of the (x,y) for y in l
(define (pairs x l)
  (define (aux accu x l)
    (if (null? l)
        accu
        (let ((y (car l))
              (tail (cdr l)))
          (aux (cons (cons x y) accu) x tail))))
  (aux '() x l))

(define (cartesian-product l m)   
  (define (aux accu l)
    (if (null? l) 
        accu
        (let ((x (car l)) 
              (tail (cdr l)))
          (aux (append (pairs x m) accu) tail))))
  (aux '() l))

Источник: Схема / Лисп, вложенные циклы и рекурсия

3 голосов
/ 05 мая 2010
  ;returs a list wich looks like ((nr l[0]) (nr l[1])......)
  (define cart-1(λ(l nr)
      (if (null? l) 
             l 
             (append (list (list nr (car l))) (cart-1 (cdr l) nr)))))

;Cartesian product for 2 lists
(define cart-2(λ(l1 l2)
                (if(null? l2) 
             '() 
             (append (cart-1 l1 (car l2)) (cart-2 l1 (cdr l2))))))

 ;flattens a list containg sublists
(define flatten
(λ(from)
 (cond [(null? from) from]
      [(list? (car from)) (append (flatten (car from)) (flatten (cdr from)))]
      [else (cons (car from) (flatten (cdr from)))])}) 

;applys flatten to every element of l
(define flat
(λ(l)
(if(null? l)
l
(cons (flatten (car l)) (flat (cdr l))))))

;computes Cartesian product for a list of lists by applying cart-2
(define cart
(lambda (liste aux)
 (if (null? liste)
  aux
  (cart (cdr liste) (cart-2 (car liste) aux)))))


(define (cart-n l) (flat (cart (cdr l ) (car l))))
2 голосов
/ 21 марта 2010

Вот мое первое решение (неоптимальное):

#lang scheme
(define (cartesian-product . lofl)
  (define (cartOf2 l1 l2)
    (foldl 
     (lambda (x res) 
       (append 
        (foldl 
         (lambda (y acc) (cons (cons x y) acc)) 
         '() l2) res))
     '() l1))
  (foldl cartOf2 (first lofl) (rest lofl)))

(cartesian-product '(1 2) '(3 4) '(5 6))

В основном вы хотите произвести продукт из списка.

1 голос
/ 19 марта 2017

Я попробовал свои силы, чтобы сделать элегантное решение Марка Уивера (https://stackoverflow.com/a/20591545/7666) более простым для понимания.

import : srfi srfi-1
define : cartesian-product . lists
    define : product-of-two xs ys
         define : cons-on-each-ys x
            map : lambda (y) (cons x y)
                . ys
         append-map cons-on-each-ys
                  . xs
    fold-right product-of-two '(()) lists

Это та же логика, но с именами операций.

Выше приведен синтаксис wisp он же SRFI-119. Эквивалентная простая схема:

(import (srfi srfi-1))
(define (cartesian-product . lists)
    (define (product-of-two xs ys)
         (define (cons-on-each-ys x)
            (map (lambda (y) (cons x y))
                ys))
         (append-map cons-on-each-ys
                  xs))
    (fold-right product-of-two '(()) lists))
...