Partage
  • Partager sur Facebook
  • Partager sur Twitter

Concatener deux chaines de caracteres sans repet

Sujet résolu
18 janvier 2020 à 16:27:05

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char* argv){
    int i,r,s,p,tab1[100]={0},t=0;
    char* tabdegenome=NULL; // intialisation du tableau final contenant toutes les sequences
    char petitesequence[100]; //Tableau contenant seulement les petites sequences entrer a chaque  fois par l'utilisateur
    do{
    printf("Donner vos fragments de sequences avec un point à la fin si vous avez finis\n");
    scanf("%s",&petitesequence);
    i=p=strlen(petitesequence);
    if(tabdegenome==NULL){ // verrification premiere necessaire pour la creation du tableau
    tabdegenome=malloc(i *sizeof(char)); 
    strcpy(tabdegenome,petitesequence); 
    }
    else{
         int fonction(p){
             for(s=t;s<strlen(tabdegenome);s++){
                for(r=0;r<p;r++){
                if(petitesequence[r]==tabdegenome[strlen(tabdegenome)-s-1]){
                    tab1[100]=r;
                    t=t+1;
                   return fontion(r-1);
                
            }
         }}}
         
        for(s=0;s<t;s++){
            tabdegenome[strlen(tabdegenome)-1-tab1[s]]=0;
            }
        strcat(tabdegenome,petitesequence);
    
    }}
    while(petitesequence[i-1] !='.'); // le -1 pour eviter le caractere '\0'
    tabdegenome[strlen(tabdegenome)-1]=0; // pour supprimer le '.' dernier 
    printf("la fusion de vos sequence est %s",tabdegenome);
    getchar(),getchar();
    }

    


Hey les gars!

Svp j'ai besoin de votre aide!! Donc voila pour un projet de classe j'ai besoin besoin de fusionner deux chaines de caractere sans qu'il y'est de répétition

c'est utile pour recombiner les fragments de sequences de genomes par exemple : CGCAT+CATGAC=CGCATGAC 

j'ai essayé de coder le programme compile parfaitement mais l'executable ne retourne rien je ne sais pas vraiement ou est l'erreur

-
Edité par Erreur 404ppp 18 janvier 2020 à 16:57:02

  • Partager sur Facebook
  • Partager sur Twitter
18 janvier 2020 à 16:40:40

Bonjour,

Le message qui suit est une réponse automatique activée par un membre de l'équipe. Les réponses automatiques leur permettent d'éviter d'avoir à répéter de nombreuses fois la même chose, ce qui leur fait gagner du temps et leur permet de s'occuper des sujets qui méritent plus d'attention.
Nous sommes néanmoins ouverts et si vous avez une question ou une remarque, n'hésitez pas à contacter la personne en question par Message Privé.

Pour plus d'informations, nous vous invitons à lire les règles générales du forum

Merci de colorer votre code à l'aide du bouton Code

Les forums d'Openclassrooms disposent d'une fonctionnalité permettant de colorer et mettre en forme les codes source afin de les rendre plus lisibles et faciles à manipuler par les intervenants. Pour cela, il faut utiliser le bouton Code de l'éditeur, choisir un des langages proposés et coller votre code dans la zone prévue. Si vous utilisez l'éditeur de messages en mode Markdown, il faut utiliser les balises <pre class="brush: cpp;">Votre code ici</pre>.

Liens conseillés

  • Partager sur Facebook
  • Partager sur Twitter
18 janvier 2020 à 19:26:28

Salut,
Je m'intéresse un peu à la génétique et je pense savoir un peu ce que tu veux faire.
CGCAT+CATGAC=CGCATGAC
Tu ne veux pas que la fin de la première séquence CAT ne se répète pas car elle est également au début de la seconde séquence.
J'ai fait un copier-coller et j'ai compilé.
dna.c: In function 'fonction':                                                                                          
dna.c:17:14: warning: type of 'p' defaults to 'int' [-Wimplicit-int]                                                    
          int fonction(p){                                                                                              
dna.c:23:27: warning: implicit declaration of function 'fontion'; did you mean 'fonction'? [-Wimplicit-function-declaration]                                                                                                                    
                    return fontion(r-1);                                                                                
C'est du pattern matching et ce n'est sûrement pas aussi évident.
Il faudrait que j'y pense plus en profondeur.
En espérant qu'un autre saura également t'aider.
  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

18 janvier 2020 à 20:02:16

Pour aider, je pense qu'il faudrait bien comprendre la règle. D'après le message de SîmÕðßž, si les N derniers caractères de la chaîne 1 sont égaux aux N premiers caractères de la chaîne 2 (et dans le même ordre), on ne recopie qu'un groupe. C'est bien ça ?

ABCD + ABCD = ABCDABCD (N = 0)

ABCD + DCBA = ABCDCBA (N = 1)

ABCD + ABCD = ABCD (N = 4)

Ou bien c'est plus compliqué ?

Si c'est comme j'ai compris, je vois bien un algorithme du style :

N = 0
Tant que N < taille de la chaîne 1 et de la chaîne 2 :
    a = les N+1 derniers caractères de la chaîne 1
    b = les N+1 premiers caractères de la chaîne 2
    Si a != b : break // c'est au N précédent qu'on avait a = b (N=0 éventuellement)
    N++
Fin Tant que
Concaténer la chaîne 1 sauf les N derniers avec la chaîne 2    

(Il me semble que les valeurs de N et N+1 sont correctes, mais il faudrait faire des essais à la main, sauf que je n'ai pas le temps, mon but était juste de donner une idée d'algorithme.)

-
Edité par robun 18 janvier 2020 à 20:09:03

  • Partager sur Facebook
  • Partager sur Twitter
19 janvier 2020 à 2:21:17

Seul SîmÕðßž peut répondre à cette question.
Mais mes connaissances de base en génétique me laissent croire que c'est un bon algorithme.
Sauf que dans la pratique, il faut "jumeler" des brins d'ADN beaucoup plus longs.
Il faudrait sans doute un algorithme de jumelage plus sophistiqué que de simplement comparer des chaînes de longueur N.
J'ai trouvé ceci sur le web pour Wikipedia:
https://fr.wikipedia.org/wiki/Algorithme_de_recherche_de_sous-cha%C3%AEne
J'ai déjà programmé l'algorithme de Knuth-Morris-Pratt.
Cependant, l'alphabet de l'ADN est limité à quatre lettres: A, C, G, T. Cet algorithme risque d'être moins efficace.
Et il devrait être modifié pour aller en reculant et tenir compte des ruptures de séquences qui seront acceptées.
Cet algorithme est fait pour de long textes et requière un temps d'initialisation non négligeable.
Si seule la dernière base de la séquence-1 est la même que la premiere de la séquence-2, la copie-t-on seulement une fois?
ATGCG + GAATG = ATGCGAATG?
@SîmÕðßž:
le code me retourne quelque chose, mais la séquence est en double.
ACG + CGTT. donne ACGCGTT
Il faudrait que la syntaxe de la lecture soit plus claire.
Par exemple: séquence-1+séquence-2.
sur une même ligne.
Ou bien que le point soit seul sur une ligne.
Le programme accepte plus de deux chaînes, doit-on faire le couplage des deux côtés des chaînes intermédiaires?

-
Edité par PierrotLeFou 19 janvier 2020 à 8:48:06

  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

19 janvier 2020 à 16:05:07

Pour répondre à  robun le principe est celui que vous avez citer mais c'est bien plus compliquer que l'algo que vous venez de décrire.

En effet pour des séquences de chaines de caractères plus longue prenant l'exemple que j'ai donné auparavant (CGCAT+CATGAC=CGCATGAC)

votre algorithme exécutera le break dès la première vérification car on peut bien remarquer que le dernier caractère de la chaîne 1 n'est pas égale au premier caractère de la chaîne 2 , cela tout en prenant compte qu'on ne sait pas quand est ce que la séquence qui se trouve dans la chaîne 2 (CAT) débutera dans la chaîne 1  mon algo que j'ai cité auparavant me parait vraie mais je ne sais toujours pas pourquoi il n'est pas exécuter. 

 int fonction(p){
             for(s=t;s<strlen(tabdegenome);s++){            
                for(r=0;r<p;r++){
                if(petitesequence[r]==tabdegenome[strlen(tabdegenome)-s-1]){
                    tab1[100]=r; // stocker les positions ou on a trouvé la conditon 
                    t=t+1;       // incrementer le t pour passe au caractere avant dernier le la tabdegenome
                   return fontion(r-1); // recusivité pour pour parcourire la petite sequence jusqua le premier element deja trouvé
                
            }
         }}}
         
        for(s=0;s<t;s++){
            tabdegenome[strlen(tabdegenome)-1-tab1[s]]=0; // vider la premiere chaine d'apres les posistions qu'on avait stocker
            }
        strcat(tabdegenome,petitesequence); 
    

PierrotLeFou je suis bien au courant que mon algrotihme retourne une sequence double (je ne sais toujours pas pourquoi)

Au début j'avais programmé une concaténation directe sans simplification qui celle la 

 int main(int argc, char* argv){
        int i;
        char* tabdegenome=NULL; // intialisation du tableau final contenant toutes les sequences
        char petitesequence[100]; //Tableau contenant seulement les petites sequences entrer a chaque  fois par l'utilisateur
        do{
        printf("Donner vos fragments de sequences avec un point à la fin si vous avez finis\n");
        scanf("%s",&petitesequence);
        i=strlen(petitesequence);
        if(tabdegenome==NULL){
        tabdegenome=malloc(i *sizeof(char)); // verrification premiere necessaire pour la creation du tableau
        strcpy(tabdegenome,petitesequence); 
        }
        else{
        strcat(tabdegenome,petitesequence);
        }
        }
        while(petitesequence[i-1] !='.'); // le -1 pour eviter le caractere '\0'
        tabdegenome[strlen(tabdegenome)-1]=0; // pour supprimer le '.' dernier 
        printf("la fusion de vos sequence est %s",tabdegenome);
        getchar(),getchar(),getchar(),getchar();
        }

 Apres j'ai essayé d'y ajouter un algo de simplification où j'ai ecris la fonction(p) qui a pour but de simplifier les sequences mais mon algo ne l'execute pas

-
Edité par Erreur 404ppp 19 janvier 2020 à 16:33:03

  • Partager sur Facebook
  • Partager sur Twitter
19 janvier 2020 à 17:45:26

Hello,

3 problèmes avant même de commencer à manipuler les données (ils sont présents dès le 1er code):

  • Ligne 7: l' & est en trop
  • Ligne 10: il manque de la place pour le \0 lors du strcpy() de la ligne 11
  • Ligne 14: la ligne 10 ne réserve pas assez de place pour tabdegenome, alors faire des strcat() dans cette variable....

Et un conseil: bien indenter le code, ça aide.

-
Edité par edgarjacobs 19 janvier 2020 à 18:36:54

  • Partager sur Facebook
  • Partager sur Twitter

On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

19 janvier 2020 à 19:04:42

@robun: cela ressemble au problème des expressions régulières où on cherche la chaîne la plus longue satisfaisant le pattern.
@SîmÕðßž:
Tu as défini une fonction au milieu de ton main mais je n'ai pas vu où tu l'appelais. Est-ce une nouvelle norme du C99 que l'appel se fait lors de la définition?
Je préfère qu'elle soit définie à l'extérieur. Cela me semble plus clair.
Petit caprice de ma part ... changes le nom pour "jumeler" par exemple :)
Corriges les problèmes mentionnés par edgarjacobs.
L'algorithme de Knuth-... serait trop lourd ici et sans doute inutile.
L'algorithme pourrait se profiler comme suit:
Prends la première base de la séquence-2 et cherche son ocurence dans la séquence-1 en partant de la fin.
Cherches la position la plus éloignée (indice le plus bas) où tu peux trouver cette base, mais ne dépassant pas la longueur de la séquence-2.
On se place en fait à la position la plus reculée et on commence la recherche à cet endroit et en allant vers la fin.
Tu compares jusqu'à la fin de la séquence-1 ou jusqu'à ce que ça ne marche pas.
Si ça ne marche pas, tu avances vers la fin de la séquence-1 en cherchant l'ocurence suivante de cette première base et tu recommences.
Si tu ne trouves rien, tu ajoutes séquence-2 à la suite de séquence-1.
Si tu trouves un jumelage, tu recopies la séquence-2 à la position où se trouve cette première base dans la séquence-1.
Ou mieux, tu recopies la fin de la séquence-2 (après la fin du jumelage) à la fin de la séquence-1.

-
Edité par PierrotLeFou 20 janvier 2020 à 3:44:34

  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

20 janvier 2020 à 7:47:27

Salut,

Je pense qu'un bon découpage permettrait d'y voir clair pour commencer. Donc on indente le code déjà, puis on fait des fonctions.

Avant de chercher un algo un efficace, je cherche un algo qui fonctionne, même si c'est un brute force tout pourri ou naïf, surtout si je ne sais pas envisager autre chose.

Donc je propose une fonction qui va rechercher la séquence du début du second terme dans le premier terme et va retourner le pointage sur le premier caractère valide du second terme.

pour cela, naïvement, je ferais 2 boucles. pour chaque caractère du second terme, je le cherche dans le premier. dès que ça match, j'avance mes index et compare les 2 caractères suivants, et j'avance mes index tant que ça match, sinon je reprend où j'en étais. si j'arrive au '\0' du premier terme sans que ça n'ait cessé de correspondre, j'ai le point de départ du second terme.

Bonne continuation.
  • Partager sur Facebook
  • Partager sur Twitter

Bonhomme !! | Jeu de plateforme : Prototype.

20 janvier 2020 à 13:07:49

SîmÕðßž a écrit:

Pour répondre à  robun le principe est celui que vous avez citer mais c'est bien plus compliquer que l'algo que vous venez de décrire.

Effectivement, il faut modifier mon algorithme pour qu'il ne s'arrête pas trop vite. En fait, il faut plutôt faire quelque chose de ce genre :

N = 1     // taille de la sous-chaîne examinée
MaxN = 0  // taille de la plus grande sous-chaîne qu'on retrouve dans chaîne 1 et chaîne 2
Tant que N <= taille de la chaîne 1 et de la chaîne 2 :
    a = les N derniers caractères de la chaîne 1
    b = les N premiers caractères de la chaîne 2
    Si a == b : MaxN = N
    N++
Fin Tant que
Concaténer la chaîne 1 sauf les MaxN derniers avec la chaîne 2

C'est sûrement loin d'être optimal, mais l'algorithme me paraît suffisamment simple pour être programmé sans trop faire d'erreur...

(Sinon j'aime bien l'algorithme de drx, clairement plus efficace que le mien.)



-
Edité par robun 21 janvier 2020 à 12:47:59

  • Partager sur Facebook
  • Partager sur Twitter
20 janvier 2020 à 14:58:56

J'ai du code qui marche (pas seulement à peu près) et non indenté avec tests pour les valeurs attendues.
Si je ne me fais pas fusiller à cause du bouton code, je peux le poster ici ...
Je ne teste pas le résultat de mon malloc et j'utilise des 'break' car j'ai horreur des variables logiques de contrôle.

-
Edité par PierrotLeFou 20 janvier 2020 à 15:10:24

  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

20 janvier 2020 à 15:07:54

Re,

fait vite fait pendant ma pause déjeuner. testé tout aussi rapidement :

char* strCutNoRepeat(char*dst, char*src);

int main(void)
{
    char dst[20] = "azertyu",
         src[20] = "tyuiopq";

    strcat(dst, strCutNoRepeat(dst,src));

    printf("%s\n", dst);

    return 0;

}


char* strCutNoRepeat(char*dst, char*src)
{
    int nSrcLen = strlen(src),
        nDstLen = strlen(dst);

    for(int i=0; i<nSrcLen; i++)
    {
        for(int j=0; j<nDstLen; j++)
        {
            int index = 0;

            while(src[i+index] == dst[j+index])
                index++;

            if (dst[j+index] == '\0')
                return &src[i+index];
        }
    }

    return src;//par defaut aucun repeat
}

Si les chaînes sont correctement formattées et tout et tout, il y a probablement quelques vérifs à ajouter et certainement un truc plus élégant à faire qui m'échappe.

Salutations.

-
Edité par drx 20 janvier 2020 à 15:09:13

  • Partager sur Facebook
  • Partager sur Twitter

Bonhomme !! | Jeu de plateforme : Prototype.

20 janvier 2020 à 15:23:01

Alors, je me lance dans la fosse aux lions ...
-
#include <stdio.h>
#include <string.h>
#include <malloc.h>
void jumeler(const char sequence1[], const char sequence2[], const char attendu[]){
int i, j;
char *combiner;
int l1 = (int)strlen(sequence1);
int l2 = (int)strlen(sequence2);
combiner = malloc(l1+l2+1);
strcpy(combiner, sequence1);
i = l1 - l2;
if(i < 0)  i = 0;
for( ; i < l1; i++) {
j = 0;
if(combiner[i] == sequence2[0]) {
for(j = 1; j < l2; j++) {
if(combiner[i+j] != sequence2[j])  break; // On passe à la suivante
}
}
if(i+j == l1) break; // On a jumelé
}
for(j = l1 - i; j < l2; j++) {
combiner[i+j] = sequence2[j];
}
combiner[i+j] = '\0';
printf("sequence1='%s' sequence2='%s' attendu='%s' combiner='%s'\n", sequence1, sequence2, attendu, combiner);
if(strcmp(combiner, attendu) != 0) {
printf("Erreur: valeur calculée difféerente de valeur attendue\n");
}
free(combiner);
}
int main() {
jumeler("acg", "gtt", "acgtt");
jumeler("atcg", "cgtg", "atcgtg");
jumeler("CGCAT", "CATGAC", "CGCATGAC");
jumeler("accct", "gatg", "accctgatg");
jumeler("actgactg", "actgtata", "actgactgtata");
jumeler("atacc", "ccgag", "ataccgag");
}
-
J'aurais pu tester le malloc
'jumeler' aurait pu retourner la chaîne combinée
J'aurais pu écrire une fonction 'tester' séparée de 'juneler'

-
Edité par PierrotLeFou 20 janvier 2020 à 17:22:37

  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

20 janvier 2020 à 17:46:16

@Pierrot: code indenté (à ma manière, mais sans toucher au code)
#include <stdio.h>
#include <string.h>
#include <malloc.h>

void jumeler(const char sequence1[], const char sequence2[], const char attendu[]) {
	int i, j;
	char *combiner;
	int l1 = (int)strlen(sequence1);
	int l2 = (int)strlen(sequence2);
	
	combiner = malloc(l1+l2+1);
	strcpy(combiner, sequence1);
	i = l1 - l2;
	if(i < 0)
		i = 0;
	
	for( ; i < l1; i++) {
		j = 0;
		if(combiner[i] == sequence2[0]) {
			for(j = 1; j < l2; j++) {
				if(combiner[i+j] != sequence2[j])
					break; // On passe à la suivante
			}
		}
		if(i+j == l1)
			break; // On a jumelé
	}

	for(j = l1 - i; j < l2; j++) {
		combiner[i+j] = sequence2[j];
	}
	combiner[i+j] = '\0';
	
	printf("sequence1='%s' sequence2='%s' attendu='%s' combiner='%s'\n", sequence1, sequence2, attendu, combiner);
	if(strcmp(combiner, attendu) != 0) {
		printf("Erreur: valeur calculée difféerente de valeur attendue\n");
	}
	free(combiner);
}

int main() {
	jumeler("acg", "gtt", "acgtt");
	jumeler("atcg", "cgtg", "atcgtg");
	jumeler("CGCAT", "CATGAC", "CGCATGAC");
	jumeler("accct", "gatg", "accctgatg");
	jumeler("actgactg", "actgtata", "actgactgtata");
	jumeler("atacc", "ccgag", "ataccgag");
}

-
Edité par edgarjacobs 20 janvier 2020 à 18:16:26

  • Partager sur Facebook
  • Partager sur Twitter

On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

20 janvier 2020 à 18:30:37

Merci edgarjacobs, je n'aurais pas fait mieux. :)
Un des problèmes est que l'éditeur du forum bouffe les espaces en début de ligne. Ce serait un peu moins affreux si ce n'était pas le cas.
Ce serait facile de s'écrire un petit programme qui fait l'indentation "automatique".
Surtout que je met presque tout entre { et }
Pour un programme qui compile bien et s'exécute correctement, se serait encore plus facile.
Si ce n'était pas le fait que certaines personnes pourraient vouloir faire un copier-coller, je pourrais placer le numéro de ligne moi-même en début de ligne.
  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

20 janvier 2020 à 19:25:10

De rien

-
Edité par edgarjacobs 20 janvier 2020 à 19:39:03

  • Partager sur Facebook
  • Partager sur Twitter

On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

21 janvier 2020 à 11:56:24

Merci a vous tous vos réponses étaient vraiment utile :D
  • Partager sur Facebook
  • Partager sur Twitter
21 janvier 2020 à 13:10:36

Bonjour,

Sujet résolu

Tu peux passer le sujet à "résolu" (bouton en haut à droite du sujet) et cliquer sur les pouces levés des messages qui t'ont aidé⋅e ;)
  • Partager sur Facebook
  • Partager sur Twitter