views:

179

answers:

7

What would be the best logic to check all the letters in a given string.

If all the 26 letters are available in the provided string, I want to check that and perform so ops. eg. Pack my box with five dozen liquor jugs.

  1. Would using a Hash be useful?
  2. Or using a bit map? or any other way?

BTW my code would be in Java.

+3  A: 

I'd go for a bitmap. If you increment a counter each time you set an entry in the bitmap to 1, you can early return as soon as you've seen all the letters. I hope this is not for enforcing password requirements.

jdv
+1  A: 

Keep an boolean array of size 26. Each position of the array says whether a particular character is present or not (a is at 0, b is at 1, etc.). Initially all are set to false. Now do a single scan through the string character by character, setting the value for that character to true. At the end, check if all 26 indexes contain true.

MAK
OP requirements would allow you to break if one character is missing so you wouldn't need to check the indexes in the end.
Filburt
@Filburt: I don't understand what you mean. My check at the end is something like this `boolean ret=true;for(int i=0;i<26 i++) retreturn ret;`.
MAK
You don't need to do a second scan, just increment a counter when you turn on a bit, i.e. ...{ count+=(!letters[i]); letters[i]++} ... return 26 == count;
CodeninjaTim
@CodeninjaTim: That's right :). Thanks for pointing that out.
MAK
@MAK Well if you discover that there's no "b" in your input string it's a) pointless to try 24 more characters and b) pointless to scan your array at the end. In that case you would want your function return false immediately.
Filburt
@CodeninjaTim,exactly what i was thinking....
st0le
+1  A: 

An array of 26 booleans is enough, each entry representing on of the alphabet letters. You can set the entry to true when the letter is found.

Guillaume Lebourgeois
A: 

I'd go for a sieve algorithm on the 26 letters. Just my $.02.

Edit: An array of 26 values that represent the 26 letters of the alphabet. Then scan the string, checking each letter as you encounter it. At the end, check if the 26 letters have been checked.

Didier Trosset
@Didier, Could you elaborate?
st0le
+3  A: 

Using a BitMap, I'm assuming you meant case insenstive.

Update: Solution by Thomas is more efficient, than the following. :) Use that one.

    //
    String test  = "abcdefeghjiklmnopqrstuvwxyz";

    BitSet alpha = new BitSet(26);
    for(char ch : test.toUpperCase().toCharArray())
        if(Character.isLetter(ch))
            alpha.set(ch - 65);

    System.out.println(alpha.cardinality() == 26);
st0le
Yes, but this is much more readable and maintainable. And besides, mabye this operation doesn't need to be efficient.
Chris Knight
Will grow the bit set for characters which aren't ASCII Latin.
Pete Kirkham
+3  A: 

Not yet fully optimized:

public static void main(String... a) {
    String s = "Pack my box with five dozen liquor jugs.";
    int i=0;
    for(char c : s.toCharArray()) {
        int x = Character.toUpperCase(c);
        if (x >= 'A' && x <= 'Z') {
            i |= 1 << (x - 'A');
        }
    }
    if (i == (i | ((1 << (1 + 'Z' - 'A')) - 1))) {
        System.out.println("ok");
    }
}
Thomas Mueller
So... use "int" instead of a BitSet. It has enough bits. In Java, "int" will always have 32 bits, unlike in C.
Thomas Mueller
Wouldn't using `0x3FFFFFF` be faster?
st0le
The right side of the `|` contains no variables, so it would be calculated at compile time and stored as a constant. (This assumes a compiler with an optimizer.)
Blrfl
@Blrfl, I meant faster `compilation`. heehee... :) true!
st0le
Actually, no need for (i | ...), you might as well use if (i == (1 << (1 + 'Z' - 'A')) - 1) - or Integer.bitCount(i) == 26.
Thomas Mueller
Thomas Mueller
A: 

You could iterate over your string for each letter of the alphabet you want to check. When you find the letter you are looking for, continue with the next. If you don’t, abort. Here is some pseudo-code:

found = true;
for (letter in letters) {
    if (!string.contains(letter)) {
        found = false;
        break;
    }
}

This way you do not need to store the information for each letter but you have to search the string again and again for each letter. What you end up using will depend on your requirements: should it be fast? Should it use little memory? Your decision. :)

Bombe