DNA Aufgabe in Englisch!



  • Dann erklaer es doch mal! Dann werde ich es lernen! Die Loesung werde ich in ca. 2 Wochen erhalten, dann koennen wir ja vergleichen. Ich will ja nicht, dass Ihr meine Aufgaben macht, will ja auch etwas lernen. Ich habe das mittlerweile mit der Ausgabe geloest, musste nur die Integerwerte in char und %d mit %c ersetzen.

    Ich wollte hier niemanden angreifen, aber denkt mal nach. Man waere viel produktiver, wenn man mit Beispielen oder Tipps kommt. Warum das so ist und wie man es besser machen koennte. Alternativ ein Algorithmus oder ne kurze Anleitung.
    Dafuer ist doch das Forum gedacht. Ich programmiere jetzt mit C mittlerweile seit ca. 3 Wochen und muss die Aufgabe bis Anfang Dezember loesen und auch verstanden haben. Meint Ihr nicht???



  • Es erklären? Was ist "es"?
    Produktiver? Tipps?
    Das schwerste in dieser Aufgabe ist das Erzeugen einer verketteten Liste, das wurde dir bereits komplett abgenommen(der Rest der Aufgabe ist ein bisschen Zählen und Prozentrechnung, okay, vllt. findet das ja manch einer schwerer).
    Das ist dir nicht produktiv genug, nicht genug Tipps?
    Deine Arbeit wäre jetzt nur noch reines Nachvollziehen, wie die Liste funktioniert und den Code so zu erweitern, dass er die Aufgabe löst.
    Was außer deinen Punkten und einem regulär ungültigen Schein hättest du sonst davon, wenn dir die komplette Lösung auf dem silbernen Tablett präsentiert würde?



  • Vorsicht, die folgenden Anmerkungen könnten insbesondere für Anfänger schädlich sein!! Bei ersten Anzeichen von Unwohlsein das Lesen einstellen.

    Wnn ich die Aufgabe richtig verstehe, soll ein normaler String in eine einfach verkettete Liste umgewandelt werden. Damit haben wir pro Buchstaben mindestens 4+1 Byte (auf 64-bit Rechnern 8+1) (Zeiger plus Nutzlast von einem Buchstaben) zusätzlichen Speicherbedarf. Aber offensichtlich will der Aufgabensteller dies so, auch wenn es irre ist. Oder halt, er will verhindern, dass im Internet wohlbekannte Funktionen benutzt werden.

    Lineare Listen mit Zeigern zu programmieren und dann nicht einmal die Einlesefunktion von C zu kennen, stimmt natürlich die Mannschaft bedenklich, wenn nicht gar aggressiv, wie man leicht sieht.

    Ich würde dem Einsender vorschlagen, einen gewöhnlichen Text mit einigen Testbuchstaben (wie in der Aufgabenstellung) zu definieren und diesen dann zeichenweise in die verlangte lineare Liste umzuwandeln. Das spart Zeit und Nerven in der Testphase. Auch die dauernde Prüfung, ob Adenin, Guanin, Zytosin und Thymin richtig eingegeben wurde, entfällt erst einmal.

    Die erste Teilaufgabe ist eine Häufigkeitsanalyse. Hier würde ich ein Array mit vier Ganzzahlen für die Buchstaben vorschlagen.
    Dann wird die lineare Liste durchlaufen und das zum Buchstaben A,G,Z,T zugehörige Arrayelement inkrementiert.
    Dann kannst Du mit den vier Elementen alles mögliche machen, also Gesamtzahl, Prozentsatz usw. berechnen.

    Falls dann das Einlesen endlich geht, empfehle das Studium folgender Algorithmen:

    Die zweite Teilaufgabe ist die sog. Lauflängenkompression (RLE, run length encoding). (Wer suchet der findet!)

    Wenn Du dann schon dabei bist, dann kannst Du noch einen Vaterschaftstest bzw. einen Plagiatfinder programmieren. Hier geht es um den Vergleich zweier Zeichenketten (bzw. Deiner linearen Listen). Das Problem ist als

    Longest Common Substring oder auch
    Longest Common Subsequence (LCS) (Wer suchet der findet!)

    bekannt. Oder kurz erklärt, wie lang ist die längste Genkette, die in beiden Genomen vorkommt? Damit ist der Vater zu 99,999% zahlungspflichtig oder der Student hat das Programm sinnlos abgeschrieben.



  • Das ist ja toll das du dir die Mühe machst, die Aufgabe zu erklären.
    Laut der Aussage des Op versteht er sie jedoch bereits.
    Vllt. hilft ja noch eine Liste zur Übung:

    typedef struct tagDnaNode dna_node;
    
    struct tagDnaNode
    {
    	char dna[2];
    	dna_node* next;
    };
    
    dna_node* new_node ( char atgc )
    {
    	dna_node* p = calloc ( 1, sizeof ( dna_node ));
    	if ( NULL != p )
    			p->dna [ 0 ] = atgc;
    	return p;
    }
    
    void free_list ( dna_node* p )
    {
    	while ( p )
    	{
    		dna_node* curr = p;
    		p = p->next;
    		free ( curr );
    	}
    }
    
    void display_list ( dna_node* p )
    {
    	while ( p )
    		printf ( "%s", p->dna ), p = p->next;
    }
    
    int main ( void )
    {
    	char* s = "Hello World!"; // Hello World Gnom-Seekwenz! :D
    	unsigned molecules_count = 0;
    	dna_node *curr, *node, *plist;
    
    	plist = curr = new_node (*s++);
    	if ( NULL == plist )
    		return 0;
    	else
    		molecules_count++;
    
    	for ( ; *s; s++ )
    	{
    		if ( NULL == ( node = new_node ( *s )))
    		{
    			puts ( "Out of memory!" );
    			free_list ( plist );
    			plist = NULL;
    			break;
    		}
    		else
    		{
    			molecules_count++;
    			curr->next = node;
    			curr = node;
    		}
    	}
    
    	if ( NULL != plist )
    	{
    		printf ( "Displaying %u molecules: ", molecules_count );
    		display_list ( plist );
    		free_list ( plist );
    	}
    
    	return 0;
    }
    

    Das wären wieder Bananen, in grün.
    Einmal verstanden, lassen sie sich nahezu mühelos in Birnen konvertieren.
    :p



  • Ok danke! Habe jetzt folgendes geschrieben mit Hilfe von Buechern und google:
    Bekomme bei der Ausgabe noch Fehler. Muss jetzt leider die BIB verlassen, deshalb mache ich es kurz. Danke CJosef fuer dein Code. Werde ich spaeter genauer unter die lupe nehmen.

    #include<stdio.h>
    #include<conio.h>
    #include<malloc.h>
    #include<process.h>
    
    //Structure declaration for the node
    struct node{
    int info;
    struct node *link;
    }*start;
    
    //This function will create a new linked list
    void Create_List(int data)
    {
    struct node *q,*tmp;
    
    //Dynamic memory is been allocated for a node
    tmp= (struct node*)malloc(sizeof(struct node));
    tmp->info=data;
    tmp->link=NULL;
    if(start==NULL)
    /*If list is empty*/
    start=tmp;
    else{
    /*Element inserted at the end*/
    q=start;
    while(q->link!=NULL)
    q=q->link;
    q->link=tmp;
    }
    }/*End of create_list()*/
    
    //This function will add new element at the beginning of the linked list
     void AddAtBeg(int data){
     struct node *tmp;
     tmp=(struct node*)malloc(sizeof(struct node));
     tmp->info=data;
     tmp->link=start;
     start=tmp;
     }/*End of addatbeg()*/
    
     //This function will display all the element(s) in the linked list
     void Display(){
     struct node *q;
     if(start == NULL){
     printf ("\n\nList is empty");
     return;
     }
     q=start;
     printf("\n\nList is : ");
     while(q!=NULL){
     printf ("%d ", q->info);
     q=q->link;
     }
     printf("\n");
     getch();
     }/*End of display() */
    
     //Function to count the number of nodes in the linked list
     void Count(){
     struct node *q=start;
     int cnt=0;
     while(q!=NULL){
     q=q->link;
     cnt++;
     }
     printf ("Number of elements are %d\n",cnt);
     getch();
     }/*End of count()*/
    
     void main(){
     int choice,n,m,position,i;
     start=NULL;
     while(1){
     clrscr();
     printf ("1.Create List\n");
     printf ("2.Add at beginning\n");
     printf ("3.Display\n");
     printf ("4.Count\n");
     printf ("5.Quit\n");
     printf ("\nEnter your choice:");
     scanf("%d",&choice);
     switch (choice){
    
     case 1:printf ("\n\nHow many nodes you want:");
     scanf ("%d",&n);
     for(i=0; i<n; i++)
     {
            printf("\nEnter the element:");
            scanf("%d", &m);
            Create_List(m);
     }
     break;
     case 2:
            printf("\nEnter the element:");
            scanf("%c",&m);
            AddATBeg(m);
            break;
     case 3:
            Display();
            break;
     case 4:
            Count(0);
            break;
     case 5:
            exit(0);
     default:
            printf("\nWrong choice, try again");
                    } //End of switch
               }//End of while
    
     }//End of main
    


  • Nettes Lob von CJosef. Das baut mich auf.

    Nur der Programmansatz (in den Tiefen des Internets gefunen) erschreckt mich doch etwas.

    1. Hoffentlich weiß machupicchu, dass die amerikanische Zählung anders als die deutsche Zählung ist. Billionen sind dann zum Glück nur noch Milliarden. Das wird ihn sicher trösten.

    2. Er will also jeden einzelnen Buchstaben über ein Menü von vorn an eine Liste einfügen. Dann muss er diese ganzen 6 Milliarden Zeichen erst einmal bis ans Ende durchlesen, um von hinten anzufügen, schließlich soll die Liste das Gen richtig herum abbilden.

    3. Meine Berechnung des Speicherbedarfs stimmt natürlich nicht, da machupicchu vorsichtshalber 2 Bytes pro Zeichen benutzt. Hoffentlich ist sein Rechner groß genug.

    4. machupicchu erwartet offensichtlich, dass CJosef ihm sein Programm auf dem Silbertablett serviert. Da habe ich aber schon andere Hinweise hier gelesen: Anregungen zum Selberlösen, konkrete Probleme usw.

    Wenn ich mir so vorstelle, wie viele Zeichen er zum Testen immer wieder von vorn (oha, natürlich von hinten) eingibt, dann wird das nichts mit der Übung. Daher noch einmal mein dringender Rat:

    Die Beispielzeichenkette des Profs einem char * zuweisen. Diese Zeichenkette in einer Schleife abarbeiten und zeichenweise an eine lineare Liste von hinten anfügen. Dazu sollte er einen Kopf- und einen Schwanzzeiger auf die Liste pflegen, um das Anhängen zu beschleunigen (sonst müsste er jedes Mal durch die Liste laufen).

    Erst dann fängt die eigentliche Aufgabenstellung an.



  • Nun, ich bekomme beim Ausfuehren des Programms folgende Fehlermeldung:

    [LinkerError]Unresolved external'-AddATBeg' referenced from G:\DSA\G\NA.OBJ

    Weiss jemand, was das zu bedeuten hat?


  • Mod

    machupicchu schrieb:

    Weiss jemand, was das zu bedeuten hat?

    Eine Symbol (eine Variable oder Funktion) namens "AddATBeg" wird deklariert und benutzt, aber es wird nirgendwo definiert, was es überhaupt ist. Prüfe deinen Code auf Tippfehler, schalte Compilerwarnungen auf Maximum.



  • Ok super! Es lag an einem Schreibfehler! Danke...



  • Waldschrat schrieb:

    Nettes Lob von CJosef. Das baut mich auf.

    Ohh! 😮
    🤡



  • Hi, ich habe jetzt das folgende Programm geschrieben. Bei der Auswahl 3.Count im switch case bekomme ich nun die Berechnung heraus. Leider nur für das letzte character. Habe die if-Abfrage in die Methode count() integriert.
    1. Ich möchte, dass alle Prozentangaben ausgegeben werden
    2. Nur Großbuchstaben als Eingabe gültig sind

    Kann mir jemand helfen? Danke im voraus.

    #include<stdio.h>
    #include<stdlib.h>
    
    //Structure declaration for the node
    struct node
    {
        char info;
        struct node *link;
    }*start;
    
    //This function will create a new linked list
    void Create_List(char data){
        struct node *q, *tmp;
        //Dynamic memory is been allocated for a node
        tmp= (struct node*)malloc(sizeof(struct node));
        tmp->info=data;
        tmp->link=NULL;
        if(start==NULL)
        /*If list is empty*/
            start=tmp;
        else{
            /*Element inserted at the end*/
            q=start;
            while(q->link!=NULL)
                q=q->link;
            q->link=tmp;
        }
    }
    
    //This function will display all the element(s) in the linked list
    void Display()
    {
        struct node *q;
        if(start == NULL)
        {
            printf ("\n\nList is empty");
            return;}q=start;
        printf("\n\nList is : ");
        while(q!=NULL)
        {
            printf ("%c", q->info);
            q=q->link;
        }
        printf ("\n");
    
    }/*End of display() */
    
    void Count(int inputMax, char comp)
    {
        struct node *q;
        q = start;
        int cnt=0;
        int A = 0, G =0, T =0, C = 0;
        while(cnt<inputMax)
        {
            if(comp=='A'){A++;}
            if(comp=='G'){G++;}
            if(comp=='T'){T++;}
            if(comp=='C'){C++;}
            q=q->link;
            cnt++;
    
        }
        printf("\nA: %lf", (float)(A/inputMax)*100);
        printf("\nG: %lf", (float)(G/inputMax)*100);
        printf("\nT: %lf", (float)(T/inputMax)*100);
        printf("\nC: %lf", (float)(C/inputMax)*100);
    
    }/*End of count()*/
    
    int main()
    {
        int choice,n,i;
        char m;
        do
        {
            printf("\n 1. Create List\n");
            printf("\n 2. Display \n");
            printf("\n 3. Count\n");
            printf("\nEnter your choice (0 to 3)\n");
            scanf("%d",&choice);
    
            switch (choice)
            {
                case 1:
                    printf ("\n\nHow many nodes you want:");
                    scanf ("%d",&n);
                    getchar();
                    for(i = 0;i<n;i++){
                        printf ("\nEnter the element:");
                        scanf ("%c",&m);
                        getchar();
                        Create_List(m);
                    }
                    break;
                case 2:
                    Display();
                    break;
                case 3:
                    Count(n, m);
                    break;
                default:
                    printf ("\n\n----WRONG CHOICE----\n");
            }
        }
        while (choice !=0);
    
        return 0 ;
    }
    

  • Mod

    machupicchu schrieb:

    Hi, ich habe jetzt das folgende Programm geschrieben. Bei der Auswahl 3.Count im switch case bekomme ich nun die Berechnung heraus. Leider nur für das letzte character.

    Du benutzt ja auch nur das letzte Zeichen.

    Habe die if-Abfrage in die Methode count() integriert.
    1. Ich möchte, dass alle Prozentangaben ausgegeben werden

    Klar möchtest du das, es ist schließlich deine Hausaufgabe.

    2. Nur Großbuchstaben als Eingabe gültig sind

    http://www.cplusplus.com/reference/cctype/isupper/
    Aber warum? Es gibt doch bloß 4 gültige Buchstaben. Prüf doch auf die.

    P.S.: Ich will dich ja nicht fertig machen, aber: Kann es sein, dass du die letzten anderthalb Wochen absolut gar nichts gemacht hast und gerade Panik schiebst, weil bald Abgabe ist? Sei mal ehrlich: Kannst du den Stoff? Hast du irgendetwas dafür getan? Verdienst du die Punkte?



  • Hi, also ich habe etwas gemacht. Da ich das Thema nicht so ganz verstanden hatte, habe ich es erneut versucht und mein vorriges Programm nochmal geändert. Verstanden habe ich natürlich nicht alles, deshalb bin ich ja hier.

    Du benutzt ja auch nur das letzte Zeichen.

    Ich gebe ja über printf alle Ausgaben aus, wo siehst Du, dass nur das letzte Zeichen ausgebe?

    http://www.cplusplus.com/reference/cctype/isupper/
    Aber warum? Es gibt doch bloß 4 gültige Buchstaben.

    Ja eben, ich könnte es ja auch mit der asci tabbelle machen. Zum Beispiel:

    if(inputMax>='A' && inputMax <='Z')
    inputMax = inputMax -32;
    

    An welcher Stelle kann ich dies integrieren? Habe jetzt einiges ausprobiert, aber mit wenig erfolg.


  • Mod

    machupicchu schrieb:

    Du benutzt ja auch nur das letzte Zeichen.

    Ich gebe ja über printf alle Ausgaben aus, wo siehst Du, dass nur das letzte Zeichen ausgebe?

    Du fragst doch auch nicht nach Ausgabe, sondern danach, dass dein Zähler bloß das letzte Zeichen zählt.

    Aber warum? Es gibt doch bloß 4 gültige Buchstaben.

    Ja eben, ich könnte es ja auch mit der asci tabbelle machen. Zum Beispiel:

    Wieso jetzt ASCII? Was soll das damit zu tun haben? Und wieso nicht stattdessen das portable isupper, welches ich dir vorgeschlagen habe?

    if(inputMax>='A' && inputMax <='Z')
    inputMax = inputMax -32;
    

    An welcher Stelle kann ich dies integrieren? Habe jetzt einiges ausprobiert, aber mit wenig erfolg.

    Was soll das überhaupt machen? Wieso nicht if (m != 'A' || m != 'G' ...) ?



  • Du fragst doch auch nicht nach Ausgabe, sondern danach, dass dein Zähler bloß das letzte Zeichen zählt.

    Ich habe ja mein inkrement cnt++ danach wird die while schleife beendet. anschließend soll alles ausgegeben werden. :xmas2: 😕
    Möchte ja alles ausgeben:

    printf("\nA: %lf", (float)(A/inputMax)*100);
        printf("\nG: %lf", (float)(G/inputMax)*100);
        printf("\nT: %lf", (float)(T/inputMax)*100);
        printf("\nC: %lf", (float)(C/inputMax)*100);
    

    Wie kann ich das ändern, dass er mir nicht nur das letzte, sondern alles ausgibt?

    Was soll das überhaupt machen? Wieso nicht if (m != 'A' || m != 'G' ...)?

    Wenn es in der count methode sein soll, dann

    void Count(int inputMax, char comp)
    {
        struct node *q;
        q = start;
        int cnt=0;
        int A = 0, G =0, T =0, C = 0;
        while(cnt<inputMax)
        {   
            if(comp !='A'|| comp !='G'|| comp !='T'|| comp !='C')
        {
            printf("Falsche Eingabe");
        }
        else
        {
    
            if(comp=='A'){A++;}
            if(comp=='G'){G++;}
            if(comp=='T'){T++;}
            if(comp=='C'){C++;}
            q=q->link;
            cnt++;
    
        }
        printf("\nA: %lf", (float)(A/inputMax)*100);
        printf("\nG: %lf", (float)(G/inputMax)*100);
        printf("\nT: %lf", (float)(T/inputMax)*100);
        printf("\nC: %lf", (float)(C/inputMax)*100);
    
    }/*End of count()*/
    

    m wird ja von meiner eingabe in die methode überladen. d.h. mein comp bekommt m übergeben. Count(n,m) in der switch case abfrage.


  • Mod

    Count im switch case bekomme ich nun die Berechnung heraus. Leider nur für das letzte character

    Ich gebe ja über printf alle Ausgaben aus, wo siehst Du, dass nur das letzte Zeichen ausgebe?

    Wo siehst du, dass es nur den letzten zähler zählt? Ich habe ja mein inkrement cnt++ danach wird die while schleife beendet. anschließend soll alles ausgegeben werden.

    Ich habe keine Ahnung mehr, was du überhaupt wissen möchtest. Weißt du es eigentlich selber? Du springst wild hin und her. Verstehst du überhaupt deinen eigenen Code oder alles bloß abgeschrieben?

    Tut mir leid, so kann ich dir nicht helfen. Das wird andern Lesern genau so gehen. Siehe die Sticky-Threads hier im Forum und die Links in meiner Signatur.



  • du solltest die zeichen direkt bei der eingabe auf gültigkeit prüfen.
    warum nimmst du nicht erstmal einen string,

    char* s = "ATATCGATCGATCG"
    

    der eine eingabe simuliert um mal in die gänge zu kommen?
    (die eingabe wird wohl in der praxis kaum vom benutzer gemacht werden, sondern kommt aus irgendwelchen dateien.)
    die zeichen kannst du ebenfalls direkt bei der eingabe zählen, z.b. während der gültigkeitsprüfung.
    die liste passt sich dann selbständig der anzahl an, man braucht nicht im voraus zu wissen, wie viele zeichen kommen.

    How many nodes you want

    kannst du dir also schenken.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    int A=0, G=0, T=0, C=0; // evtl in struktur einbetten
    
    int add_element(char e)
    {
    	// if malloc == NULL return 0 else 
    	printf("%c", e);
    	return 1; //ok
    }	
    
    int check_element(char e)
    {
    	int ok = 0;// invalid element
    	e=toupper(e);
    	if ('A' == e)
    		A++, ok=1;
    	else if ('G'==e) 
    		G++, ok=1;
    	else if ('T'==e) 
    		T++, ok=1;
    	else if ('C'==e) 
    		C++, ok=1;
    	if (!ok)
    		printf("\ninvalid element: %c\n", e);
    	return ok;
    }
    
    int main(void)
    {
    	char* atgc = "ATATCGATCGATCGX", *p;
    	for (p=atgc; *p!=0; p++)
    	{
    		if (!check_element(*p))
    		/*free list and then*/return 1;
    		else if(!add_element(*p))
    		/*free list and then*/return 1;
    	}
    	return 0;
    }
    

    du hast schon 2 fast komplette lösungen bekommen, die eine liste erzeugen aber statt diese zu nutzen, daraus zu lernen und für dich zu verwerdten irrst du weiter im dickicht der unwissenheit und des herumprobierens.



  • Danke Leute! Ich werde mal die Abfrage versuchen in mein Programm zu integrieren. Meine Dozentin will schon, dass ich es einlese. Ich habe mein Programm nicht einfach kopiert und hier gepostet. Ich möchte nun mal mit Methoden arbeiten, um eine bessere struktur zu haben, statt alles in die main methode zu klatschen.

    Sepj, ich habe dich schon verstanden. Ich wollte nur wissen, wie ich meine zähler ändern muss, dass er mir alle Prozentangaben ausgibt???


Anmelden zum Antworten