Compara dues seqüències d'ADN introduïdes per l'usuari i mostra el percentatge d'identitat.
#include <stdio.h> /* Inclou la biblioteca estàndard d'entrada/sortida */
/* Necessària per a printf() i scanf() */
#include <string.h> /* Inclou la biblioteca per a funcions de cadenes */
/* Necessària per a strlen() */
#include <ctype.h> /* Inclou la biblioteca per a classificació de caràcters */
/* Necessària per a toupper() */
int main(){ /* Funció principal del programa, punt d'entrada d'execució */
char seq1[501]; /* Array per a la primera seqüència d'ADN */
/* Mida 501: fins a 500 caràcters + '\0' */
char seq2[501]; /* Array per a la segona seqüència d'ADN */
/* Mateixa mida que la primera */
printf("========================================\n");
printf(" COMPARADOR DE SEQUENCIES D'ADN\n");
printf("========================================\n\n");
/* Lectura de les dues seqüències */
printf("Introdueix la primera sequencia d'ADN: "); /* Demana la primera seqüència */
scanf("%500s", seq1); /* Llegeix fins a 500 caràcters */
/* %500s limita la lectura per evitar desbordaments */
printf("Introdueix la segona sequencia d'ADN: "); /* Demana la segona seqüència */
scanf("%500s", seq2); /* Llegeix la segona seqüència */
/* Calcula les longituds de les dues seqüències */
int len1 = strlen(seq1); /* strlen() retorna el nombre de caràcters (sense '\0') */
int len2 = strlen(seq2); /* Longitud de la segona seqüència */
printf("\n=== INFORMACIO DE LES SEQUENCIES ===\n");
printf("Sequencia 1: %s (longitud: %d)\n", seq1, len1); /* Mostra la primera */
printf("Sequencia 2: %s (longitud: %d)\n", seq2, len2); /* Mostra la segona */
/* Converteix ambdues seqüències a majúscules per comparació uniforme */
for(int i = 0; i < len1; i++)
seq1[i] = toupper(seq1[i]); /* toupper() retorna la versió majúscula */
for(int i = 0; i < len2; i++)
seq2[i] = toupper(seq2[i]); /* Converteix cada caràcter */
/* Determina la longitud per a la comparació */
/* Si les seqüències tenen longituds diferents, comparem fins a la més curta */
int min_len = (len1 < len2) ? len1 : len2; /* Operador ternari: si len1 len2) ? len1 : len2; /* La longitud més llarga */
int coincidencies = 0; /* Comptador de posicions on coincideixen */
/* S'inicialitza a 0 per començar el recompte */
int diferencies = 0; /* Comptador de posicions on difereixen */
int gaps = 0; /* Comptador de posicions no comparables (diferència de longitud) */
/* Bucle de comparació nucleòtid per nucleòtid */
for(int i = 0; i < min_len; i++){ /* Recorre fins a la seqüència més curta */
if(seq1[i] == seq2[i]) /* Compara els caràcters a la mateixa posició */
coincidencies++; /* Si són iguals, incrementa coincidències */
else
diferencies++; /* Si són diferents, incrementa diferències */
}
/* Calcula les posicions no comparables (diferència de longitud) */
gaps = max_len - min_len; /* Les posicions extra de la seqüència més llarga */
/* Calcula els percentatges */
float pct_identitat = 0.0; /* Percentatge d'identitat (coincidències) */
if(max_len > 0) /* Evita la divisió per zero */
pct_identitat = (float)coincidencies / max_len * 100;
/* Dividim pel max_len perquè les posicions no comparables compten com a diferències */
float pct_diferencia = 0.0; /* Percentatge de diferències */
if(max_len > 0)
pct_diferencia = (float)diferencies / max_len * 100;
float pct_gaps = 0.0; /* Percentatge de gaps (diferència de longitud) */
if(max_len > 0)
pct_gaps = (float)gaps / max_len * 100;
/* Mostra els resultats de la comparació */
printf("\n=== RESULTATS DE LA COMPARACIO ===\n");
printf("Coincidencies: %d de %d (%.2f%%)\n", coincidencies, max_len, pct_identitat);
printf("Diferencies: %d de %d (%.2f%%)\n", diferencies, max_len, pct_diferencia);
if(gaps > 0)
printf("Gaps (longitud diferent): %d de %d (%.2f%%)\n", gaps, max_len, pct_gaps);
/* Mostra un alineament visual simple */
printf("\n=== ALINEAMENT VISUAL ===\n");
printf("Seq1: %s", seq1); /* Mostra la primera seqüència */
if(len1 < max_len)
for(int i = 0; i < gaps; i++) printf("-"); /* Afegeix guions si és més curta */
printf("\n");
/* Línia de coincidències: '|' si coincideixen, ' ' si no */
printf(" "); /* Espai per alinear */
for(int i = 0; i < min_len; i++){
if(seq1[i] == seq2[i])
printf("|"); /* Barra vertical per a coincidències */
else
printf(" "); /* Espai per a diferències */
}
if(gaps > 0)
for(int i = 0; i < gaps; i++) printf(" "); /* Espais per als gaps */
printf("\n");
printf("Seq2: %s", seq2); /* Mostra la segona seqüència */
if(len2 < max_len)
for(int i = 0; i < gaps; i++) printf("-"); /* Afegeix guions si és més curta */
printf("\n");
/* Classificació del grau de similitud */
printf("\n=== INTERPRETACIO BIOLOGICA ===\n");
if(pct_identitat > 99.0)
printf(" Identitat molt alta: possiblement la mateixa sequencia.\n");
else if(pct_identitat > 90.0)
printf(" Identitat alta: sequencies molt relacionades (mateix gen, especie propera).\n");
else if(pct_identitat > 70.0)
printf(" Identitat moderada: possible relacio evolutiva distant.\n");
else if(pct_identitat > 50.0)
printf(" Identitat baixa: possiblement gens diferents.\n");
else
printf(" Identitat molt baixa: sequencies no relacionades.\n");
return 0; /* Finalitza el programa amb èxit */
}
Llegeix dues seqüències des d'un fitxer i detecta totes les mutacions, indicant si són transicions (A↔G, C↔T) o transversions (altres canvis).
#include <stdio.h> /* Inclou la biblioteca estàndard d'entrada/sortida */
/* Necessària per a printf(), fopen(), fgets(), fclose() */
#include <string.h> /* Inclou la biblioteca per a funcions de cadenes */
/* Necessària per a strlen(), strcpy() */
#include <ctype.h> /* Inclou la biblioteca per a classificació de caràcters */
/* Necessària per a toupper() */
/* Estructura per emmagatzemar informació d'una mutació */
/* Una struct agrupa totes les dades rellevants d'una mutació */
struct Mutacio {
int posicio; /* Posició de la mutació (1-based per a l'usuari) */
char base_original; /* Base en la primera seqüència (seqüència de referència) */
char base_mutada; /* Base en la segona seqüència (seqüència mutada) */
char tipus[20]; /* Tipus de mutació: "Transicio" o "Transversio" */
};
/* Funció per determinar si un canvi és transició o transversió */
/* Retorna 1 si és transició, 0 si és transversió, -1 si és error */
int es_transicio(char b1, char b2){ /* Rep les dues bases a comparar */
/* Converteix a majúscules per comparació uniforme */
b1 = toupper(b1); /* toupper() retorna la versió majúscula */
b2 = toupper(b2);
/* Si les bases són iguals, no és una mutació */
if(b1 == b2) return -1; /* -1 indica "no és mutació" */
/* Transicions: canvi entre purines (A↔G) o entre pirimidines (C↔T) */
/* Purines: Adenina (A) i Guanina (G) */
if((b1 == 'A' && b2 == 'G') || (b1 == 'G' && b2 == 'A'))
return 1; /* És transició (A↔G) */
/* Pirimidines: Citosina (C) i Timina (T) */
if((b1 == 'C' && b2 == 'T') || (b1 == 'T' && b2 == 'C'))
return 1; /* És transició (C↔T) */
/* Qualsevol altre canvi és transversió */
/* Exemples: A↔C, A↔T, G↔C, G↔T (canvi purina↔pirimidina) */
return 0; /* És transversió */
}
/* Funció per classificar la mutació en text */
const char* nom_tipus_mutacio(int tipus){ /* Rep 1 (transició) o 0 (transversió) */
if(tipus == 1)
return "Transicio"; /* Canvi dins del mateix grup químic */
else if(tipus == 0)
return "Transversio"; /* Canvi entre grups químics diferents */
else
return "Desconegut"; /* Per seguretat */
}
int main(){ /* Funció principal */
char seq1[501]; /* Array per a la seqüència de referència */
char seq2[501]; /* Array per a la seqüència a comparar */
struct Mutacio mutacions[500]; /* Array per emmagatzemar les mutacions */
/* Com a màxim 500 mutacions (una per posició) */
int total_mutacions = 0; /* Comptador de mutacions trobades */
int transicions = 0; /* Comptador de transicions */
int transversions = 0; /* Comptador de transversions */
printf("========================================\n");
printf(" DETECTOR DE MUTACIONS PUNTUALS\n");
printf("========================================\n\n");
/* Intenta obrir el fitxer de seqüències */
FILE *fitxer = fopen("sequencies_mutacions.txt", "r"); /* Obre en mode lectura */
if(fitxer == NULL){ /* Si el fitxer no existeix */
printf("No s'ha trobat el fitxer 'sequencies_mutacions.txt'.\n");
printf("Creant fitxer d'exemple...\n");
/* Crea un fitxer d'exemple amb dues seqüències */
fitxer = fopen("sequencies_mutacions.txt", "w"); /* Obre en mode escriptura */
if(fitxer == NULL){
printf("Error en crear el fitxer.\n");
return 1;
}
/* Escriu dues seqüències d'exemple amb diverses mutacions */
fprintf(fitxer, "ATGGCGATCGATCG\n"); /* Primera seqüència (referència) */
fprintf(fitxer, "ATGGCAATCGATGG\n"); /* Segona seqüència (amb mutacions) */
fclose(fitxer);
/* Torna a obrir en mode lectura */
fitxer = fopen("sequencies_mutacions.txt", "r");
if(fitxer == NULL) return 1;
printf("Fitxer d'exemple creat. Executa de nou el programa.\n");
fclose(fitxer);
return 0;
}
/* Llegeix les dues seqüències del fitxer */
fgets(seq1, 500, fitxer); /* Llegeix la primera línia (primera seqüència) */
fgets(seq2, 500, fitxer); /* Llegeix la segona línia (segona seqüència) */
fclose(fitxer); /* Tanca el fitxer */
/* Elimina els salts de línia de les seqüències llegides */
int len1 = strlen(seq1); /* Longitud de la primera seqüència */
if(len1 > 0 && seq1[len1-1] == '\n')
seq1[len1-1] = '\0'; /* Substitueix '\n' per '\0' */
int len2 = strlen(seq2); /* Longitud de la segona seqüència */
if(len2 > 0 && seq2[len2-1] == '\n')
seq2[len2-1] = '\0'; /* Substitueix '\n' per '\0' */
/* Actualitza les longituds després d'eliminar '\n' */
len1 = strlen(seq1);
len2 = strlen(seq2);
/* Converteix a majúscules */
for(int i = 0; i < len1; i++) seq1[i] = toupper(seq1[i]);
for(int i = 0; i < len2; i++) seq2[i] = toupper(seq2[i]);
printf("Sequencia de referencia: %s (longitud: %d)\n", seq1, len1);
printf("Sequencia a comparar: %s (longitud: %d)\n\n", seq2, len2);
/* Determina la longitud mínima per a la comparació */
int min_len = (len1 < len2) ? len1 : len2;
if(len1 != len2)
printf("NOTA: Les sequencies tenen longituds diferents. Es compararan %d posicions.\n\n", min_len);
/* Compara les seqüències nucleòtid per nucleòtid */
printf("=== MUTACIONS DETECTADES ===\n");
printf("%-10s %-10s %-10s %-15s\n", "POSICIO", "ORIGINAL", "MUTADA", "TIPUS");
printf("---------------------------------------------\n");
for(int i = 0; i < min_len; i++){ /* Recorre les posicions comparables */
if(seq1[i] != seq2[i]){ /* Si les bases són diferents (hi ha mutació) */
int tipus = es_transicio(seq1[i], seq2[i]); /* Determina el tipus */
/* Emmagatzema la informació de la mutació */
mutacions[total_mutacions].posicio = i + 1; /* Posició 1-based */
mutacions[total_mutacions].base_original = seq1[i];
mutacions[total_mutacions].base_mutada = seq2[i];
strcpy(mutacions[total_mutacions].tipus, nom_tipus_mutacio(tipus));
/* Mostra la mutació per pantalla */
printf("%-10d %c -> %c %-15s\n",
i + 1, seq1[i], seq2[i], nom_tipus_mutacio(tipus));
/* Actualitza els comptadors segons el tipus */
if(tipus == 1)
transicions++; /* Incrementa transicions */
else if(tipus == 0)
transversions++; /* Incrementa transversions */
total_mutacions++; /* Incrementa el total de mutacions */
}
}
/* Mostra el resum estadístic */
printf("\n=== RESUM ESTADISTIC ===\n");
printf("Total de posicions comparades: %d\n", min_len);
printf("Total de mutacions: %d\n", total_mutacions);
printf(" Transicions: %d (%.1f%%)\n",
transicions,
total_mutacions > 0 ? (float)transicions/total_mutacions*100 : 0);
printf(" Transversions: %d (%.1f%%)\n",
transversions,
total_mutacions > 0 ? (float)transversions/total_mutacions*100 : 0);
/* Calcula la taxa de mutació */
float taxa_mutacio = (float)total_mutacions / min_len * 100;
printf("\nTaxa de mutacio: %.2f%%\n", taxa_mutacio);
/* Interpretació de la relació transicions/transversions */
printf("\n=== INTERPRETACIO BIOLOGICA ===\n");
if(transversions > 0){
float ratio = (float)transicions / transversions;
printf("Ratio transicions/transversions: %.2f\n", ratio);
if(ratio > 2.0)
printf(" Ratio alt: esperat en sequencies relacionades (purificacio).\n");
else if(ratio > 1.0)
printf(" Ratio normal: mutacions aleatories tipiques.\n");
else
printf(" Ratio baix: possible saturacio de mutacions.\n");
}
/* Informació sobre la importància biològica */
printf("\n=== INFORMACIO ADDICIONAL ===\n");
printf("Transicions (A<->G, C<->T):\n");
printf(" - Canvi dins del mateix grup quimic (purina<->purina o pirimidina<->pirimidina)\n");
printf(" - Mes frequents en l'evolucio molecular\n");
printf(" - Menys probables de causar canvis en la proteina\n\n");
printf("Transversions (altres canvis):\n");
printf(" - Canvi entre grups quimics diferents (purina<->pirimidina)\n");
printf(" - Menys frequents pero mes impactants\n");
printf(" - Major probabilitat de canviar l'aminoacid codificat\n");
return 0; /* Finalitza el programa */
}
Implementa una matriu de substitució simple per a aminoàcids (hidrofòbic, polar, carregat) i calcula la similitud entre dues proteïnes curtes.
#include <stdio.h> /* Inclou la biblioteca estàndard d'entrada/sortida */
/* Necessària per a printf() i scanf() */
#include <string.h> /* Inclou la biblioteca per a funcions de cadenes */
/* Necessària per a strlen() i strchr() */
#include <ctype.h> /* Inclou la biblioteca per a classificació de caràcters */
/* Necessària per a toupper() */
/* Constants per a les categories d'aminoàcids */
/* #define crea constants simbòliques que el compilador substitueix */
#define HIDROFOBIC 0 /* Aminoàcids hidrofòbics (apolars) */
#define POLAR 1 /* Aminoàcids polars (sense càrrega) */
#define CARREGAT 2 /* Aminoàcids carregats (positiva o negativa) */
#define ESPECIAL 3 /* Aminoàcids amb propietats especials (cisteïna, glicina, prolina) */
/* Funció per classificar un aminoàcid en una categoria */
/* Retorna la categoria: HIDROFOBIC, POLAR, CARREGAT o ESPECIAL */
int categoria_aminoacid(char aa){ /* Rep la lletra de l'aminoàcid (codi d'una lletra) */
aa = toupper(aa); /* Converteix a majúscula per uniformitat */
/* Classificació basada en les propietats químiques de la cadena lateral */
switch(aa){
/* Aminoàcids hidrofòbics: cadenes laterals apolars */
case 'A': case 'V': case 'L': case 'I': /* Alanina, Valina, Leucina, Isoleucina */
case 'M': case 'F': case 'W': /* Metionina, Fenilalanina, Triptòfan */
return HIDROFOBIC; /* Retorna la constant HIDROFOBIC (0) */
/* Aminoàcids polars: cadenes laterals polars sense càrrega */
case 'S': case 'T': case 'N': case 'Q': /* Serina, Treonina, Asparagina, Glutamina */
case 'Y': /* Tirosina */
return POLAR; /* Retorna la constant POLAR (1) */
/* Aminoàcids carregats: cadenes laterals amb càrrega elèctrica */
case 'K': case 'R': /* Lisina, Arginina (càrrega positiva) */
case 'D': case 'E': /* Aspartat, Glutamat (càrrega negativa) */
case 'H': /* Histidina (càrrega positiva a pH fisiològic) */
return CARREGAT; /* Retorna la constant CARREGAT (2) */
/* Aminoàcids especials: propietats úniques */
case 'C': /* Cisteïna: forma ponts disulfur */
case 'G': /* Glicina: molt petita, flexible */
case 'P': /* Prolina: estructura rígida, trenca hèlixs */
return ESPECIAL; /* Retorna la constant ESPECIAL (3) */
default:
return -1; /* Aminoàcid no reconegut */
}
}
/* Funció per obtenir la puntuació de similitud entre dos aminoàcids */
/* Retorna: 3 = idèntics, 2 = mateixa categoria, 1 = categories compatibles, 0 = molt diferents, -1 = error */
int puntuacio_similitud(char aa1, char aa2){ /* Rep dues lletres d'aminoàcids */
aa1 = toupper(aa1); /* Converteix a majúscula */
aa2 = toupper(aa2);
/* Si són el mateix aminoàcid, màxima puntuació */
if(aa1 == aa2) return 3; /* Identitat: puntuació màxima */
int cat1 = categoria_aminoacid(aa1); /* Obté la categoria del primer */
int cat2 = categoria_aminoacid(aa2); /* Obté la categoria del segon */
/* Si algun no és reconegut, retorna -1 */
if(cat1 < 0 || cat2 < 0) return -1;
/* Si pertanyen a la mateixa categoria, bona puntuació */
if(cat1 == cat2) return 2; /* Mateixa categoria: canvi conservatiu */
/* Matriu de compatibilitat entre categories */
/* Hidrofòbic <-> Polar: poden ser compatibles en certs contextos */
if((cat1 == HIDROFOBIC && cat2 == POLAR) ||
(cat1 == POLAR && cat2 == HIDROFOBIC))
return 1; /* Categories compatibles: canvi semi-conservatiu */
/* Polar <-> Carregat: poden ser compatibles */
if((cat1 == POLAR && cat2 == CARREGAT) ||
(cat1 == CARREGAT && cat2 == POLAR))
return 1; /* Categories compatibles */
/* Hidrofòbic <-> Carregat: generalment incompatible */
if((cat1 == HIDROFOBIC && cat2 == CARREGAT) ||
(cat1 == CARREGAT && cat2 == HIDROFOBIC))
return 0; /* Categories incompatibles: canvi no conservatiu */
/* Especial amb qualsevol altre: baixa compatibilitat */
return 1; /* Per defecte, puntuació intermèdia */
}
/* Funció per obtenir el nom de la categoria en text */
const char* nom_categoria(int cat){ /* Rep el número de categoria */
switch(cat){
case HIDROFOBIC: return "Hidrofobic"; /* Apolar */
case POLAR: return "Polar"; /* Polar sense càrrega */
case CARREGAT: return "Carregat"; /* Amb càrrega */
case ESPECIAL: return "Especial"; /* Propietats úniques */
default: return "Desconegut"; /* No classificat */
}
}
int main(){ /* Funció principal */
char prot1[101]; /* Array per a la primera proteïna */
char prot2[101]; /* Array per a la segona proteïna */
printf("========================================\n");
printf(" CALCUL DE SIMILITUD ENTRE PROTEINES\n");
printf("========================================\n\n");
printf("Introdueix la primera sequencia d'aminoacids: ");
scanf("%100s", prot1); /* Llegeix la primera seqüència */
printf("Introdueix la segona sequencia d'aminoacids: ");
scanf("%100s", prot2); /* Llegeix la segona seqüència */
int len1 = strlen(prot1); /* Longitud de la primera */
int len2 = strlen(prot2); /* Longitud de la segona */
/* Converteix a majúscules */
for(int i = 0; i < len1; i++) prot1[i] = toupper(prot1[i]);
for(int i = 0; i < len2; i++) prot2[i] = toupper(prot2[i]);
printf("\n=== SEQUENCIES ===\n");
printf("Proteina 1: %s (longitud: %d)\n", prot1, len1);
printf("Proteina 2: %s (longitud: %d)\n", prot2, len2);
/* Determina la longitud per a la comparació */
int min_len = (len1 < len2) ? len1 : len2;
int max_len = (len1 > len2) ? len1 : len2;
/* Variables per a l'anàlisi de similitud */
int puntuacio_total = 0; /* Suma de puntuacions */
int puntuacio_maxima = min_len * 3; /* Màxima puntuació possible (tots idèntics) */
int identics = 0; /* Comptador de posicions idèntiques */
int conservatius = 0; /* Comptador de canvis conservatius */
int no_conservatius = 0; /* Comptador de canvis no conservatius */
printf("\n=== ALINEAMENT I PUNTUACIO ===\n");
printf("%-5s %-5s %-5s %-12s %-12s\n", "POS", "AA1", "AA2", "PUNTUACIO", "TIPUS");
printf("------------------------------------------\n");
for(int i = 0; i < min_len; i++){ /* Recorre les posicions comparables */
int punt = puntuacio_similitud(prot1[i], prot2[i]); /* Calcula la puntuació */
puntuacio_total += punt; /* Acumula la puntuació */
/* Classifica el tipus de coincidència */
const char *tipus = ""; /* Text descriptiu */
if(punt == 3){
tipus = "Identic";
identics++;
} else if(punt == 2){
tipus = "Conservatiu";
conservatius++;
} else if(punt == 1){
tipus = "Semi-conserv.";
conservatius++; /* Comptabilitzat com a conservatiu */
} else {
tipus = "No conserv.";
no_conservatius++;
}
printf("%-5d %-5c %-5c %-12d %-12s (cat: %s <-> %s)\n",
i + 1, prot1[i], prot2[i], punt, tipus,
nom_categoria(categoria_aminoacid(prot1[i])),
nom_categoria(categoria_aminoacid(prot2[i])));
}
/* Calcula el percentatge de similitud */
float pct_similitud = 0.0;
if(puntuacio_maxima > 0)
pct_similitud = (float)puntuacio_total / puntuacio_maxima * 100;
float pct_identitat = 0.0;
if(min_len > 0)
pct_identitat = (float)identics / min_len * 100;
/* Mostra el resum */
printf("\n=== RESUM DE SIMILITUD ===\n");
printf("Posicions comparades: %d\n", min_len);
printf("Puntuacio total: %d de %d possibles\n", puntuacio_total, puntuacio_maxima);
printf("Percentatge de similitud: %.1f%%\n", pct_similitud);
printf("\nDesglossament:\n");
printf(" Identics: %d (%.1f%%)\n", identics, pct_identitat);
printf(" Conservatius: %d\n", conservatius);
printf(" No conservatius: %d\n", no_conservatius);
if(len1 != len2)
printf("\nNota: Les proteines tenen longituds diferents (%d vs %d).\n", len1, len2);
/* Interpretació biològica */
printf("\n=== INTERPRETACIO ===\n");
if(pct_identitat > 70)
printf(" Alta identitat: probablement proteines homologues.\n");
else if(pct_identitat > 40)
printf(" Identitat moderada: possible relacio evolutiva distant.\n");
else if(pct_similitud > 50)
printf(" Baixa identitat pero similitud estructural conservada.\n");
else
printf(" Baixa similitud: probablement proteines no relacionades.\n");
return 0; /* Finalitza el programa */
}
Escriu un programa complet que llegeixi dues seqüències, generi un alineament visual, detecti mutacions i guardi un informe.
#include <stdio.h> /* Inclou la biblioteca estàndard d'entrada/sortida */
/* Necessària per a printf(), scanf(), fopen(), fprintf(), fgets(), fclose() */
#include <stdlib.h> /* Inclou la biblioteca estàndard */
/* Necessària per a malloc(), free() */
#include <string.h> /* Inclou la biblioteca per a funcions de cadenes */
/* Necessària per a strlen(), strcpy(), strncpy(), strcat(), strchr() */
#include <ctype.h> /* Inclou la biblioteca per a classificació de caràcters */
/* Necessària per a toupper() */
/* Constants del programa */
#define MAX_SEQ 2000 /* Longitud màxima de cada seqüència */
#define MAX_MUTACIONS 1000 /* Nombre màxim de mutacions a detectar */
#define MAX_LINIA 2000 /* Longitud màxima d'una línia del fitxer */
/* Estructura per emmagatzemar informació d'una mutació */
typedef struct {
int posicio; /* Posició de la mutació (1-based) */
char base_original; /* Base en la seqüència de referència */
char base_mutada; /* Base en la seqüència comparada */
char tipus[20]; /* "Transicio" o "Transversio" */
char classe[30]; /* "Substitucio", "Insercio" o "Delecio" */
} Mutacio; /* 'Mutacio' és ara un tipus vàlid gràcies a typedef */
/* Variables globals */
char seq1[MAX_SEQ]; /* Primera seqüència (referència) */
char seq2[MAX_SEQ]; /* Segona seqüència (a comparar) */
int len1 = 0; /* Longitud de la primera seqüència */
int len2 = 0; /* Longitud de la segona seqüència */
Mutacio mutacions[MAX_MUTACIONS]; /* Array de mutacions */
int total_mutacions = 0; /* Comptador de mutacions */
int transicions_count = 0; /* Comptador de transicions */
int transversions_count = 0; /* Comptador de transversions */
int substitucions = 0; /* Comptador de substitucions */
int insercions = 0; /* Comptador d'insercions */
int delecions = 0; /* Comptador de delecions */
/* Prototips de les funcions principals */
int carregar_sequencies(const char *nom_fitxer); /* Carrega seqüències del fitxer */
void comparar_sequencies(); /* Compara i detecta mutacions */
void mostrar_alineament(); /* Genera alineament visual */
void mostrar_mutacions(); /* Llista les mutacions */
void mostrar_resum(); /* Mostra resum estadístic */
void guardar_informe(const char *nom_fitxer); /* Desa l'informe en fitxer */
/* Funcions auxiliars */
int es_transicio(char b1, char b2); /* Determina si és transició */
const char* obtenir_tipus_mutacio(char b1, char b2); /* Classifica la mutació */
int main(){ /* Funció principal del programa */
char nom_fitxer[200]; /* Nom del fitxer d'entrada */
int opcio; /* Opció del menú */
printf("========================================\n");
printf(" ALINEADOR DE SEQUENCIES D'ADN\n");
printf("========================================\n\n");
/* Demana el fitxer amb les seqüències */
printf("Nom del fitxer amb les sequencies: ");
scanf("%199s", nom_fitxer);
/* Carrega les seqüències */
if(carregar_sequencies(nom_fitxer) == 0){
printf("Error en carregar les sequencies. Finalitzant.\n");
return 1;
}
printf("Sequencies carregades correctament.\n");
printf(" Sequencia 1 (referencia): %d nucleotids\n", len1);
printf(" Sequencia 2 (comparada): %d nucleotids\n", len2);
/* Compara les seqüències i detecta mutacions */
comparar_sequencies();
/* Menú d'opcions */
do{
printf("\n--- MENU D'OPCIONS ---\n");
printf(" 1. Mostrar sequencies originals\n");
printf(" 2. Mostrar alineament visual\n");
printf(" 3. Llistar totes les mutacions\n");
printf(" 4. Mostrar resum estadistic\n");
printf(" 5. Guardar informe complet\n");
printf(" 0. Sortir\n");
printf(" Opcio: ");
scanf("%d", &opcio);
getchar(); /* Consumeix el '\n' */
switch(opcio){
case 1:
printf("\nSequencia 1: %s\n", seq1);
printf("Sequencia 2: %s\n", seq2);
break;
case 2:
mostrar_alineament();
break;
case 3:
mostrar_mutacions();
break;
case 4:
mostrar_resum();
break;
case 5:
guardar_informe("informe_mutacions.txt");
break;
case 0:
printf("\nAdeu!\n");
break;
default:
printf("Opcio no valida.\n");
}
} while(opcio != 0);
return 0; /* Finalitza el programa */
}
/* Funció per carregar les seqüències des d'un fitxer */
int carregar_sequencies(const char *nom_fitxer){
FILE *fitxer = fopen(nom_fitxer, "r"); /* Obre en mode lectura */
if(fitxer == NULL){
printf("Error: No s'ha pogut obrir el fitxer '%s'.\n", nom_fitxer);
printf("Creant fitxer d'exemple 'seq_alinear.txt'...\n");
/* Crea un fitxer d'exemple amb dues seqüències */
fitxer = fopen(nom_fitxer, "w");
if(fitxer == NULL) return 0;
/* Escriu dues seqüències amb diverses mutacions */
fprintf(fitxer, ">sequencia_referencia\n");
fprintf(fitxer, "ATGGCGATCGATCGATCG\n");
fprintf(fitxer, ">sequencia_comparada\n");
fprintf(fitxer, "ATGGCAATCGATGGATCG\n");
fclose(fitxer);
printf("Fitxer d'exemple creat. Executa de nou el programa.\n");
return 0;
}
char linia[MAX_LINIA];
int llegint_seq1 = 1; /* Bandera: 1 = llegint primera seqüència, 0 = segona */
seq1[0] = '\0'; /* Inicialitza les seqüències com a buides */
seq2[0] = '\0';
/* Llegeix el fitxer línia per línia */
while(fgets(linia, MAX_LINIA, fitxer) != NULL){
/* Elimina el salt de línia */
int len = strlen(linia);
if(len > 0 && linia[len-1] == '\n')
linia[len-1] = '\0';
/* Si és una capçalera FASTA, canvia a la segona seqüència */
if(linia[0] == '>'){
if(strlen(seq1) > 0) /* Si ja tenim la primera seqüència */
llegint_seq1 = 0; /* Passem a llegir la segona */
continue; /* Ignora la línia de capçalera */
}
/* Converteix a majúscules i afegeix a la seqüència corresponent */
for(int i = 0; linia[i] != '\0'; i++)
linia[i] = toupper(linia[i]);
if(llegint_seq1)
strcat(seq1, linia); /* Afegeix a la primera seqüència */
else
strcat(seq2, linia); /* Afegeix a la segona seqüència */
}
fclose(fitxer);
/* Filtra només les bases vàlides (A, C, G, T) */
char temp1[MAX_SEQ], temp2[MAX_SEQ];
int j1 = 0, j2 = 0;
for(int i = 0; seq1[i] != '\0'; i++)
if(strchr("ACGT", seq1[i]) != NULL) /* strchr() busca un caràcter en una cadena */
temp1[j1++] = seq1[i]; /* Conserva només bases vàlides */
temp1[j1] = '\0'; /* Finalitza la cadena filtrada */
for(int i = 0; seq2[i] != '\0'; i++)
if(strchr("ACGT", seq2[i]) != NULL)
temp2[j2++] = seq2[i];
temp2[j2] = '\0';
strcpy(seq1, temp1); /* Copia les seqüències filtrades */
strcpy(seq2, temp2);
len1 = strlen(seq1); /* Calcula les longituds */
len2 = strlen(seq2);
return (len1 > 0 && len2 > 0) ? 1 : 0; /* Retorna 1 si ambdues tenen dades */
}
/* Funció per comparar les seqüències i detectar mutacions */
void comparar_sequencies(){
total_mutacions = 0;
transicions_count = 0;
transversions_count = 0;
substitucions = 0;
insercions = 0;
delecions = 0;
int min_len = (len1 < len2) ? len1 : len2; /* Longitud mínima */
/* Detecta substitucions (posicions comparables amb bases diferents) */
for(int i = 0; i < min_len; i++){
if(seq1[i] != seq2[i]){ /* Si les bases són diferents */
Mutacio *m = &mutacions[total_mutacions]; /* Punter a la mutació actual */
m->posicio = i + 1; /* Posició 1-based */
m->base_original = seq1[i];
m->base_mutada = seq2[i];
strcpy(m->classe, "Substitucio");
/* Determina el tipus (transició o transversió) */
if(es_transicio(seq1[i], seq2[i])){
strcpy(m->tipus, "Transicio");
transicions_count++;
} else {
strcpy(m->tipus, "Transversio");
transversions_count++;
}
total_mutacions++;
substitucions++;
}
}
/* Detecta insercions (seq2 més llarga) */
if(len2 > len1){
for(int i = min_len; i < len2; i++){
Mutacio *m = &mutacions[total_mutacions];
m->posicio = i + 1;
m->base_original = '-'; /* No hi ha base en la referència */
m->base_mutada = seq2[i];
strcpy(m->tipus, "Insercio");
strcpy(m->classe, "Insercio");
total_mutacions++;
insercions++;
}
}
/* Detecta delecions (seq2 més curta) */
if(len1 > len2){
for(int i = min_len; i < len1; i++){
Mutacio *m = &mutacions[total_mutacions];
m->posicio = i + 1;
m->base_original = seq1[i];
m->base_mutada = '-'; /* No hi ha base en la comparada */
strcpy(m->tipus, "Delecio");
strcpy(m->classe, "Delecio");
total_mutacions++;
delecions++;
}
}
}
/* Funció per mostrar l'alineament visual */
void mostrar_alineament(){
int max_len = (len1 > len2) ? len1 : len2;
printf("\n=== ALINEAMENT VISUAL ===\n\n");
/* Mostra la primera seqüència en blocs de 50 caràcters */
printf("Ref: ");
for(int bloc = 0; bloc < max_len; bloc += 50){
for(int i = bloc; i < bloc + 50 && i < max_len; i++){
if(i < len1)
printf("%c", seq1[i]); /* Base de la referència */
else
printf("-"); /* Gap si la referència és més curta */
}
printf("\n ");
}
printf("\n");
/* Línia de coincidències */
printf(" ");
for(int bloc = 0; bloc < max_len; bloc += 50){
for(int i = bloc; i < bloc + 50 && i < max_len; i++){
if(i < len1 && i < len2){
if(seq1[i] == seq2[i])
printf("|"); /* Coincidència */
else
printf(" "); /* Diferència */
} else {
printf(" "); /* Gap */
}
}
printf("\n ");
}
printf("\n");
/* Mostra la segona seqüència */
printf("Cmp: ");
for(int bloc = 0; bloc < max_len; bloc += 50){
for(int i = bloc; i < bloc + 50 && i < max_len; i++){
if(i < len2)
printf("%c", seq2[i]); /* Base de la comparada */
else
printf("-"); /* Gap si la comparada és més curta */
}
printf("\n ");
}
printf("\n");
/* Llegenda */
printf("\n | = coincidencia espai = diferencia - = gap\n");
/* Estadístiques ràpides */
int coincidencies = 0;
int min_len = (len1 < len2) ? len1 : len2;
for(int i = 0; i < min_len; i++)
if(seq1[i] == seq2[i]) coincidencies++;
printf("\n Coincidencies: %d/%d (%.1f%%)\n",
coincidencies, max_len,
max_len > 0 ? (float)coincidencies/max_len*100 : 0);
}
/* Funció per llistar totes les mutacions */
void mostrar_mutacions(){
if(total_mutacions == 0){
printf("\nNo s'han detectat mutacions.\n");
return;
}
printf("\n=== MUTACIONS DETECTADES (%d total) ===\n\n", total_mutacions);
printf("%-8s %-8s %-8s %-15s %-15s\n", "POSICIO", "ORIG.", "MUT.", "TIPUS", "CLASSE");
printf("-----------------------------------------------------\n");
for(int i = 0; i < total_mutacions; i++){
printf("%-8d %-8c %-8c %-15s %-15s\n",
mutacions[i].posicio,
mutacions[i].base_original,
mutacions[i].base_mutada,
mutacions[i].tipus,
mutacions[i].classe);
}
}
/* Funció per mostrar el resum estadístic */
void mostrar_resum(){
printf("\n=== RESUM ESTADISTIC ===\n\n");
printf("--- INFORMACIO GENERAL ---\n");
printf("Longitud sequencia de referencia: %d nucleotids\n", len1);
printf("Longitud sequencia comparada: %d nucleotids\n", len2);
int min_len = (len1 < len2) ? len1 : len2;
int max_len = (len1 > len2) ? len1 : len2;
int coincidencies = 0;
for(int i = 0; i < min_len; i++)
if(seq1[i] == seq2[i]) coincidencies++;
printf("Posicions comparades: %d\n", min_len);
printf("Coincidencies: %d\n", coincidencies);
printf("Percentatge d'identitat: %.2f%%\n",
max_len > 0 ? (float)coincidencies/max_len*100 : 0);
printf("\n--- CLASSIFICACIO DE MUTACIONS ---\n");
printf("Total de mutacions detectades: %d\n", total_mutacions);
printf(" Substitucio: %d\n", substitucions);
printf(" Transicions: %d (%.1f%%)\n",
transicions_count,
substitucions > 0 ? (float)transicions_count/substitucions*100 : 0);
printf(" Transversions: %d (%.1f%%)\n",
transversions_count,
substitucions > 0 ? (float)transversions_count/substitucions*100 : 0);
printf(" Insercions: %d\n", insercions);
printf(" Delecions: %d\n", delecions);
if(substitucions > 0 && transversions_count > 0){
float ratio = (float)transicions_count / transversions_count;
printf("\n Ratio Transicions/Transversions: %.2f\n", ratio);
if(ratio > 2.0)
printf(" Interpretacio: Alta fidelitat evolutiva (purificacio negativa).\n");
else if(ratio > 1.0)
printf(" Interpretacio: Mutacio aleatoria tipica.\n");
else
printf(" Interpretacio: Possible saturacio de mutacions.\n");
}
}
/* Funció per guardar l'informe complet en un fitxer */
void guardar_informe(const char *nom_fitxer){
FILE *fitxer = fopen(nom_fitxer, "w"); /* Obre en mode escriptura */
if(fitxer == NULL){
printf("Error: No s'ha pogut crear el fitxer '%s'.\n", nom_fitxer);
return;
}
/* Capçalera de l'informe */
fprintf(fitxer, "========================================\n");
fprintf(fitxer, " INFORME D'ALINEAMENT I MUTACIONS\n");
fprintf(fitxer, "========================================\n\n");
/* Dades generals */
fprintf(fitxer, "--- DADES GENERALS ---\n");
fprintf(fitxer, "Sequencia de referencia: %s\n", seq1);
fprintf(fitxer, "Sequencia comparada: %s\n", seq2);
fprintf(fitxer, "Longitud referencia: %d nt\n", len1);
fprintf(fitxer, "Longitud comparada: %d nt\n\n", len2);
/* Alineament visual */
fprintf(fitxer, "--- ALINEAMENT VISUAL ---\n");
int max_len = (len1 > len2) ? len1 : len2;
fprintf(fitxer, "Ref: ");
for(int i = 0; i < max_len; i++){
if(i < len1) fprintf(fitxer, "%c", seq1[i]);
else fprintf(fitxer, "-");
}
fprintf(fitxer, "\n ");
for(int i = 0; i < max_len; i++){
if(i < len1 && i < len2){
if(seq1[i] == seq2[i]) fprintf(fitxer, "|");
else fprintf(fitxer, " ");
} else {
fprintf(fitxer, " ");
}
}
fprintf(fitxer, "\nCmp: ");
for(int i = 0; i < max_len; i++){
if(i < len2) fprintf(fitxer, "%c", seq2[i]);
else fprintf(fitxer, "-");
}
fprintf(fitxer, "\n\n");
/* Estadístiques */
int coincidencies = 0;
int min_len = (len1 < len2) ? len1 : len2;
for(int i = 0; i < min_len; i++)
if(seq1[i] == seq2[i]) coincidencies++;
fprintf(fitxer, "--- ESTADISTIQUES ---\n");
fprintf(fitxer, "Posicions comparades: %d\n", min_len);
fprintf(fitxer, "Coincidencies: %d\n", coincidencies);
fprintf(fitxer, "Percentatge d'identitat: %.2f%%\n",
max_len > 0 ? (float)coincidencies/max_len*100 : 0);
fprintf(fitxer, "Total de mutacions: %d\n", total_mutacions);
fprintf(fitxer, " Transicions: %d\n", transicions_count);
fprintf(fitxer, " Transversions: %d\n", transversions_count);
fprintf(fitxer, " Insercions: %d\n", insercions);
fprintf(fitxer, " Delecions: %d\n\n", delecions);
/* Llista detallada de mutacions */
fprintf(fitxer, "--- LLISTA DE MUTACIONS ---\n");
fprintf(fitxer, "%-8s %-8s %-8s %-15s %-15s\n", "POSICIO", "ORIG.", "MUT.", "TIPUS", "CLASSE");
fprintf(fitxer, "-----------------------------------------------------\n");
for(int i = 0; i < total_mutacions; i++){
fprintf(fitxer, "%-8d %-8c %-8c %-15s %-15s\n",
mutacions[i].posicio,
mutacions[i].base_original,
mutacions[i].base_mutada,
mutacions[i].tipus,
mutacions[i].classe);
}
fclose(fitxer);
printf("\nInforme guardat a '%s'.\n", nom_fitxer);
}
/* Funció auxiliar: determina si un canvi és transició */
int es_transicio(char b1, char b2){
b1 = toupper(b1);
b2 = toupper(b2);
if(b1 == b2) return -1; /* No és mutació */
/* Transició: A<->G (purines) o C<->T (pirimidines) */
if((b1 == 'A' && b2 == 'G') || (b1 == 'G' && b2 == 'A'))
return 1;
if((b1 == 'C' && b2 == 'T') || (b1 == 'T' && b2 == 'C'))
return 1;
return 0; /* És transversió */
}
/* Funció auxiliar: retorna el tipus de mutació en text */
const char* obtenir_tipus_mutacio(char b1, char b2){
int tipus = es_transicio(b1, b2);
if(tipus == 1) return "Transicio";
if(tipus == 0) return "Transversio";
return "Identic";
}