EvilZone

Programming and Scripting => Java => : leewillz May 12, 2012, 09:24:54 PM

: anyone done regex before?
: leewillz May 12, 2012, 09:24:54 PM
im looking for an expression that takes a scrambled word and finds it in a list i have currently
 "^["+word+"]{"+word.length()+"}$"
but its not perfect i gets confused quite easily anyone know a better one?
: Re: anyone done regex before?
: Kulverstukas May 12, 2012, 09:53:36 PM
I don't think you can do this with regex. You will have to search for words one by one, comparing char by char.
: Re: anyone done regex before?
: Deque May 12, 2012, 10:29:34 PM
It is not possible with regex alone.
But you can try something like this:

:
private static boolean isScrambledWord(char[] word1, char[] word2) {
        Arrays.sort(word1);
        Arrays.sort(word2);
        return Arrays.equals(word1, word2);
}
: Re: anyone done regex before?
: Kulverstukas May 12, 2012, 10:46:15 PM
I just whipped a complete solution for you. It was fun remembering how to code in Java :D
I am certain it works like you described. Loops through every word in array (your list) until the match is found, or not. Just run and see! hope this helps you to understand what is going on, tried to comment the code as much as I can.

:
package bandymas;

public class test {

    // our array of words
    private final static String[] scrambledWordArray = {"apple", "carrot", "tomatoe", "cannabis", "manure", "garden", "tree"};
    // scrambled "manure"
    private final static String wordToMatch = "rueanm";
   
    // method to match 2 words
    private static boolean matchWord(String scrambledWord, String word) {
char[] charArray = scrambledWord.toCharArray(); // split the word into chars
boolean matches = false;
// loop through each char of the scrambled word, checking if given words contains them
for (int i = 0; i < charArray.length; i++) {
    if (word.contains(charArray[i]+"")) {
matches = true;
    } else {
matches = false;
break; // if single char can't be found then get out, it's not the word
    }
}
return matches;
    }
   
    // method that loops through word array checking each word for a match
    private static String findWord(String scrambledWord) {
int arraySize = scrambledWordArray.length;
// default string to be returned. If match is found it will be overwritten
String returnString = "No match can be done, sorry!";
boolean matchFound = false;
for (int i = 0; i < arraySize; i++) {
    matchFound = matchWord(scrambledWord, scrambledWordArray[i]);
    if (matchFound) {
returnString = "Found a match of word \""+scrambledWord+"\" as \""+scrambledWordArray[i]+"\"";
break; // not very good code-wise but it'll do this time
    }
}

return returnString;
    }
   
    public static void main(String[] args) {
System.out.println(findWord(wordToMatch));
    }

}
: Re: anyone done regex before?
: Deque May 14, 2012, 07:18:11 PM
Kulver, I am sorry to disappoint you, but your code is not better than the regex of leewillz. Example: Change "manure" to "mannurre". Your program will still say that is matches "rueanm".
: Re: anyone done regex before?
: Kulverstukas May 14, 2012, 08:28:56 PM
Oh darn :D well I tried... I'm sure this can be corrected with a simple hack, but I won't bother - let the OP do his homework.
: Re: anyone done regex before?
: ca0s May 14, 2012, 08:48:00 PM
Is this for a SO challenge? :P
: Re: anyone done regex before?
: s3my0n May 15, 2012, 06:03:45 AM
It is not possible with regex alone.
But you can try something like this:

:
private static boolean isScrambledWord(char[] word1, char[] word2) {
        Arrays.sort(word1);
        Arrays.sort(word2);
        return Arrays.equals(word1, word2);
}

This ^ .

Runs in O(k(n log n)), as far as I can tell, where k is the number of words in checking dictionary, and n is the length of the scrambled word. You only need to sort the scrambled word once.

Before sorting though you gotta check if the lengths of the two words are the same.
: Re: anyone done regex before?
: techb May 15, 2012, 07:14:24 AM
Le regex reff (http://www.regular-expressions.info/reference.html). But really regex was a problematic thing for me to get a grasp of. It will take more than one example or use of regular expressions is required.


Just remember regex is used for special occasions when regular splitting and error checking is viable. The only place in real life I've ever seen regex, except for learning, is with PBX and voice manipulations when human language is required. Linguistics is the only area I've personally seen it in. Correct me if I'm wrong, I enjoy regex.
: Re: anyone done regex before?
: Deque May 15, 2012, 03:08:39 PM
This ^ .

Runs in O(k(n log n)), as far as I can tell, where k is the number of words in checking dictionary, and n is the length of the scrambled word. You only need to sort the scrambled word once.

Before sorting though you gotta check if the lengths of the two words are the same.

It's only a sketch. ;)
The code has a trap too. It changes its arguments, because the arrays are not copied before sorting. But I think the TO is responsible for taking care of the details.

Edit: If I write "something like this" it usually means you shouldn't copy&paste the code without thinking.
: Re: anyone done regex before?
: leewillz May 16, 2012, 01:03:42 AM
thanks guys,
glad this sparked some interest and discussion, it was just something that interested me, being able to find a jumbled word from a list of words, the solutions are very good and different being the key, sadly i still have no complete solution to this but i will update you if i find one. thanks all for the replies!
: Re: anyone done regex before?
: s3my0n May 16, 2012, 01:24:16 AM
I coded the solution in C (if you don't mind me posting C code in Java forum ^^):

Basically it sorts the scrambled word and then loops through every word in the dictionary, and if the word's length is the same as the scrambled word it copies the scrambled word and then sorts that copy. After that it tries to match the two sorted words and if they are the same then the scrambled is found.

:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 7

char scrambled_word[] = "esmdcrlab"; // scrambled
char *dictionary[SIZE] = {"world", "array", "testing", "largeword", "abitlargerword", "scrambled", "download"};

int compare(const void *a, const void *b)
{
    return ( *(char*)a - *(char*)b );
}

int matchWord(const char *scrambled, char *word)
{
    // assuming scrambled is aready sorted
    size_t wlen = strlen(word);
    char test_word[wlen+1];
    if (strlen(scrambled) == wlen){
        strncpy(test_word, word, wlen);
        qsort(test_word, wlen, sizeof(char), compare);
        if (!strncmp(test_word, scrambled, wlen))
            return 1;
    }

    return 0;
}

int main(void)
{
    size_t scrlen = strlen(scrambled_word);
    char orig_scrambled[scrlen+1];
    strncpy(orig_scrambled, scrambled_word, scrlen);
    qsort(scrambled_word, scrlen, sizeof(char), compare);
    int i;
    for (i = 0; i < SIZE; i++){
        printf("Testing: %s\n", dictionary[i]);
        if (matchWord(scrambled_word, dictionary[i])){
            printf("[+] %s is %s !\n", orig_scrambled, dictionary[i]);
            return 0;
        }
    }

    printf("[-] %s is not in the dictionary\n", scrambled_word);

    return 0;                                         
}
: Re: anyone done regex before?
: leewillz May 16, 2012, 03:25:48 AM
excellent thanks for this, ive rewritten in java and adapted slightly this is what i have now and it works wonderfully!
: Re: anyone done regex before?
: Deque May 16, 2012, 06:04:29 AM
@leewillz

public static boolean matchWord(String scrambled, String aWord)

Java has a method called equals() for every Object that is overriden by String for string comparison. Use it instead of implementing a worse O(n^2) version.

:
public static void toChar(int i) 
    {
 
               for (int j = 0; j < dictionary[i].length(); j++) 
        {
                   array_elem = dictionary[i].toCharArray();
               }
    }

Why do you assign the array n times? Do you realize that you are overriding the previous assignment several times?

:
else
                {//do nothing basically}

?

:
if (compare(scrambled_word.length(), dictionary[i].length()) == 0)
Writing
:
if(scrambled_word.length() == dictionary[i].length()) is more straightforward, more concise and better understandable.

:
array_elem = null;//reset the array for the next word.
Useless line of code.

You didn't apply any sorting. You say it works, but if it does I don't believe it works right.
The version you gave doesn't even compile.

You adapted the C style for naming your variables. There are Java code conventions (http://www.oracle.com/technetwork/java/codeconv-138413.html). Variable names should be camel case.

________________________________________________

@s3my0n:

After your last post I thought you would create a version with a better asymptotic runtime (it seemed to be your point of argument).
: Re: anyone done regex before?
: s3my0n May 16, 2012, 10:35:40 AM

@s3my0n:

After your last post I thought you would create a version with a better asymptotic runtime (it seemed to be your point of argument).

No, I was happy with the sorting approach to this problem, I just wanted to implement it :)
: Re: anyone done regex before?
: Deque May 16, 2012, 11:19:01 AM
No, I was happy with the sorting approach to this problem, I just wanted to implement it :)

I am not a C expert, but well done.
: Re: anyone done regex before?
: leewillz May 16, 2012, 06:55:46 PM
the code does work fine, bearing in mind it was 2:30 on me doing it, the toChar method is pointless i see it now ive changed it, the output i get is attatched. ive not corrected everything is it works fine even if its not to "java convention"
 thanks Lee
: Re: anyone done regex before?
: Deque May 16, 2012, 09:22:04 PM
the code does work fine, bearing in mind it was 2:30 on me doing it, the toChar method is pointless i see it now ive changed it, the output i get is attatched. ive not corrected everything is it works fine even if its not to "java convention"
 thanks Lee

Then let me tell you this again: The code you provided here does not compile. There is at least one curly bracket and a return statement missing in the end.
I didn't say that it doesn't run on your machine. Maybe something went wrong with copy&paste or whatever, but it doesn't work, no matter what you tell me.

And now to the working right part: That it works right for one input, doesn't mean it works right for every input. Testing can never tell you the absence of bugs. It only might tell you the presence.
However I can't prove anything, because your code doesn't compile.

Of course it works although you didn't care for java code conventions. You didn't even look what they are for, did you? Otherwise you would know that this has nothing to do with each other.
: Re: anyone done regex before?
: leewillz May 16, 2012, 11:10:08 PM
ive just downloaded the file and tried to compile, the problem is the comment in the else statement,
else
                {//do nothing basically}
if u want it to run then get rid of the comment or the else in total, up to you but basically the comment is commenting out the bracket, work after that.
: Re: anyone done regex before?
: Deque May 17, 2012, 06:20:30 AM
ive just downloaded the file and tried to compile, the problem is the comment in the else statement,
else
                {//do nothing basically}
if u want it to run then get rid of the comment or the else in total, up to you but basically the comment is commenting out the bracket, work after that.

You are right, that was the reason it didn't work.

Now try "array" and "aaray". They will match, because your algorithm doesn't care how often the characters occur. As long as the length is the same and every distinct character is at least one time in the scrambled word, it will match.

Testing: world
Testing: araay
array is araay !
: Re: anyone done regex before?
: leewillz May 17, 2012, 11:34:33 AM
indeed, i have thought of a way to overcome this, i shall test this now and post the results.
: Re: anyone done regex before?
: leewillz May 17, 2012, 01:16:25 PM
i think this has sored it out, basically ive changed it to an array list of the characters and when if finds the element it removes it from the arraylist therefore matching the correct ammount of letters in the word. let me know if it works for you  :)

:
import java.util.ArrayList;
import java.util.Scanner;

public class Scrambled {

    public static String scrambled_word;
    public static String[] dictionary = {"world", "array", "scrambled", "testing", "scrambley", "largeword", "abitlargerword", "download"};
    public static ArrayList<Character> orig_word = new ArrayList<Character>();
    public static ArrayList<Character> array_elem = new ArrayList<Character>();
    public static char[] array_elem1 = new char[100];
    public static char[] orig_word1 = new char[100];
    public static boolean quit = false;

    public static void main(String[] args) {
        while (!quit) {
            Scanner s = new Scanner(System.in);
            System.out.println("Enter a string to look for:>");
            scrambled_word = s.nextLine();
            if (scrambled_word.equalsIgnoreCase("q")) {
                quit = true;
            } else {
                orig_word1 = scrambled_word.toCharArray();
                for (int i = 0; i < orig_word1.length; i++) {
                    orig_word.add(orig_word1[i]);
                }

                for (int i = 0; i < dictionary.length; i++) {

                    if (compare(scrambled_word.length(), dictionary[i].length()) == 0) {
                        System.out.println("Testing: " + dictionary[i]);
                        array_elem1 = dictionary[i].toCharArray();
                        swap(array_elem1);

                        if (matchWord()) {
                            System.out.println(dictionary[i] + " is the word you are loooking for");

                        } else {
                            System.out.println("this is not the scrambled word");
                        }
                    }
                    removeElem();
                }

            }
        }
    }

    public static int compare(int a, int b) {

        return a - b;

    }

    public static void swap(char[] words) {
        for (int i = 0; i < words.length; i++) {
            array_elem.add(words[i]);
        }


    }

    public static void removeElem() {
        for (int i = array_elem.size() - 1; i >= 0; i--) {
            array_elem.remove(i);
        }
    }

    public static boolean matchWord() {
        // assuming scrambled is aready sorted

        int m = 0;
        for (int i = 0; i < orig_word.size(); i++) {
            for (int j = 0; j < array_elem.size(); j++) {

                if (orig_word.get(i) == array_elem.get(j)) {

                    m = 1;
                    array_elem.remove(j);
                    array_elem.trimToSize();
                    break;
                } else {
                }
            }
            if (m == 0) {
                return false;
            } else {
                m = 0;
            }
        }
        return true;
    }
}
: Re: anyone done regex before?
: Deque May 17, 2012, 01:45:49 PM
yrraa should match array, but it doesn't.

Enter a string to look for:>
yrraa
Testing: world
this is not the scrambled word
Testing: array
this is not the scrambled word

Edit: It is a good thing that you try to solve this yourself. You could have just used the sorting approach that s3myon and I suggested, but what you do is a complete different way. Go on, you will get it your way.
: Re: anyone done regex before?
: leewillz May 17, 2012, 01:53:05 PM
hi  idont know whats going on there but ive just had a go on yrraa and it seems to pick it up :S ive done a few tweeks again ill post it now, this time ive used a text file with the words and it reads from the file to an array but main code is still the same.
:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

public class Scrambled {

    public static String scrambled_word;
    public static ArrayList<String> dictionary = new ArrayList<String>();
    public static ArrayList<Character> orig_word = new ArrayList<Character>();
    public static ArrayList<Character> array_elem = new ArrayList<Character>();
    public static char[] array_elem1 = new char[100];
    public static char[] orig_word1 = new char[100];
    public static boolean quit = false;

    public static void main(String[] args) throws FileNotFoundException, IOException {
        while (!quit) {
            try{
               removeElem(dictionary);
             BufferedReader in = new BufferedReader(new FileReader("C:\\Users\\Lee\\Documents\\NetBeansProjects\\Lab12\\src\\lab15\\read.txt"));
            int add = 0;
             while(in.ready()){               
                 dictionary.add(add, in.readLine());
                 add++;
               
             }
            }catch(FileNotFoundException e)
            {
                System.out.println("File not found");
            }
            Scanner s = new Scanner(System.in);
            System.out.println("Enter a string to look for:>");
            scrambled_word = s.nextLine();
            if (scrambled_word.equalsIgnoreCase("q")) {
                quit = true;
            } else {
                orig_word1 = scrambled_word.toCharArray();
                for (int i = 0; i < orig_word1.length; i++) {
                    orig_word.add(orig_word1[i]);
                }

                for (int i = 0; i < dictionary.size(); i++) {

                    if (compare(scrambled_word.length(), dictionary.get(i).length()) == 0) {
                     
                        array_elem1 = dictionary.get(i).toCharArray();
                        swap(array_elem1);

                        if (matchWord()) {
                            System.out.println(dictionary.get(i) + " is the word you are loooking for");

                        } else {
                           
                        }
                    }
                    removeElem(array_elem);
                }

            }
        }
    }

    public static int compare(int a, int b) {

        return a - b;

    }

    public static void swap(char[] words) {
        for (int i = 0; i < words.length; i++) {
            array_elem.add(words[i]);
        }


    }

    public static void removeElem(ArrayList array) {
        for (int i = array.size() - 1; i >= 0; i--) {
            array.remove(i);
        }
    }

    public static boolean matchWord() {
        // assuming scrambled is aready sorted

        int m = 0;
        for (int i = 0; i < orig_word.size(); i++) {
            for (int j = 0; j < array_elem.size(); j++) {

                if (orig_word.get(i) == array_elem.get(j)) {

                    m = 1;
                    array_elem.remove(j);
                    array_elem.trimToSize();
                    break;
                } else {
                }
            }
            if (m == 0) {
                return false;
            } else {
                m = 0;
            }
        }
        return true;
    }
}
: Re: anyone done regex before?
: ca0s May 17, 2012, 02:04:53 PM
I solved this problem with a hash table. Something like (wants to be perl syntax):
Initialization:
foreach (@word) {
    $w = $_;
    $table{sort_letters_alphabetically($w)} = $w;
}
Lookup:
echo $table{sort_letters_alphabetically($scrambled_word)};
Where sort_letters_alphabetically("testingword") = "deginorsttw"

Just giving another way. IDK if would work fine in every testing case.
: Re: anyone done regex before?
: Deque May 17, 2012, 02:12:29 PM
Alright. I used the updated code and yrraa works, but raary doesn't.

Enter a string to look for:>
yrraa
array is the word you are loooking for
Enter a string to look for:>
raary
Enter a string to look for:>

It may help you to create a test suite, that covers a lot of cases at once while you are working on your algorithm.
: Re: anyone done regex before?
: leewillz May 17, 2012, 02:20:32 PM
i know why that is aswell, when it finds array once it gets deleted from the arraylist so some more tweeking i think.
: Re: anyone done regex before?
: leewillz May 17, 2012, 02:36:29 PM
correction, the reason was very simple i wasnt clearing the orig_word arraylist so basically when you were enterring yrraa it was looking for yrraa but then when you enter raary it was actually looking for yrraaraary because it wasnt clearing the array this should solve it.
:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

public class Scrambled {

    public static String scrambled_word;
    public static ArrayList<String> dictionary = new ArrayList<String>();
    public static ArrayList<Character> orig_word = new ArrayList<Character>();
    public static ArrayList<Character> array_elem = new ArrayList<Character>();
    public static char[] array_elem1 = new char[100];
    public static char[] orig_word1 = new char[100];
    public static boolean quit = false;

    public static void main(String[] args) throws FileNotFoundException, IOException {
       
            try{
               
             BufferedReader in = new BufferedReader(new FileReader("C:\\Users\\Lee\\Documents\\NetBeansProjects\\Lab12\\src\\lab15\\read.txt"));
            int add = 0;
             while(in.ready()){               
                 dictionary.add(add, in.readLine());
                   add++;             
             }
             in=null;
             
            }catch(FileNotFoundException e)
            {
                System.out.println("File not found");
            }
             while (!quit) {
            Scanner s = new Scanner(System.in);
            removeElem(orig_word);
            removeElem(array_elem);
            System.out.println("Enter a string to look for:>");
            scrambled_word = s.nextLine();
            if (scrambled_word.equalsIgnoreCase("q")) {
                quit = true;
            } else {
                orig_word1 = scrambled_word.toCharArray();
                for (int i = 0; i < orig_word1.length; i++) {
                    orig_word.add(orig_word1[i]);
                }

                for (int i = 0; i < dictionary.size(); i++) {

                    if (compare(scrambled_word.length(), dictionary.get(i).length()) == 0) {
                     
                        array_elem1 = dictionary.get(i).toCharArray();
                        swap(array_elem1);

                        if (matchWord()) {
                            System.out.println(dictionary.get(i) + " is the word you are loooking for");

                        } else {
                           
                        }
                    }
                    removeElem(array_elem);
                }

            }
        }
    }

    public static int compare(int a, int b) {

        return a - b;

    }

    public static void swap(char[] words) {
        for (int i = 0; i < words.length; i++) {
            array_elem.add(words[i]);
        }


    }

    public static void removeElem(ArrayList array) {
        for (int i = array.size() - 1; i >= 0; i--) {
            array.remove(i);
        }
    }

    public static boolean matchWord() {
        // assuming scrambled is aready sorted

        int m = 0;
        for (int i = 0; i < orig_word.size(); i++) {
            for (int j = 0; j < array_elem.size(); j++) {

                if (orig_word.get(i) == array_elem.get(j)) {

                    m = 1;
                    array_elem.remove(j);
                    array_elem.trimToSize();
                    break;
                } else {
                }
            }
            if (m == 0) {
                return false;
            } else {
                m = 0;
            }
        }
        return true;
    }
}
: Re: anyone done regex before?
: Deque May 17, 2012, 03:05:45 PM
Congrats, it works now.
(but the code got pretty messy)
: Re: anyone done regex before?
: leewillz May 17, 2012, 11:36:11 PM
haha excellent (just how i like it)  ;)