0

couple of years ago I was on an interview and received a question that I'd love to know how to solve in Java correctly. Given a string, return true if that string is made up of only letter combinations that exist in periodic table element names.

FriendlyMikhail
  • 2,857
  • 23
  • 39
  • 1
    Do you mean; is the word an anagram of a word in the periodic table? BTW If they didn't say it had to return `false`, you could just return `true` all the time ;) – Peter Lawrey Apr 19 '15 at 16:34
  • 1
    Not necessarily an anagram,term can be made up of multiple periodic element abbrevations – FriendlyMikhail Apr 19 '15 at 16:37
  • Compile a `java.util.regex Pattern tabloids` allowing concatenations of the element names(/abbreviations?!) and have the JRE do `tabloids.matcher(givenString).matches()`. – greybeard Apr 19 '15 at 18:15
  • @greybeard could you expand on your solution a bit. I'm not very good with regex. Yes it is abbreviations – FriendlyMikhail Apr 19 '15 at 18:19
  • possible duplicate of [Dynamic Programming - Word Break](http://stackoverflow.com/questions/25168061/dynamic-programming-word-break) – Paul Hankin Apr 19 '15 at 23:38

4 Answers4

1

Not necessarily an anagram,term can be made up of multiple periodic element abbrevations

What you can do is start a collection of two letter and one letter abbreviations.

From this you can recursively attempt to search for two letter (only one possibility at time) or one letter matches. This can be done progressively meaning the worst case cost is O(2^N) search time. (Still pretty horrible but better than brute force)

e.g. say you have "bar"

  • look up the set of two letters for "ba" and there is, this leaves one letter "r" which doesn't exist.
  • then backtrack to look for "b" and then "ar" which both exist.

You could search for one letter then two letter at a time, but this would be slower if either would be a solution.


If you need to check if the word is an anagram of another set of words, you can do

public static String sortLetters(String str) {
   char[] chars = str.toLowerCase().toCharArray();
   Arrays.sort(chars);
   return new String(chars);
}

// first build a set of sorted words in lower case.
public static Set<String> buildLookup(Collection<String> words) {
   return words.stream().map(s -> sortLetters(s)).collect(toSet()));
}

// use the pre built set of words for the lookup.  O(1) operation for small words.
public static boolean isAnagram(Set<String> lookup, String word) {
    return lookup.contains(sortLetters(word));
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
1

See my answer here for same puzzle: Dynamic Programming - Word Break

This is O(N) solution.

Community
  • 1
  • 1
olegarch
  • 3,670
  • 1
  • 20
  • 19
0

This I relatively easy from the logical side , well technically most element names on the periodic table are 2 Letters long .

String elements = "alcamgheo"

Well some elements are a letter long only ....so this problem will also have to be paid attention to..

Here you can have a function make an array by splitting the string at intervals of 2 letters .

Create your own logic to sort the single lettered ones to the end , and then just read the array and when you encounter an array position containing something which doesn't resemble an element like OC ... Then you know that the single lettered elements are being read..so just join them into another string and read at intervals of every single charecter.

TheAnimatrix
  • 566
  • 1
  • 6
  • 19
0

If the problem was to return whether the given string could be split into element abbreviations, Java code might delegate this to the java.util.regex package. For the hell of it:

import java.util.regex.Pattern;

/** is CharSequence weird enough to be split into
    chemical element abbreviations? */
class Weirdo {
    static final Pattern tabloids;
    static {
    // single character element abbreviations
        StringBuilder eap = new StringBuilder(250)
            .append("([HBCNOFPSKVYIWU]");
    //  two-character element abbreviations
        char [] abbreviations = (
            "HeLiBeNeNaMgAlSiClAr" +
            "CaScTiCrMnFeCoNiCuZnGaGeAsSeBrKr" +
            "RbSrZrNbMoTcRuRhPdAgCdInSnSbTeXe" +
            "CsBaLaCePrNdPmSmEuGdTbDyHoErTmYb" +
              "LuHfTaReOsIrPtAuHgTlPbBiPoAtRn" +
            "FrRaAcThPaNpPu").toCharArray();
        for (int i = 0 ; i < abbreviations.length ; i++) 
            eap.append('|') // tack on one alternative each
               .append(abbreviations[i++])
               .append(abbreviations[i]);
        eap.append(")*"); // allow arbitrary repetition 
        tabloids = Pattern.compile(eap.toString(),
                       Pattern.CASE_INSENSITIVE);
    }

    /** @return decomposability of <code>input</code>
     *          into element abbreviations */
    static boolean isWeird(CharSequence input) {
        return tabloids.matcher(input).matches();
    }

    public static void main(String[] args) {
        String [] toCheck =
            (null != args && 0 < args.length) ? args
            : ("Plankalkül assembler Fortran Algol Lisp " +
            "COBOL APL BASIC Simula PL/I Forth PEARL " +
            "Pascal Smalltalk C Prolog ELAN shell awk " +
            "Ada Beta Occam DACAPO Eiffel SQL Self Perl " +
            "Erlang Oberon Haskell Python Oak Lua Ruby " +
            "ECMAScript Java gBeta Swift").split(" ");
        for (String given: toCheck)
            System.out.println(given + ": " +
                               isWeird(given));
    }
}
greybeard
  • 2,249
  • 8
  • 30
  • 66