2016-11-09 1 views
1

J'essaye d'écrire une fonction qui fonctionnera pour une quantité infinie d'ensembles au lieu de la fonction d'intersection normale qui prend seulement deux ensembles. Je l'ai cependant écrit une fonction d'intersection normale (qui ne prend que 2 jeux) qui ressemble à ceci:Schéma - Comment retourner l'intersection d'une quantité INFINITE d'ensembles?

(define intersection 
(lambda (s1 s2 [res '()]) 
    (cond ((set-empty? s1) (make-set res)) 
     ((member? (set-first s1) s2) (intersection (set-rest s1) s2 (set-insert (set-first s1) res))) 
     (else (intersection (set-rest s1) s2 res))))) 

J'ai une fonction cassée d'intersection qui tente de prendre une quantité infinie d'ensembles comme arguments dits « intersection * ». Il ressemble à ceci:

(define intersection* 
(lambda (s1 s2 . r) 
    (cond ((set-empty? r) (intersection s1 s2)) 
     (else (intersection s1 (apply append s2 r)))))) 

Lorsque l'argument 'r' est un argument de repos.

Cependant, j'ai réussi à écrire une fonction Union qui prend une quantité infinie de jeux:

(define union* 
(lambda (s1 [s2 '()] . r) 
    (cond ((set-empty? r) (union s1 s2)) 
     (else (union s1 (apply append s2 r)))))) 

Vous remarquerez que le syndicat * fonction et l'intersection * fonction apparence presque identique. C'est parce que j'ai essayé d'utiliser désespérément la même logique sur la fonction d'intersection * que dans la fonction union *. Je ne m'attendais pas à ce que ça marche non plus ... Je manque d'idées. De l'aide?

+3

Arbitrairement, beaucoup ne sont pas les mêmes que les infiniment nombreux. – molbdnilo

+0

Dès que vous utilisez append sur des ensembles implémentés en tant que listes, vous risquez de casser la propriété que les éléments n'apparaissent qu'une seule fois dans un ensemble. L'union et l'intersection peuvent ne pas se comporter comme prévu. Ici, vous êtes en train d'ajouter des ensembles, ce qui fonctionne pour les syndicats, mais cela n'a aucun sens pour l'intersection. – coredump

Répondre

2

Tant que intersection est implémenté correctement, il suffit de croiser les deux premiers ensembles, puis le résultat avec le jeu suivant, et le suivant, et ainsi de suite. Cela devrait fonctionner:

(define (intersect* s1 s2 . r) 
    (foldl intersect (intersect s1 s2) r)) 

Ce qui précède est le même que:

(define (intersect* s1 s2 . r) 
    (let helper ((acc (intersect s1 s2)) (r r)) 
    (if (null? r) 
     acc 
     (helper (intersect (first r) acc) (rest r))))) 

Bonus: cette version court-circuit et dès qu'il trouve une intersection vide, renvoie:

(define (intersect* s1 s2 . r) 
    (let helper ((acc (intersect s1 s2)) (r r)) 
    (cond ((null? r) acc) 
      ((null? acc) '()) 
      (else (helper (intersect (first r) acc) (rest r)))))) 
+0

Couln't ce fait court-circuiter. par exemple. le deuxième 'acc' est l'ensemble vide que vous pouvez arrêter depuis que vous avez le résultat? – Sylwester

+0

Pas avec une opération «fold» ... une solution basée sur la continuation laissée comme un exercice pour le lecteur: P –

+0

Mais le rouler vous-même 'intersect *' pourrait facilement le faire. – Sylwester