Avatar billede tanis13 Nybegynder
23. januar 2006 - 12:56 Der er 29 kommentarer og
1 løsning

Palindrom kendkendelse

Er der nogen som kan hjælpe mig med at finde en funktion, som kontrollerer om et String input er et palindrom - dvs. staves ens forfra og bagfra, F.eks. "Elg udnytter ret tynd ugle".

Dog skal evt. mellemrum, komma og lign ikke medregnes i palindromet.

Håber der er nogen der kan give en hånd.

Mvh Thomas
Avatar billede mikkelbm Nybegynder
23. januar 2006 - 13:18 #1
Det kunne måske gøres således:

public class Palindrom
{
    public static void main (String[] args)
    {
        String testText = "Elg udnytter ret tynd ugle";
        System.out.println (isPalindrom (testText));
    }
   
    public static boolean isPalindrom (String text)
    {
        text = text.replace (" ", "");
        text = text.toLowerCase();
        if (text.length() % 2 != 0)
            return false;
           
        char[] leftside = text.substring (0, text.length() / 2).toCharArray();
        char[] rightside = text.substring (text.length() / 2).toCharArray();
       
        boolean ok = true;
        for (int i = 0, j = rightside.length - 1; i < leftside.length; i++, j--)
        {
            System.out.println (leftside[i] + " - " + rightside[j]);
            ok &= leftside[i] == rightside[j];
        }
           
        return ok;
    }
}


Så kan du selv tilrette med flere 'replaces', hvis komma, punktum, etc. ikke skal med.
Avatar billede jakoba Nybegynder
23. januar 2006 - 13:39 #2
jeg foretrækker denne (definere hvilke bogstaver der skal tælle med)

boolean static testPalindrom( String kandidat ) {
    String alfabet = "abcdefghijklmnopqrstuvwxyz";
          // tilføj evt andre bogstaver der også skal 'tælle med'
    kandidat = kandidat.toLowerCase();      // så 'a'=='A', osv
    char[] temp = new char[kandidat.length()];
    int i = 0;
    int j = 0;
    for( i=0; i<kandidat.length(); i++ ) {
        if( alfabet.indexOf( kandidat.charAt(i) ) >= 0 ) {
            temp[j++] = kandidat.charAt(i);  // kun de bogstaver der skal testes på
        }
    }
    i = 0;
    j--;
    while ( i<j ) {
        if ( temp[i] != temp[j] ) break;  // forlad løkken hvis vi ser en forskel
        i++;
        j--;
    }
    return i>= j;    // hvis vi ikke forlod løkken i utide er det et palindrom.
}

men det er vist mest en smagssag. og mikkel er klart først.
Avatar billede ldanielsen Nybegynder
23. januar 2006 - 14:13 #3
Nu kan jeg ikke Java, kun javascript, men jeg vil også være med:

function checkIt(strIn){
    var strPalin = strIn.toLowerCase();
    strPalin = strPalin.replace(/ /g, "");
    strPalin = strPalin.replace(/\,/g, "");
    strPalin = strPalin.replace(/\./g, "");

    var strRev = "";
    var iLen = strPalin.length
    for (i=iLen;i>=0;i--){
        strRev += strPalin.substring(i, i+1);
        }
       
    var bIsPalin = (strPalin.substring(0, Math.ceil(iLen/2)) == strRev.substring(0, Math.ceil(iLen/2)))
    return bIsPalin;
   
    }
Avatar billede ldanielsen Nybegynder
23. januar 2006 - 14:40 #4
Hi hi, nu går der sport i det:

function checkIt(strIn){
    var strPalin = strIn.replace(/[^\d\w]/g, "").toLowerCase();
    var strRev = strPalin.split("").reverse().join("");
    return (strPalin.substring(0, Math.ceil(strPalin.length/2)) == strRev.substring(0, Math.ceil(strPalin.length/2)));
    }

Jeg ved ikke om det kan overføres direkte til Java, men 3 linier, det er lidt godt gået ikke? :o)

PS: Ingen point til mig, jeg var sidst ...
Avatar billede jakoba Nybegynder
23. januar 2006 - 14:56 #5
Det kan det godt nok ikke (den der reverse funktion ville være rar at have)

men hvis det skal være på den måde så kan det da godt blive kortere i java :-))

static boolean testPalindrom( String kandidat ) {
    String alfabet = "abcdefghijklmnopqrstuvwxyzæøå";
          // tilføj evt andre bogstaver der også skal 'tælle med'
    kandidat = kandidat.toLowerCase();      // så 'a'=='A', osv
    int i = 0;
    int j = kandidat.length()-1;
    while ( true ) {
        while ( i<j && alfabet.indexOf( kandidat.charAt(i) ) < 0 ) i++; // skip tegn og spaces
        while ( i<j && alfabet.indexOf( kandidat.charAt(j) ) < 0 ) j--; // skip tegn og spaces
        if ( i >= J ) return true;        // slut. alt er godt       
        if ( temp[i] != temp[j] ) return false;  // slut. den gik ikke
        i++;
        j--;
    }
}
Avatar billede arne_v Ekspert
23. januar 2006 - 15:08 #6
String har ikke reverse, men det har StringBuffer/StringBuilder ...
Avatar billede ldanielsen Nybegynder
24. januar 2006 - 09:04 #7
Der er Array.reverse() jeg bruger ...

Men kan man i det mindste ikke bruge Regular Expressions til at fjerne uønskede tegn? Det siges at være meget hurtigere. [^\d\w] matcher alt andet end bogstaver og tal.
Avatar billede jakoba Nybegynder
24. januar 2006 - 10:03 #8
Jo man kan bruge regular expression til at fjerne uønskede.
String  replaceAll(String regex, String replacement)
          Replaces each substring of this string that matches the given regular expression with the given replacement.
fra: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html
  ( den der java API er dejlig at slå op i :-))

men regular expressions er tek der nok mere forvirrer end informerer når 'finde et palindrom' stadig er en svær opgave.
Avatar billede ldanielsen Nybegynder
24. januar 2006 - 10:38 #9
Du har ret, sorry :o) Jeg havde helt glemt tanis13. Slut herfra
Avatar billede tanis13 Nybegynder
24. januar 2006 - 13:02 #10
Tusind tak for et hurtigt svar =}

Ved ikke hvem jeg skal smide pointene til, da der er ingen som er kommet med et svar, men mikkelbm eller jakoba er nok mest overskueligt fra min side af!

Men tak alle for hjælpen.
Avatar billede mikkelbm Nybegynder
24. januar 2006 - 13:04 #11
Så smider vi et svar...
Avatar billede arne_v Ekspert
24. januar 2006 - 14:46 #12
public static boolean isPalindrome(String s) {
        String tmp = s.replaceAll("[ ,]","").toLowerCase();
        return tmp.equals((new StringBuffer(tmp)).reverse().toString());
    }
Avatar billede jakoba Nybegynder
25. januar 2006 - 05:34 #13
arne_v >>  blær  :-))
tanis13 >> mikkelbm var først. hans svar.
Avatar billede jakoba Nybegynder
25. januar 2006 - 05:40 #14
arne >> men hvis det endelig skal være:

public static boolean isPalindrome(String s) {
        return (s=s.replaceAll("[ ,]","").toLowerCase()).equals((new StringBuffer(s)).reverse().toString());
    }
Avatar billede tanis13 Nybegynder
25. januar 2006 - 12:57 #15
Efter at have kigget en del på mikkelbm's bud på, er jeg stødt på en forhindring fra min side af.

Eftersom han bruger en påforhånd defineret "String testText", har jeg ikke lige kunne omskrive denne, så man kan komme med andre input - dvs. ikke en på forhånd defineret palindrom, men en valgfri tekst som brugeren skriver ind.

Er det muligt der stadig er nogen som kan hjælpe med dette ?
Avatar billede mikkelbm Nybegynder
25. januar 2006 - 13:18 #16
Har lige samlet alle tre eksempler i én klasse, og lavet sådan at brugeren selv skal indtaste data:

import java.util.*;

public class Palindrom
{
    public static void main (String[] args)
    {
        String exitCode = "Exit";
        String testText = "";
        Scanner scanner = new Scanner (System.in);
        do
        {
            System.out.println ();
            System.out.print ("Indtast palindrom: ");
            testText = scanner.next ();
            System.out.println ("Mikkel" + testText + " - " + isPalindromeMikkel (testText));
            System.out.println ("Arne" + testText + " - " + isPalindromeArne (testText));
            System.out.println ("Jakob" + testText + " - " + isPalindromeJakob (testText));
        }
        while (!testText.equalsIgnoreCase (exitCode));
    }
   
    public static boolean isPalindromeMikkel (String text)
    {
        text = text.replace (" ", "");
        text = text.toLowerCase();
        if (text.length() % 2 != 0)
            return false;
           
        char[] leftside = text.substring (0, text.length() / 2).toCharArray();
        char[] rightside = text.substring (text.length() / 2).toCharArray();
       
        boolean ok = true;
        for (int i = 0, j = rightside.length - 1; i < leftside.length; i++, j--)
        {
            System.out.println (leftside[i] + " - " + rightside[j]);
            ok &= leftside[i] == rightside[j];
        }
           
        return ok;
    }
   
    public static boolean isPalindromeArne(String s)
    {
        return (s=s.replaceAll("[ ,]","").toLowerCase()).equals((new StringBuffer(s)).reverse().toString());
    }
   
    public static boolean isPalindromeJakob( String kandidat )
    {
        String alfabet = "abcdefghijklmnopqrstuvwxyz";
              // tilføj evt andre bogstaver der også skal 'tælle med'
        kandidat = kandidat.toLowerCase();      // så 'a'=='A', osv
        char[] temp = new char[kandidat.length()];
        int i = 0;
        int j = 0;
        for( i=0; i<kandidat.length(); i++ )
        {
            if( alfabet.indexOf( kandidat.charAt(i) ) >= 0 )
            {
                temp[j++] = kandidat.charAt(i);  // kun de bogstaver der skal testes på
            }
        }
        i = 0;
        j--;
        while ( i<j )
        {
            if ( temp[i] != temp[j] ) break;  // forlad løkken hvis vi ser en forskel
            i++;
            j--;
        }
       
        return i>= j;    // hvis vi ikke forlod løkken i utide er det et palindrom.
    }
}
Avatar billede mikkelbm Nybegynder
25. januar 2006 - 13:19 #17
Jeg fandt dog også en fejl i min metode :(

Jeg laver et tjek på om længden kan divideres med 2. Og det tjek dur ikke, kommer jeg lige i tanke om. Så de andre metoder er faktisk bedre :)
Avatar billede arne_v Ekspert
25. januar 2006 - 13:41 #18
du skal da bare fjerne det check

hvis laengden er 7 saa sammenligner du de 3 til venstre med de 3 til hoejre
og den i midten skal nok matche sig selv
Avatar billede tanis13 Nybegynder
25. januar 2006 - 13:44 #19
Umiddelbart virker det fornuftigt nok med din metode, men den er ikke så venlig overfor ,.' og lign tegn. Men vil man ikke kunne bruge en metode, så den kun bruger "letters" ?

Har lige ledt lidt på nettet efter noget lign. og fandt: http://www.dickinson.edu/~braught/courses/cs132s03/code/Palindrome.src.html

Her bruger de en "Character.isLetter".
Avatar billede tanis13 Nybegynder
25. januar 2006 - 13:45 #20
så man kan sagtens bruge "divider med 2" metoden ?
Avatar billede arne_v Ekspert
25. januar 2006 - 13:46 #21
man kan sagtens erstatte alle ikke bogstaver med ingenting via replaceAll
Avatar billede mikkelbm Nybegynder
25. januar 2006 - 13:47 #22
Ja, det er rigtigt. Der skal vel så lige en condition mere ind i forløkken der tjekker for j, da der ellers kan komme en fejl på index.
Avatar billede tanis13 Nybegynder
25. januar 2006 - 13:50 #23
har ogå lige gennemgået funktionerne igen, den er kan ikke finde ud af hvis det er flere end ét ord... dvs. "Elg udnytter ret tynd ugle" betegner den ikke som et palindrom.
Avatar billede mikkelbm Nybegynder
25. januar 2006 - 14:25 #24
Min fejl...

Skift:
testText = scanner.next ();

ud med:
testText = scanner.nextLine ();
Avatar billede arne_v Ekspert
25. januar 2006 - 18:50 #25
re 25/01-2006 05:40:31

Jakob er du sikker paa at s bliver replacet og toloweret inden stringbuffer
constructor kaldes ?

garanterer java at man har fuindet det objekt man skal kalde en metode paa
inden den begynder ar beregne argumenter ?
Avatar billede jakoba Nybegynder
26. januar 2006 - 13:43 #26
Det er den ret nødt til. Den kan jo ikke checke datatype på parametrene førend den ved hvilken type objekt metoden 'equals' bliver kaldt i.
men jeg er ikke 100%. har ikke testet.
Avatar billede arne_v Ekspert
26. januar 2006 - 13:52 #27
det er rigtigt

men forhindrer det:

beregn temp = (new StringBuffer(s)).reverse().toString()
beregn s = s.replaceAll("[ ,]","").toLowerCase()
beregn s.equals(temp);

?

jeg ved ikke om det er undefine hvordan det beregnes eller om der er en
angivelse af det i JLS

tanis>

bare ignorer den her lille subtraad
Avatar billede jakoba Nybegynder
26. januar 2006 - 14:23 #28
det nærmeste jeg kan komme til en garanti for at det virker er
    http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.7
'.' er en operator der sammenknytter objektet med metodenavnet, og dermed bør objektet (på venstre side af '.') være færdigevalueret førend runtime tager fat på metoden og dens parametre.
Avatar billede jakoba Nybegynder
26. januar 2006 - 14:48 #29
Der var den.  target reference evalueres først :-))
  http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.4
Avatar billede arne_v Ekspert
26. januar 2006 - 14:56 #30
saa er den god nok
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester