Making Anagrams

I received a practice message from Hacker Rank. I like the idea to be reminded to spend some time practicing to solve a problem that is completely apart from the things I do at work or are in my learning schedule. The topic of the challenge is anagrams. You can find the description here.

After reading the description a couple times, it seems that the task is to remove characters from the two strings until we end up with two anagrams. In the example we end up with “a” as a string. Not much of an anagram. The goal is to return the number of characters removed from both strings. Continue reading “Making Anagrams”

Strings – Making Anagrams

anagram_sampleIn this blog entry I generated a solution for the Strings: Making Anagrams challenge at HackerRank.

For a description of the challenge please refer to the HackerRank web site using Strings: Making Anagrams.

I received a comment regarding two items:

Item Comment
1 I can’t see the utility of the line char c = s.charAt(i);
2 And the line hist += 1; has incompatibility error.

It has been almost a year since I posted this entry. Had to look through several workspaces to locate the actual source code and updates the project. Today I am using Eclipse IDE Version: Oxygen.1a Release (4.7.1a). Apparently the projects in that workspace were not compatible. Eclipse did whatever it needed to do and the source code appeared on the screen. Ran the code and all seems to be working fine.

Item 1

The only reason for it is testing. I like to see what the code is doing. I write several hundred thousand lines of code a year using different programming languages and IDEs. I like to use simple and easy to follow code. Typically with enough comments that remind me what and why I wrote code segments (which may be single lines).

The line in question could have been condensed as follows:

			// **** get the current character from the string ****
			
			char c = s.charAt(i);
			
			// **** increment the frequency associated with this character in the histogram ****
			
			hist += 1;
			
			// **** alternately condensing the above two statements into one ****
			
//			hist[s.charAt(i) - 'a'] += 1;

Item 2

Not sure why that statement is producing such error. The actual statement is:

hist += 1;	// NOT:  hist+= 1;

Lately (in the past year or so), I am using a different mechanism to surround code which produces nice output. The previous mechanism was not that great. Sorry is that caused confusions.

Following is a console screen capture of the Eclipse IDE when I tried the sample data:

cde
abc
<<< hist: c(1) d(1) e(1) 
<<< hist: a(1) b(1) c(1) 
numberNeeded <<< deleted: 4
4

The proper answer is 4. The reason for this is that ‘d’, ‘e’, ‘a’ and ‘b’ characters are not in both strings.

The approach that I used is to generate two histograms with the character counts in each string. The counts in the arrays are in alphabetic order where ‘a’ matches 0, ‘b’ matches 1 and so forth and so on. The final logic is to determine how many characters are in one array but not in the other.

The actual Java code for my solution follows:

package john.canessa.anagrams;

import java.util.Scanner;

public class Solution {

	final private static int totalLetters 	= 26;	// [a - z]

	/*
	 * print histogram
	 */
	private static void print(int[] hist) {
		System.out.print("<<< hist: ");
		for (int i = 0; i < totalLetters; i++) {
			if (hist[i] != 0) {
				System.out.print((char)(i + 'a') + "(" + hist[i] + ") ");
			}
		}
		System.out.println();
	}
	
	/*
	 * array with histogram of letters
	 */
	private static int[] histogram(String s) {
		int[] hist = new int[totalLetters];
		
		// **** traverse the string from start to finish ****
		
		for (int i = 0; i < s.length(); i++) {
			
			// **** get the current character from the string ****
			
			char c = s.charAt(i);
			
			// **** increment the frequency associated with this character in the histogram ****
			
			hist += 1;
			
			// **** alternately condensing the above two statements into one ****
			
//			hist[s.charAt(i) - 'a'] += 1;
		}
		return hist;
	}
	
	/*
	 * count characters needed to be deleted from both histograms
	 */
	private static int countCharacters(int[] firstHist, int[] secondHist) {
		int deleted	= 0;
		for (int i = 0; i < totalLetters; i++) {
			if (firstHist[i] != secondHist[i]) {
				deleted += Math.abs(firstHist[i] - secondHist[i]);
			}
		}
		return deleted;
	}
	
	/*
	 * count number of deleted characters
	 */
	public static int numberNeeded(String first, String second) {
		int	deleted	= 0;
		
		// **** build histogram with letters from first string ****
		
		int[] firstHist = histogram(first);
		print(firstHist);
		
		// **** build histogram with letters from second string ****
		
		int[] secondHist = histogram(second);
		print(secondHist);

		// **** count different characters on histograms ****
		
		deleted = countCharacters(firstHist, secondHist);
		System.out.println("numberNeeded <<< deleted: " + deleted);

		// **** return number of deleted characters ****
		
		return deleted;
	}

	/*
	 * test code
	 */
	public static void main(String[] args) {
		Scanner in 	= new Scanner(System.in);
		String a 	= in.next();
		String b 	= in.next();
		in.close();
		System.out.println(numberNeeded(a, b));
	}
}

The print() method is used for testing purposes only. References to that method are commented out in the final solution.

If you have comments or questions on this or any other blog entry, please send me a message via email.

John

www.johncanessa.com

Follow me on Twitter:  @john_canessa