Tuesday, March 22, 2011

Printing number series with multiple threads

Problem: Write a code to print numbers 1 to 10 with using two threads such that one thread prints 1, 3, 5, 7, 9 and other thread prints 2, 4, 6, 8, 10


Solution:
Below is the code I wrote first but do not believe it to be an elegant solution, I plan to write a more elegant solution later but let's see when it happens.
With this solution, I ran into an issue when I used Integer class instead of MyInteger, could you spot the issue?

 public class AlternatePrint implements Runnable {  
int id;
MyInteger number;
// Integer number;
AlternatePrint(int id, MyInteger number) {
this.id = id;
this.number = number;
}
public void run() {
int last = id;
while (number.getValue() <= 10) {
synchronized (number) {
if (last != number.getValue()) {
System.out.println("Thread: " + id + " printing: "
+ number.getValue());
number.setValue(number.getValue() + 1);
last = number.getValue();
// number++;
// last = number;
}
try {
number.wait(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
System.out.println("Thread: " + id + " exiting!!!");
}
public static void main(String[] args) {
AlternatePrint a, b;
MyInteger o = new MyInteger(1);
a = new AlternatePrint(1, o);
b = new AlternatePrint(2, o);
new Thread(a).start();
new Thread(b).start();
System.out.println("Main Thread exiting!!!");
}
}
class MyInteger {
private int value;
MyInteger(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}

Tuesday, March 8, 2011

Find common elements in two sets of numbers.

Problem: Find common elements between 2 sets of numbers received from console.

For example: For following input:
Set A - > [ 1,4 ,7,9,11]
Set B - > [4, 9 , 13]
Output should be:
[4, 9]


Source Code:


 import java.io.BufferedReader;  
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
/**
*
* @author bhavin
*
*/
public class NumberUtil {
/**
* Delimiter used for separating numbers in string list consumed by createIntegerList
*/
public static final String SPACE_DELIMITER = " +";
/**
* Creates list of integers from the delimited list of numbers.
*
* @param elementsStr String containing numbers separated by delimiter
* @param delimiter Delimiter used to separate numbers in elementsStr
* @return List of valid-numbers present in elementsStr
*/
public static List<Integer> createIntgerList(String elementsStr, String delimiter) {
List<Integer> intList = new ArrayList<Integer>();
if (elementsStr == null)
return intList;
String[] strArray = elementsStr.split(delimiter);
for (int idx = 0; idx < strArray.length; idx++) {
try {
intList.add(Integer.parseInt(strArray[idx]));
} catch (NumberFormatException exception) {
//if string to number conversion fails, ignore the exception
System.out.println("'" + strArray[idx]
+ "' is possibly an invalid input, ignoring it.");
}
}
return intList;
}
/**
*
* @param firstList first list of numbers
* @param secondList second list of numbers
* @return return set of numbers which are common to both lists
*/
public static Set<Integer> getCommonElements(List<Integer> firstList,
List<Integer> secondList) {
List<Integer> smallList = null;
List<Integer> bigList = null;
Map<Integer, Integer> elements = new HashMap<Integer, Integer>();
Set<Integer> commonElements = new HashSet<Integer>();
if (firstList == null || secondList == null
|| firstList.size() == 0 || secondList.size() == 0)
return commonElements;
// For small list prepare the map
if (firstList.size() < secondList.size()) {
smallList = firstList;
bigList = secondList;
} else {
smallList = secondList;
bigList = firstList;
}
// prepare a map of elements present in the first map
for (Integer element : smallList) {
elements.put(element, element);
}
for (Integer element : bigList) {
if (elements.remove(element) != null) {
commonElements.add(element);
// when all, we have exhausted first list, no need to
// continue
if (elements.size() == 0)
break;
}
}
return commonElements;
}
public static void main(String[] args) {
List<Integer> firstElementList = null;
List<Integer> secondElementlist = null;
String firstElementListStr = null;
String secondElementListStr = null;
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(inputStreamReader);
try {
System.out.print("Enter first set: ");
firstElementListStr = br.readLine();
System.out.print("Enter second set: ");
secondElementListStr = br.readLine();
} catch (IOException e) {
System.out.println("Something went wrong while reading input,"
+ " exception stack-trace is printed below.");
e.printStackTrace();
} finally {
try {
br.close();
inputStreamReader.close();
} catch (IOException e) {
System.out.println("Something went wrong while closing "
+" stream-readers, exception stack-trace is printed below.");
e.printStackTrace();
}
}
firstElementList = createIntgerList(firstElementListStr,
SPACE_DELIMITER);
secondElementlist = createIntgerList(secondElementListStr,
SPACE_DELIMITER);
Set<Integer> commonElements = getCommonElements(firstElementList,
secondElementlist);
if (commonElements != null && commonElements.size() != 0)
System.out.println("Common Elements: " + commonElements);
else
System.out.println("There are no common elements.");
}
/**
* A unit-test method to test combined logic of createIntegerList and getCommonElements method.
*/
public static void testNumberUtil() {
String numberStr1 = "1 4 7 9 11";
String numberStr2 = "4 9 13";
String numberStr3 = "1 4 4";
String numberStr4 = "2";
String numberStr5 = "2 2 2x";
List<Integer> elements1;
List<Integer> elements2;
Set<Integer> commonElements;
//few common elements test-case
elements1 = createIntgerList(numberStr1, SPACE_DELIMITER);
elements2 = createIntgerList(numberStr2, SPACE_DELIMITER);
commonElements = getCommonElements(elements1, elements2);
if (commonElements.size() != 2)
System.out.println("Program fails for input: "
+ numberStr1 + " and " + numberStr2);
if (commonElements.contains(new Integer(4)) == false
|| commonElements.contains(new Integer(9)) == false )
System.out.println("Program fails for input: "
+ numberStr1 + " and " + numberStr2);
//no common elements test-case
elements1 = createIntgerList(numberStr3, SPACE_DELIMITER);
elements2 = createIntgerList(numberStr4, SPACE_DELIMITER);
commonElements = getCommonElements(elements1, elements2);
if (commonElements.size() != 0)
System.out.println("Program fails for input: "
+ numberStr3 + " and " + numberStr4);
//part-invalid input
elements1 = createIntgerList(numberStr4, SPACE_DELIMITER);
elements2 = createIntgerList(numberStr5, SPACE_DELIMITER);
commonElements = getCommonElements(elements1, elements2);
if (commonElements.size() != 1)
System.out.println("Program fails for input: "
+ numberStr4 + " and " + numberStr5);
if (commonElements.contains(new Integer(2)) == false)
System.out.println("Program fails for input: "
+ numberStr4 + " and " + numberStr5);
//null input
elements1 = createIntgerList(null, SPACE_DELIMITER);
elements2 = createIntgerList(null, SPACE_DELIMITER);
commonElements = getCommonElements(elements1, elements2);
if (commonElements.size() != 0)
System.out.println("Program fails for null inputs.");
}
}