Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > C/C++
You last visited: Today at 00:15

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Anagramm Programm

Discussion on Anagramm Programm within the C/C++ forum part of the Coders Den category.

Reply
 
Old   #1
 
NRj™'s Avatar
 
elite*gold: 309
The Black Market: 119/0/0
Join Date: Jul 2011
Posts: 4,311
Received Thanks: 886
Anagramm Programm

Hi. Ich habe ein Problem mit einem Programm. Die Aufgabenstellung: Erstelle ein Programm das überprüft ob 2 Wörter Anagramme sind oder nicht. Hier der Quelltext:


Probiert man die Wörter aab und baa oder baa und aba etc. funktioniert alles. Jedoch bei aab und abb nicht. Da zeigt es an, dass es ein Anagramm ist, obwohl das nicht stimmt. Könnt ihr mir helfen?
NRj™ is offline  
Old 01/14/2016, 16:43   #2
 
elite*gold: 0
Join Date: Feb 2009
Posts: 1,137
Received Thanks: 573
Das liegt daran das strspn nur überprüft ob die zeichen vorkommen nicht ob die anzahl oder Reihenfolge stimmt. ich würde es etwa so machen:
Code:
int isAnagram(char[] s1, char[] s2, int length){
  for (i=0; i<length; i++) 
    if (s1[i]!=s2[length-i-1])
      return 0;
  return -1;
}
warfley is offline  
Thanks
1 User
Old 01/14/2016, 17:40   #3


 
Jeoni's Avatar
 
elite*gold: 966
Join Date: Apr 2010
Posts: 1,105
Received Thanks: 681
Die Begründung, warum dein Programm nicht funktioniert, hat warfly schon gegeben. Präsentiert hat er aber eine Funktion, die man eher isPalindrome nennen sollte. Sie prüft nur auf einen Spezialfall eines Anagramms, nämlich dem des Palindroms.

Würde es irgendwie so machen:
Code:
int isAnagram(const char* s1, const char* s2, unsigned int length)
{
	unsigned char chars[255]; // count of one char must not exceed 255; assume that even in a string a character can have a value of [0;255]
	memset(chars, 0, sizeof(chars));

	for (unsigned int i = 0; i < length; i++)
	{
		chars[s1[i]]++;
		chars[s2[i]]--;
	}

	for (unsigned int i = 0; i < (sizeof(chars) / sizeof(chars[0])); i++)
		if (chars[i])
			return 0;

	return -1;
}
Wenn genau die gleichen Zeichen (und die gleiche Anzahl für jedes dieser Zeichen) in s1 wie in s2 vorkommen, ist das array "chars" nach der ersten Schleife wieder vollständig mit 0 gefüllt. Ich hoffe, es ist ungefähr klar, was ich meine bzw. dass sich alles andere eh aus dem Quelltext erklärt.
Mit freundlichen Grüßen
Jeoni
Jeoni is offline  
Thanks
1 User
Old 01/14/2016, 18:00   #4
 
hazejp's Avatar
 
elite*gold: 0
Join Date: Jan 2015
Posts: 62
Received Thanks: 13
Du könntest das Problem komplett ohne Schleifen lösen:

Code:
static int compare_char(const void *x, const void *y) {
  return *((const char*)x) - *((const char*)y);
}

char is_anagram(const char *a, const char *b) {
  int lenA = strlen(a);
  char *cpA, *cpB, res;
  if (strlen(b) != lenA) return 1;
  cpA = strdup(a);
  cpB = strdup(b);
  qsort(cpA, lenA, 1, compare_char);
  qsort(cpB, lenA, 1, compare_char);
  res = strcmp(cpA, cpB);
  free(cpA);
  free(cpB);
  return res;
}
hazejp is offline  
Thanks
1 User
Old 01/14/2016, 18:13   #5


 
Jeoni's Avatar
 
elite*gold: 966
Join Date: Apr 2010
Posts: 1,105
Received Thanks: 681
Trotz scheinbarer Schleifenlosigkeit der Lösung, ist die Komplexität doch höher.
Die von mir vorgeschlagene Lösung hat eine Komplexitätsklasse von O(N). Mit einem konstanten Faktor bestehend aus der zweiten Schleife und dem memset. Also quasi O(N+c), aber meines Wissens nach schreibt man das so nicht, ist aber vllt. genauer.
Die schleifenlose Lösung hat eine Komplexitätsklasse von O(N*log(N)) (wobei log der Logarithmus zur Basis 2 ist), durch die Verwendung von qsort. Auch hier kann man das wieder genauer spezifizieren mit O(2*N*log(N)+2N). Die 2N kommen aus dem strdup, was intern ja auch letztlich eine Schleife ist, die N mal durchlaufen wird. Die Komplexität von strcmp (also im worst case wieder N) kommt noch hinzu. Abgesehen von der höheren algorithmischen Komplexität kostet das Allokieren (hier in strdup) und Deallokieren auch seine Zeit (allerdings unabhängig von der Stringlänge N), weil dahinter ja letztlich auch irgendwelche Algorithmen sitzen, die für's Heap-Speichermanagement verantwortlich sind.
Auch wenn die Funktion selber tatsächlich schleifenlos ist (Unterfunktionen nicht einbezogen), wollte ich das nur mal anbringen
Mit freundlichen Grüßen
Jeoni
Jeoni is offline  
Thanks
1 User
Old 01/14/2016, 18:34   #6
 
hazejp's Avatar
 
elite*gold: 0
Join Date: Jan 2015
Posts: 62
Received Thanks: 13
Tatsächlich zählt mein Programm nicht zu den effizientesten. Tja, das ich habe ich nun von meiner Faulheit... übrigens ist strdup() obiges Beispiel betreffend redundant. Immerhin wäre mit richtig angesetzten Optimierungen "noch" O(N+2N*log(N)) zu erreichen
hazejp is offline  
Old 01/14/2016, 20:19   #7
 
NRj™'s Avatar
 
elite*gold: 309
The Black Market: 119/0/0
Join Date: Jul 2011
Posts: 4,311
Received Thanks: 886
Ich dank euch Leute. Leider bin ich nicht auf dem selben Level eurer geposteten codes. So sehr wie ich es versuche sie zu verstehen, es gelingt mir nicht. Und c & p ist nicht der Sinn der Sache.
NRj™ is offline  
Old 01/14/2016, 21:35   #8
 
elite*gold: 0
Join Date: Feb 2009
Posts: 1,137
Received Thanks: 573
Quote:
Originally Posted by Jeoni View Post
Die Begründung, warum dein Programm nicht funktioniert, hat warfly schon gegeben. Präsentiert hat er aber eine Funktion, die man eher isPalindrome nennen sollte. Sie prüft nur auf einen Spezialfall eines Anagramms, nämlich dem des Palindroms.
Stimmt verwechsel die immer

Quote:
Ich dank euch Leute. Leider bin ich nicht auf dem selben Level eurer geposteten codes. So sehr wie ich es versuche sie zu verstehen, es gelingt mir nicht. Und c & p ist nicht der Sinn der Sache.
Dann versuche ich dir mal den Code von Jeoni zu erklären:

Die Idee ist, ein Ansistring besteht aus Charactern, Byte großen Zahlen von 0 bis 255 (Siehe ASCII Tabelle). Um rauszufinden ob das Wort ein Anagramm ist müssen wir nur überprüfen ob die anzahlen aller einzelnen Buchstaben bei beiden Wörtern gleich sind. Wir zählen also die A's, die B's, etc.
Dafür wird ein Array verwendet welches die Anzahlen sichert. Dieses Array benötigt 255 Felder (für die Zeichen 1..255, 0 darf sowieso nur einmal vorkommen am Ende eines Strings)
Code:
unsigned char chars[255];
der Datentyp unsigned char stellt Zahlen zwischen 0 und 255 dar, da du eh nicht mehr buchstaben in deinem Wort haben kannst reicht er völlig aus, der typ könnte natürlich auch int sein.

Nun hat sich Jeoni in seinem Code zunutze gemacht das ein 'A' letztlich nur eine Zahl ist (65), und man darüber dann auf ein Array Feld zugreifen kann
So würde
Code:
arr['A'] = 3
eine 3 in das 65te Feld des Arrays schreiben.

Nun wird einfach in einer Schleife über die Wörter gelaufen.
Um nur ein Array zu verwenden wird für jeden Buchstaben in Wort 1 der entsprechende Counter erhöht
Code:
chars[s1[i]]++;
und für jeden Buchstaben aus Wort 2 der Counter verringert
Code:
chars[s2[i]]--;
Somit, wenn die Wörter aus den selben Buchstaben bestehen muss der Counter in der Summe für jeden Buchstaben 0 ergeben.

das memset am Anfang ist nur dafür da um zunächst einmal alle Felder des Arrays zu nullen, bei Statischen Arrays ist der Speicher, welcher für das Array alloziiert wurde bereits beschrieben mit den werten die zuletzt dort lagen.

Ein kleiner Lauf mit den wörtern ABC und BCA:
Code:
1. Schleifendurchgang:
chars['A']++;
chars['B']--;
Damit ist:
chars[65] == 1
und
chars[66] == -1 (255)

2. Schleifendurchgang:
chars['B']++;
chars['C']--;
Damit ist:
chars[65] == 1
und
chars[66] == 0 (-1 + 1)
und 
chars[66] == -1 (255)

3. Schleifendurchgang:
chars['C']++;
chars['A']--;
Damit ist:
chars[65] == 0 (+1 - 1)
und
chars[66] == 0 (-1 + 1)
und 
chars[66] == 0 (-1 + 1)
Die anderen Felder wurden nie verwendet, daher sind alle Felder = 0 also ist es ein Anagramm

Code:
for (unsigned int i = 0; i < (sizeof(chars) / sizeof(chars[0])); i++)
		if (chars[i])
			return 0;

	return -1;
Macht nichts anderes als zu überprüfen:
Gehe jedes Feld durch, ist das feld != 0 (kürzer mit if (chars[i])) dann ist es kein Anagramm, und return 0 (false)
Wenn für jedes Feld der Wert = 0 war so wurde kein false returned, also return -1 (true)
warfley is offline  
Thanks
3 Users
Reply


Similar Threads Similar Threads
[Batch] start programm, wait, close programm and redo after 60sec ?!
08/06/2013 - General Coding - 1 Replies
Hallo ich versuche gerade mit Batch das im Titel genannte zu erreichen. Soweit bin ich schon: @echo off cls :start START "Mozilla Firefox" /wait "C:\Program Files (x86)\Mozilla Firefox\firefox.exe"
[Suche] Programm das ermittelst welche ports von einem programm verwendet werden
04/06/2012 - Off Topic - 3 Replies
Hallo, ich versuche immer einen apache server auf meinen pc laufen zu lassen mit xampp nur ich kann das apache nicht starten ka warum ich denke der port wird von irgend einem anderen programm verwändet. skype alles beendet aber geht immernochnicht und jetzt suche ich ein gutes programm mit dem ich herausfinden kann welche ports von welchem programm belegt werden Wäre toll wenn mir hier einer ein Programm nennen kann MFG Benni
Erstes Deutsches All-in-One Multiboxing Programm (Offizieles Legales Programm)
07/10/2010 - World of Warcraft Trading - 2 Replies
Noch nie war Multiboxing leichter, MMObox unterstützt Sie mehrere Charaktere gleichzeit zu spielen, dabei wird nur ein PC benötigt. MMObox steuert im Hintergrund Ihre Charaktere mit Makros. Bis zu 5 Cahraktere gleichzeitig steuern Es wird nur ein PC benötigt Makrofunktionen für alle Charaktere z.b Alle folgen, essen, trinken, aufsitzen....



All times are GMT +1. The time now is 00:15.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.