2010-03-20 1 views
5

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

---- ПОЗДНО ИЗМЕНИТЬ -----

Вот решение, которое я придумал, я уверен, что это не самым ЭФФЕКТИВНАЯ или аккуратным, но я только учусь схема 3 недели, так что будьте легко на меня.

+0

Это домашнее задание? –

+0

похоже: http://stackoverflow.com/questions/1658229/scheme-lisp-nested-loops-and-recursion –

+0

да, это часть домашней работы, мне не обязательно нужен код, мне нужны некоторые рекомендации –

ответ

3
;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)))) 
4
;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)) 

Источник: Scheme/Lisp nested loops and recursion

+1

это должно помочь? Это декартово произведение из 2 наборов, мой вопрос был для n наборов, я знаю, как вычислить его для двух наборов, я не знаю, как сделать это для n –

+2

Объединить 2-заданную версию с чтобы получить версию n-set. В общем случае для ассоциативных операций вы можете определить версию аргумента n в терминах версии 2 аргументов со сгибом. – soegaard

2

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

#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)) 

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

+0

Также, если вы посмотрите на вопрос о том, что Юваль опубликовал Paul Hollingsworth, опубликовал хорошо документированную версию, хотя и не работал в plt-схеме. http://stackoverflow.com/questions/1658229/scheme-lisp-nested-loops-and-recursion/1677386#1677386 – Jake

+0

Что касается решения Cipher, что вы можете сделать для того, чтобы список списков был не установлен? –

+1

Я думаю, что вы имеете в виду, что вы не хотите, чтобы результат был списком неправильных списков (или вложенных пар), а вам нужен список списков. Если это так, самым простым/простейшим/наихудшим способом для этого было бы изменить (cons x y) на (cons x (if (list? Y) y (list y))). Мне это не нравится. Но это не моя домашняя работа ...;) – Jake

6

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

(define (cartesian-product . lists) 
    (fold-right (lambda (xs ys) 
       (append-map (lambda (x) 
           (map (lambda (y) 
            (cons x y)) 
            ys)) 
          xs)) 
       '(()) 
       lists)) 
1

Я попробовал свои силы на то, чтобы элегантное решение Марка H Weaver (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-syntax aka 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))