Anagramm

iks

Mitglied
Guten Tag!

Ich habe mich zu Übungszwecken an einem Programm versucht, das feststellen soll, ob die beiden Übergebenen Strings ein Anagramm sind, also ob sie aus den gleichen Buchstaben bestehen.
Die Lösung aus dem Buch kann ich nicht nachvollziehen, ich wüsste gerne, wo in meiner Lösung der denkfehler liegt. Meine Idee war es, mit 2 verschachtelten for-Schleifen zu arbeiten, sodass fuer den ersten Buchstaben des ersten Strings alle Buchstaben des 2. Strings durchgetestet werden, aber irgendwie funktioniert es nicht, obwohl es doch ganz simpel sein muss. *Brett vorm Kopf*, HEUL!!!
Hier der Code:

Java:
	public static boolean istAnagramm(String s1, String s2) {
		
		boolean ergebnis = true;
		
		if (s1.length() != s2.length()) {
			ergebnis = false;
			return ergebnis;
		} // Ende if
	
		else {
			
			for(int i=0 ; i < s1.length(); i++) {
										
				for(int j=0; j < s1.length(); j++ ) {
					
					if (s1.charAt(i) == s2.charAt(j)) {
						ergebnis = true;
						
					} // Ende if
		
					else ergebnis = false;
					
				} // Ende innere for-Schleife
						
			} // Ende auessere for-Schleife			
				
		} // Ende else
		
		return ergebnis;
		
	} // ende istAnagramm()

Aufgerufen wirds in meiner main so:
System.out.println(istAnagramm("all" , "lla"));

ergebnis sollte also "true" sein, es funktioniert aber nicht, kann mir jemand auf die Sprünge helfen?
 
A

Andgalf

Gast
Nur kurz draufgeschaut, aber ich denke die innere Schleife sollte anders rum laufen .... also vom Ende des Strings zum Anfang
 

iks

Mitglied
Oh je, es funktioniert, wenn die innere Schleife anders herum läuft, ich verstehe jedoch nicht, wieso das in in diesem Fall einen Unterschied macht...
Ob ich nun das wort von vorn nach hinten oder hinten nach vorn pruefe, wo ist da der Unterschied, der uebereinstimmende Buchstabe sollte doch so oder so gefunden werden oder nicht?
Hmm, vielleicht muss ich das nochmal mit Stift und Zettel durchgehen...
 
S

SlaterB

Gast
wichtig: nicht bei jeder einzelnen Übereinstimmung auf true setzen,
sondern mit true beginnen und einer Nicht-Übereinstimmung auf false setzen,
dann kann eigentlich auch schon abgebrochen werden
 

iks

Mitglied
Also ob ich das vorher auf true setze oder falsch und umgekehrt prüfe macht bei mir keinen Unterschied aus, zumindest nicht im Ergebnis.
Mag sein, dass es saubererer Stil ist, es erst auf true zu setzen, dass weiss ich nicht. Aber mit 2 hochzaehlenden Schleifen klappt es auch nicht, wenn ich ich vorher auf true setze und die if-pruefung umkehre(!=) ....
Wie auch immer, es funktioniert ja mit der runterzaehlenden for-Schleife und ich werde heute Abend mit stift und zettel nachvollziehen, warum das der Fall ist:)
Daher auf jeden Fall: Großes Dankeschön!
 
S

SlaterB

Gast
auf die Schleife solltest du wirklich achten, stell dir vor bei 6 Buchstaben ergeben die ersten 5 Vergleiche keine Übereinstimmung,
der 6. aber schon, dann ist true das falsche Endergebnis
 

iks

Mitglied
istAnagramm("aaa355bbb" , "bbbaaa553");

Das waere ja aber in diesem Fall oben der Fall...und dennoch funktionierts...oder verstehe ich da wieder was falsch, hrm, vielleicht bin ich heute auch einfach zu muede zu denken.
In welchem Fall sollte es denn nicht funktionieren, wenn ich den boolean vorher auf true setze?
 

iks

Mitglied
Also das ist jetzt mein endgueltiger code und der funktioniert fuer alle meine getesteten Anagramme:

Java:
	public static boolean istAnagramm(String s1, String s2) {
		
		boolean ergebnis = true;
		
		if (s1.length() != s2.length()) {
			ergebnis = false;
			return ergebnis;
		} // Ende if
	
		else {
			
			for(int i=0 ; i < s1.length(); i++) {
										
				for(int j=s1.length()-1; j > 0; j-- ) {
					
					if (s1.charAt(i) == s2.charAt(j)) {
						ergebnis = true;
						
					} // Ende if
		
					else ergebnis = false;
					
				} // Ende innere for-Schleife
						
			} // Ende auessere for-Schleife			
				
		} // Ende else
		
		return ergebnis;
		
	} // ende istAnagramm()
 

iks

Mitglied
Hmm war es so gemeint:

Java:
	public static boolean istAnagramm(String s1, String s2) {
		
		boolean ergebnis = false;
		
		if (s1.length() != s2.length()) {
			ergebnis = false;
			return ergebnis;
		} // Ende if
	
		else {
			
			for(int i=0 ; i < s1.length(); i++) {
										
				for(int j=s1.length()-1; j > 0; j-- ) {
					
					if (s1.charAt(i) != s2.charAt(j)) {
						ergebnis = false;
						
					} // Ende if
		
					else ergebnis = true;
					
				} // Ende innere for-Schleife
						
			} // Ende auessere for-Schleife			
				
		} // Ende else
		
		return ergebnis;
		
	} // ende istAnagramm()

...funktioniert bei mir nämlich auch nicht...ich gebs auf, war mein ansatz denn so falsch??!!
 
S

SlaterB

Gast
bei istAnagramm("aaa355bbb" , "bbbaaa553"); wird true zurückgegeben, weil der letzte Vergleich b mit b true ergibt,
allerdings ist aaa355bbb kein Anagramm von bbbaaa553,

bzw. schon, im Sinne von
Der Begriff Anagramm (von griechisch anagraphein ‚umschreiben‘) bezeichnet ein Wort, das aus einem anderen Wort durch Umstellung (Permutation) der einzelnen Buchstaben oder Silben gebildet wurde.
Anagramm ? Wikipedia

ist das dein Ziel? dann musst du aber ganz anders vorgehen,

falls es um Palindrom geht: aaa355bbb ist kein Palindrom von bbbaaa553
bzw. auch wieder Quatsch, ein Palindrom ist ja ein einzelnes Wort ;)
was ist überhaupt dein Ziel, ich schaue nochmal ins erste Post
 
S

SlaterB

Gast
so, also dein Beispiel mit true ist dann korrekt,
das ist aber nur zufällig, weil der letzte Vergleich (b und b) passt,


istAnagramm("aaa35bbb5", "bbbaaa553")
liefert false, obwohl es genauso klappen sollte, weil zuletzt b und 5 verglichen werden


du könntest z.B. in beiden Strings die einzelnen Zeichen sortieren, dann muss am Ende 2x der gleiche String rauskommen
 

iks

Mitglied
Hmm, also Anagramm bedeutet doch, das zwei Woerter, sagen wir Strings in unserm Fall, die gleichen buchstaben in gleicher anzahl beeinhalten. Sollte es das nicht bedeuten, ist es dennoch das, was ich abfragen moechte.

Daher war meine idee:

Ich nehme mir den ersten Buchstaben des ersten Strings, und pruefe dann ob es ihn noch ein anderers mal gibt....und ich merke gerade auch hier schon während ich schreibe, das mein Ansatz quatsch ist, weil ich ja auch pruefen muss, wie oft jeder einzelne vorkoemmt, ARG. Also doch der Schlafmangel, letzte Woche hat das alles noch so gut gefunzt mit dem Programmieren:)

Okay, RÜCKZUG, So kann es natürlich nicht gehen. MEIN FEHLER....***Peinlich***.
 

Gossi

Bekanntes Mitglied
Wenn Groß- und Kleinschreibung egal sind mal nen kleiner Denkanstoß:
------------------------------------------------
String nr1 = eingangsStringNr1.inKleinbuchstaben;
String nr2 = eingangsStringNr2.inKleinbuchstaben;

int inNr1 = 0;
int inNr2 = 0;

für jeden char zwischen 97 und 122

für jeden char in nr1
ist aktueller char der gleiche: inNr1++;

für jeden char in nr2
ist aktuellers char der gleiche: inNr2++;

stimmt inNr1 mit inNr2 überein?
------------------------------------------------
Keine gute Lösung, aber wenigstens etwas ^^
 

iks

Mitglied
Hmmja, also ich habe auch einen neuen Ansatz:

Ich zaehle jeweils alle vorkommenden zeichen einzeln durch, das ergebnis speicher ich in jeweils einem Array, alphabetisch.
Zum schluss vergleiche ich dann nur noch die Arrays, die die Ergebnisse der Buchstabenzaehlung enthalten, das muesste funktionieren.
Aber ich glaub vorher mach ich nochmal n kleines nickerchen damit ich nich wieder solche peinlichen Fragen stelle:p
 

iks

Mitglied
Um meine Ehre wenigstens ein bischen zu retten, hier mein Code, und der funtkioniert auch glatt. Einziges problem ist, das ich es diesmal gar nicht über Boolean variablen abfrage , also auch kein return ergebnisboolean am Ende. Aber prinzipiell läufts so.
Zumindest für Strings die aus kleinbuchstaben bestehen, ansonsten muesste ich sie konvertieren. Und buchstaben aus dem Alphabet sollten es auch sein...okayokay schon wieder merke ich beim schreiben, dass da noch einiges zu verbessern ist, aber unter diesen (meinen)bestimmten vorgaben läuft es so ganz gut:

Java:
public static void istAnagramm(String s1, String s2) {
		
		int ergebnis = 0;
		
		char []zeichenArray = {'a', 'b', 'c' ,'d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
		if (s1.length() != s2.length()) {
			ergebnis++;			
		} // Ende if
		
		int[] s1result = new int[zeichenArray.length];
		int[] s2result = new int[zeichenArray.length];
		
		char s1vokal, s2vokal;		
		
		
		for(int j =0; j < zeichenArray.length; j++) {
			
			for(int i = 0;i < s1.length();i++) {
		
				s1vokal = s1.charAt(i);
			
				if(s1vokal == zeichenArray[j]) {
					s1result[j]++;					
				} //end if	
			} // end for		
		} // end for
		

		for(int j =0; j < zeichenArray.length; j++) {
			
			for(int i = 0;i < s2.length();i++) {
		
				s2vokal = s2.charAt(i);
			
				if(s2vokal == zeichenArray[j]) {
					s2result[j]++;					
				} //end if	
			} // end for		
		} // end for

		for (int k = 0; k < s1result.length; k++) {
			
			if(s1result[k] > s2result[k] || s1result[k] < s2result[k]) {
				ergebnis++;
			} // end if
									
		} // end for
					
		if (ergebnis > 0) {
			System.out.println("false");
			
		} // end if
		else System.out.println("true");
						
	} // end istAnagramm()
 
S

SlaterB

Gast
für > oder < gibt es auch !=

und nimm lieber ein großes Array von 0-200 oder gar bis 70.000,
und nimm jeden char direkt als Array-Index,
das spart dir die innere Schleife, die äußere über den String:
Java:
for (einmal über den String) {
s1result[s1.charAt(i)]++;     
}
 

Neue Themen


Oben