3
public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String s = br.readLine();
    int[] arr = new int[26];
    for(int i=0;i<s.length();i++)
        arr[s.charAt(i)-'a']++;
    
    int odds = 0;
    for(int i=0;i<26;i++)
        if(arr[i]%2!=0)
            odds++;
    
    if(odds%2==1 || odds==0)
        System.out.println("First");
    else
        System.out.println("Second");

}

I saw this snippet of code and found this part confusing. So could you please tell me why do we use this and what is the significance of 'a' in arr[s.charAt(i)-'a']++;?

ggorlen
  • 44,755
  • 7
  • 76
  • 106
psygo
  • 95
  • 2
  • 10
  • 1
    `'a'` is a `char` literal. `char` is an integer type, so arithmetic with `char`'s is well defined and produces an integral result. – John Bollinger Aug 31 '18 at 20:24
  • 1
    @JohnBollinger But that doesn't mean anything unless you understand ASCII/Unicode and that all lowercase letters are consecutive. – Andreas Aug 31 '18 at 20:28
  • @JohnBollinger sir, can you please elaborate the use of this 'a', I did not understand. – psygo Aug 31 '18 at 20:28
  • Yes. 'a' corresponds to the integer 97 in java. So you are essentially just taking the integer when you call charAt(i) and you are subtracting the integer 97 from it. The integer value of characters is well documented. – Simeon Ikudabo Aug 31 '18 at 20:40
  • Possible duplicate of [adding and subtraction chars why does this work? (java)](https://stackoverflow.com/questions/21208308/adding-and-subtraction-chars-why-does-this-work-java) – ggorlen Aug 31 '18 at 22:40

2 Answers2

4

This code makes a histogram-like counter for each letter of the alphabet. Try printing a char such as 'a' as follows:

System.out.println((int)'a'); // Output: 97

Each char has a corresponding Unicode value between 0 and 65,535. Subtracting 'a' (or, 97) scales each letter in the alphabet to the 0-26 range that corresponds to the "buckets" in the arr array. Here's an example:

System.out.println('z' - 'a'); // Output: 25 (the last bucket in the array)
System.out.println('a' - 'a'); // Output: 0 (the first bucket in the array)

The second loop in the code checks the parity of each count to determine which are odd. Lastly, the final print conditional checks if the total number of letters with an odd number of occurrences. If this total is 0 or itself odd, print "First", else "Second".

Try this code with any character outside of a to z or with a capital letter. It'll crash because the ASCII representation of the character is out of the array's size and you'll wind up with an IndexOutOfBoundsException.

Here's a sample program showing how the histogram is built and converts its output back to letters through addition:

class Main {
    public static void main(String[] args) {
        String s = "snuffleupagus";
        int[] arr = new int[26];

        for (int i = 0; i < s.length(); i++) {
            arr[s.charAt(i)-'a']++;
        }

        for (int i = 0; i < arr.length; i++) {
            System.out.println((char)(i + 'a') + ": " + arr[i]);
        }
    }
}

Output:

a: 1
b: 0
c: 0
d: 0
e: 1
f: 2
g: 1
h: 0
i: 0
j: 0
k: 0
l: 1
m: 0
n: 1
o: 0
p: 1
q: 0
r: 0
s: 2
t: 0
u: 3
v: 0
w: 0
x: 0
y: 0
z: 0
ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • Small correction regarding the encoding. ASCII is in range 0-127 and extended in ASCII 0-255. The point is that char is in unicode standard, not ascii. – John Aug 31 '18 at 22:11
  • 1
    Thanks, I think this answer threw me off: https://stackoverflow.com/questions/21208308/adding-and-subtraction-chars-why-does-this-work-java – ggorlen Aug 31 '18 at 22:40
  • Java's `String` and `char` have nothing to do with ASCII or any of the character sets underspecified as "Extended ASCII". – Tom Blodget Aug 31 '18 at 23:40
  • 1
    Thanks a lot for answering. – psygo Sep 03 '18 at 18:54
2

arr is made of an int array of size 26, which is also the number of letters in English alphabet. All that loop is doing is counting the frequency of the letters, represented via their index in the alphabet, arr[0] being 'a', arr[1] being 'b', etc.

The technicalities of it can be explained simply. s.charAt(i) is returning a char instance at the specified position i. A char can also be represented as a byte in Java. The subtraction then takes the ASCII value (represented as a byte) of 'a' from the current character at i. So what you end up getting is 'a' - 'a' == 0, 'b' - 'a' == 1, and so on.

Please note that this is probably not the best way to count characters as a string can contain more than just the lowercase letters, e.g. uppercase letters, and many more symbols.

SupaHam
  • 1,125
  • 2
  • 12
  • 20