0

I have to write a function that takes 2 char[]s and returns:

  • -1 if the the first word comes before the second in a lexicographical order
  • 0 if they are the same word
  • 1 if it comes after

I'm aware of compareTo() method but this is an assignment, I need to avoid using it. So far, my code is working well, I've done a few tests with different words.

I was wondering if there was another way of doing it, my code doesn't feel optimized, it's long and repetitive:

public static int lexico(char[] word1, char[] word2) {
        int length1 = word1.length;
        int length2 = word2.length;

        if (length1 == length2) {
            for (int i = 0; i < length1; i++) {
                if (word1[i] < word2[i]) {
                    return -1;
                } else if (word1[i] > word2[i]) {
                    return 1;
                } else if (i == length1 - 1) {
                    return 0;
                }
            }
        }

        if (length1 < length2) {
            for (int i = 0; i < length1; i++) {
                if (word1[i] < word2[i]) {
                    return -1;
                } else if (word1[i] > word2[i]) {
                    return 1;
                } else if (i == length1 - 1) {
                    // If I'm here then it means that all of the characters
                    // from 0 to length1-1 are equals
                    // but since length of the first string is shorter than the second,
                    // the first string will be put before the second
                    return -1;
                }

            }
        }

        if (length1 > length2) {
            for (int i = 0; i < length2; i++) {
                if (word1[i] < word2[i]) {
                    return -1;
                } else if (word1[i] > word2[i]) {
                    return 1;
                } else if (i == length1 - 1) {
                    return 1;
                }
            }
        }

        return -999;
    }

public static void main(String[] args) {
    char[] share = { 's', 'h', 'a', 'r', 'e' };
    char[] ship = { 's', 'h', 'i', 'p' };

    System.out.println(lexico(share, ship)); // -1 share is before ship
    System.out.println(lexico(ship, share)); // 1 ship is after share
    System.out.println(lexico(ship, ship)); // 0 same word

}
Chai T. Rex
  • 2,972
  • 1
  • 15
  • 33
Blebhebhe
  • 83
  • 1
  • 9
  • 2
    If you're asking about improving working code, then you have come to the wrong place, and *perhaps* the [code-review stackexchange](https://codereview.stackexchange.com/) is a better fit, but before asking there, do check their [help](https://codereview.stackexchange.com/help) links to find out about their question requirements. I believe that you would need to provide metrics to quantify what you mean by "improved", but I could be wrong. – Hovercraft Full Of Eels Oct 17 '18 at 13:36
  • 3
    Look at the source of the `compareTo` implementation http://hg.openjdk.java.net/jdk7u/jdk7u6/jdk/file/8c2c5d63a17e/src/share/classes/java/lang/String.java – luk2302 Oct 17 '18 at 13:37
  • My hint rather than providing a solution as this is an assignment is to write a function that compares 2 chars (after all they are if I am not mistaken represented as an 16 bit unsigned integer). I would then write another function that would take 2 char arrays, and that would loop through them, using the function above to do an equality check. – Beezer Oct 17 '18 at 13:39

3 Answers3

2

A couple of notes for you:

  • You only need one loop: From the beginning to the lower of the two lengths. If the arrays are the same up until the lower of the two lengths and their lengths are different, your assignment should tell you what to return (normally it would be -1 if the left array was shorter than the right, 1 otherwise).

  • a < b isn't a valid alphabetic comparison of two characters (what most programmers mean when they say "lexicographic", the "lexico" meaning "pertaining to words"), it's a numeric comparison. Now, String's compareTo claims to use "lexicographic ordering," but it really just uses numeric ordering, so that may be good enough for what you're doing. If you want alphabetic ordering, I can't think of a JDK comparison method that accepts two single chars to compare rather than strings. There may be one I don't know of, or you may have to create one-character strings to do the comparison (with a Collator), which will (for instance) correctly identify that the à in "voilà" should be before any of the other letters in it.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Here is the ASCII table. UTF-8 respects the ASCII table int values for char, and by inference therefore in Java (if you use UTF-8). Given the certification information for Java fundamentals, the ASCII table below honours the lexographic ordering in Java: https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html So, the int values are correctly ordered and int comparison therefore is valid [Numbers before Uppercase before Lowercase]. I would therefore really like to know how this reasoning is falwed? – Beezer Oct 19 '18 at 15:22
  • @Beezer - I think most programmers mean "alphabetic" when they say "lexicographic." Alphabetically in any locale you want to pick, the `à` in "voilà" comes before any of the other letters in it if you sort them. And it does with a `Collator`. It doesn't if you do a naïve numeric comparison. I've updated the answer to draw the distinction. – T.J. Crowder Oct 19 '18 at 15:43
  • 1
    I see. Then actually the question I read was not the one posed. Thanks very much. This is actually a very subtle difference. Many thanks; I will check out Collator. – Beezer Oct 20 '18 at 15:37
  • @Beezer - I think you can read the question either way, actually. :-) In any case, your comment helped improve the answer. Thanks! – T.J. Crowder Oct 20 '18 at 17:46
  • I just looked up the differences between Lexico and Alpha: https://www.quora.com/Whats-the-difference-between-lexicographical-and-alphabetical-order ... the question clearly asks for Lexico...:=) so maybe I was being self-deprecating a little too soon. Thanks all the same....I will read on. – Beezer Oct 21 '18 at 18:08
  • @Beezer - Mathematics is just one domain where the word is used. In non-mathematics use, I believe you can ready "lexicographic order" as "dictionary order" -- e.g., alphabetical (mostly). – T.J. Crowder Oct 21 '18 at 18:10
  • Thanks. I mean the more I dig the crazier this subject matter gets. :=) – Beezer Oct 22 '18 at 19:41
0
Sharing a custom method for comparing two char array lexicographically

 public static int lexicographicalSort(char[] chArr1, char[] chArr2){

        // return -ve means chArr1 or first word comes before the second in a 
           lexicographical order
        // return  +ve means chArr1 or first word comes after the second in a 
           lexicographical order
        // return  0 means chArr1 and chArr2 contents are same

        int min = Math.min(chArr1.length,chArr2.length);
        int k = 0;

        while(k<min){
            if( chArr1[k] != chArr2[k]){
                return chArr1[k]-chArr2[k];
            }
            k++;
        }

        return chArr1.length-chArr2.length;
    }
abhinav kumar
  • 1,487
  • 1
  • 12
  • 20
-2

okay I gave up and wrote it...no Unit testing (always delivery code Unit Tested) but I think this should give you a good idea to work functionally (there are like edge cases like different lengths etc. I have not dealt with but you get the idea right?)...cheers and have fun :=)...it can be done more efficiently i guess with streams...

public static void main(String[] args) {
    List<Character> firstCharArr = new ArrayList<>(Arrays.asList('a', 'c'));
    List<Character> secondCharArr = new ArrayList<>(Arrays.asList('x', 'c'));

    BiFunction<Character, Character, Integer> charCompareFunction = new BiFunction<Character, Character, Integer>() {
        @Override
        public Integer apply(Character character, Character character2) {
            if (character.charValue() < character2.charValue()) {
                return -1;
            } else if (character.charValue() == character2.charValue()) {
                return 0;
            } else {
                return 1;
            }
        }
    };

    int i = 0;
    for (Character firstLineChar : firstCharArr) {
        if (charCompareFunction.apply(firstLineChar, secondCharArr.get(i++)) == 0) {
            continue;
        } else {
            if (charCompareFunction.apply(firstLineChar, secondCharArr.get(i++)) < 0) {
                System.out.println("FirstLine is Smaller");
                break;
            } else {
                System.out.println("FirstLine is Larger");
                break;
            }
        }
    }
}

In fact, you can using the above, prove the character lexicographic order of Java: Numbers before letters Uppercase before lowercase

Beezer
  • 1,084
  • 13
  • 18
  • Why would you bother with a BiFunction here instead of another method? – Louis Wasserman Oct 17 '18 at 15:14
  • Because I felt like it Louis. I am free to express myself in a language that you are not the police of, even if you work for Google. Freedom of expression. 1st amendment right I believe. Feeling like it...the same way you felt like commenting and maybe down-voting it. But i don't care. Its not your language. It belongs to anyone and everyone that feels like using it to express themselves to have Fun. You remember FUN right Louis? Fun trumps ego. – Beezer Oct 18 '18 at 11:01