Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Défi n°4 : Comparer deux listes de mots
Venez relever les défis MATLAB.

Le , par ol9245

43PARTAGES

0  0 
J'ai deux listes de mots en nombre arbitraire et non ordonnées. Par exemple :
Code : Sélectionner tout
1
2
A = {'un' 'deux' 'chateau' 'trois' 'quatre'} ;
B = {'deux' 'quatre' 'six' 'huit' 'dix' 'douze' 'maison' 'bateau' 'chateau'} ;
Le défi est le suivant :
Écrire le code le plus compact(*) possible pour trouver tous les mots communs aux deux listes. c'est-à-dire quelque chose comme ça :
Code : Sélectionner tout
1
2
3
4
5
>>votre formule magique ici

ans = 

    'deux'    'chateau'    'quatre'
-----------------------------------
(*) un code est compact quand il a :
  • moins de boucles (for-end, while-end, ...)
  • moins de lignes de code
  • moins d'affectations (signe =)
  • moins de variables déclarées


Pas besoin de hiérarchiser ces critères car toute amélioration de l'un impacte les autres.

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de magelan
Modérateur https://www.developpez.com
Le 16/06/2012 à 23:39
Salut,

proposition avec cellfun justement :
Code : Sélectionner tout
1
2
3
4
5
A = {'un' 'deux' 'chateau' 'trois' 'quatre'} ;
B = {'deux' 'quatre' 'six' 'huit' 'dix' 'douze' 'maison' 'bateau' 'chateau'} ;
C = repmat(A,size(B,2),1)
D = repmat(B.',1,size(A,2))
E = cellfun(@(x,y)strfind(x,y), C, D,'UniformOutput',false)
ou en compactant encore plus :
Code : Sélectionner tout
1
2
3
A = {'un' 'deux' 'chateau' 'trois' 'quatre'} ;
B = {'deux' 'quatre' 'six' 'huit' 'dix' 'douze' 'maison' 'bateau' 'chateau'} ;
E = cellfun(@(x,y)strfind(x,y), repmat(A,size(B,2),1), repmat(B.',1,size(A,2)),'UniformOutput',false)
Juste une remarque pour préciser qu'un code compact n'est pas toujours un code optimisé et cela peut le rendre parfois illisible.
0  0 
Avatar de ol9245
Membre éprouvé https://www.developpez.com
Le 17/06/2012 à 0:08
Pour un début, la barre est assez haut : une seule instruction

Par contre tu n'obtiens pas la solution (je vais ajouter une précision dans l'énoncé). Je veux les trois chaines communes. Et toi, il te faut encore quelques instructions de plus pour les sortir :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
E = cellfun(@(x,y)strfind(x,y), repmat(A,size(B,2),1), repmat(B.',1,size(A,2)),'UniformOutput',false)

E = 

     []    [1]     []     []     []
     []     []     []     []    [1]
     []     []     []     []     []
     []     []     []     []     []
     []     []     []     []     []
     []     []     []     []     []
     []     []     []     []     []
     []     []     []     []     []
     []     []    [1]     []     []
0  0 
Avatar de duf42
Expert confirmé https://www.developpez.com
Le 17/06/2012 à 11:04
Bonjour,

Je pense que la fonction INTERSECT doit faire l'affaire ici:
Code : Sélectionner tout
1
2
intersect(A,B)
Duf
0  0 
Avatar de ol9245
Membre éprouvé https://www.developpez.com
Le 17/06/2012 à 11:44
Citation Envoyé par duf42 Voir le message
Bonjour,

Je pense que la fonction INTERSECT doit faire l'affaire ici:
Code : Sélectionner tout
1
2
3
4
A = {'un' 'deux' 'chateau' 'trois' 'quatre'} ;
B = {'deux' 'quatre' 'six' 'huit' 'dix' 'douze' 'maison' 'bateau' 'chateau'} ;
intersect(A,B)
Duf

Bravo Duf !

0 boucle
0 variables intermédiaires
1 ligne de code,
1 fonction matlab appelée.

Je propose de t'accorder la victoire à ce défi

Mon idée de départ était celle-ci, que tu as largement battu :
Code : Sélectionner tout
1
2
3
4
A = {'un' 'deux' 'chateau' 'trois' 'quatre'} ;
B = {'deux' 'quatre' 'six' 'huit' 'dix' 'douze' 'maison' 'bateau' 'chateau'} ;
[a, b]=meshgrid(1:numel(A),1:numel(B)) ;
A(any(strcmp(A(a),B(b))))
0  0 
Avatar de ol9245
Membre éprouvé https://www.developpez.com
Le 17/06/2012 à 12:07
@Duf :

J'ai essayé d'appliquer ta solution dans mon code, mais mon problème n'est pas exactement celui que j'ai formulé dans le défi. Le défi est un problème symétrique. Le mien ne l'est pas.
J'ai une liste A de mots de référence (un dictionnaire) et une liste de mots B à chercher dans A. J'ai besoin des index des mots de B dans le dictionnaire A.
Voici un bout de code qui résume les deux solutions, appliquées au problème non symétrique. Qu'en penses-tu ?

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Dico = {'deux' 'quatre' 'six' 'huit' 'dix' 'douze' 'maison' 'bateau' 'chateau'} ;
Chercher = {'deux' 'chateau'} ;

% Duf
M = intersect(Dico, Chercher) ;
fprintf('\nLes mots communs sont -dans le désordre- (recette Duf) : ') ;
fprintf('%s ', M{:}) ;

% OL9245
[a, b]=meshgrid(1:numel(Dico),1:numel(Chercher)) ;
Ix = find(any(strcmp(Dico(a),Chercher(b)))) ;
fprintf('\nLeurs index dans le dico sont -dans l''ordre- (recette OL9245) : ') ;
fprintf('%d ', Ix) ;
fprintf('\n') ;
Résultat :
Code : Sélectionner tout
1
2
Les mots communs sont -dans le désordre- (recette Duf) : chateau deux 
Leurs index dans le dico sont -dans l'ordre- (recette OL9245) : 1 9
0  0 
Avatar de Winjerome
Modérateur https://www.developpez.com
Le 17/06/2012 à 13:00
Salut,

Petit tour du côté de la doc :
[c, ia, ib] = intersect(a, b) also returns column index vectors ia and ib such that c = a(ia) and c = b(ib) (or c = a(ia,:) and c = b(ib,:)).
Donc à partir de là, ce n'est pas dur d'obtenir ces indices

Sinon, deux autres solutions :
Code : Sélectionner tout
1
2
3
4
5
6
A = {'un' 'deux' 'chateau' 'trois' 'quatre'} ;
B = {'deux' 'quatre' 'six' 'huit' 'dix' 'douze' 'maison' 'bateau' 'chateau'} ;

A(ismember(A,B))

A ( cellfun(@(a) any(strcmp(a,B)), A) )
Concernant ta solution ol9245, je rajouterais A(any(strcmp(A(a),B(b)),1)) dans le cas d'un seul mot à chercher.
0  0 
Avatar de Jerome Briot
Rédacteur/Modérateur https://www.developpez.com
Le 17/06/2012 à 13:06
Et pour une solution encore plus spécifique que la solution "générale" de duf42 :

Code : Sélectionner tout
edit intersect
0  0 
Avatar de tanguy4724
Membre habitué https://www.developpez.com
Le 26/06/2012 à 15:34
sans aucun mérite car je ne fais que résumer les messages précédents :

Code : Sélectionner tout
1
2
3
[C,IA,IB] = INTERSECT(Dico, Chercher) ;
IA = sort(IA)
on a ainsi le résultat suivant :


Dico = {'deux' 'quatre' 'six' 'huit' 'dix' 'douze' 'maison' 'bateau' 'chateau'} ;
Chercher = {'deux' 'chateau'} ;
[C,IA,IB] = INTERSECT(Dico, Chercher) ;
IA = sort(IA)

IA =

1 9
0  0 
Avatar de ol9245
Membre éprouvé https://www.developpez.com
Le 26/06/2012 à 18:45
Ca nous fait donc deux lignes, donc autant que ma proposition, mais ++ joli et ++ compact.
0  0