Wednesday, September 30, 2009

Maintain Layout Orientation in Android Applications

Here is a one-liner statement in your manifest xml (AndroidManifest.xml) to maintain your preferred portrait layout orientation. Simply add this line in the XML:

android:screenOrientation="portrait"
Otherwise, you may also use "landscape" as the value.
android:screenOrientation="landscape"

Further information is available at the Android Developers Website

Changing the Orientation of Android Emulator

Simply use these key combination:
fn + control + F12

Tuesday, September 22, 2009

Tokenizing String Recursively

This is an update to the blog entry "String tokenizer by hand". In this article, I am demonstrating an example of tokenizing a given string in a recursive manner. The code is as below:

import java.util.ArrayList;

public class StringTokenizer {

private static ArrayList tokenizedStr = new ArrayList();
private static StringBuffer str = new StringBuffer();

public static ArrayList tokenizer(String input){
int strLength = input.length();
return tokenizer(input, 0, strLength);
}

public static ArrayList tokenizer(String input, int currentIndex, int strLength){
if (currentIndex < strLength) {
char curr = input.charAt(currentIndex);
if (curr != ' ') {
str.append(curr);
} else {
if (str.length() != 0) {
tokenizedStr.add(str);
}
str = new StringBuffer();
}
if ((currentIndex == strLength-1 ) && (curr != ' ')) {
tokenizedStr.add(str);
}
currentIndex++;
tokenizer(input, currentIndex, strLength);
}
return tokenizedStr;
}

public static void main(String[] args) {
System.out.println(tokenizer(" Hello World This is Nicholas Key. How are you? "));
}

}

Screenshot of Android 1.6 SDK

This is how the most recent Android 1.6 SDK looks like :)

Wednesday, September 16, 2009

Venture Capitalists and Investors

This is an interesting video for us to ponder together and to reflect ourselves.

Tuesday, September 15, 2009

Android, iPhone, PalmOS

These are the screenshots of the desktop from three smartphones. From left to right: Android, iPhone and PalmOS. I personally prefer to write applications on Android simply because I'm familiar with Eclipse as the IDE and Java as the programming language, followed by iPhone simply because of the demand in the market and lastly, the PalmOS.

Sunday, September 13, 2009

Binary Tree and its popular methods

This is something convenient I think to do a brief revision on Binary Tree other than reading about it on Wikipedia. This implementation demonstrates the construction of binary tree with some elements and the typical methods related to it such as:
[1] Pre-Order Traversal
[2] In-Order Traversal
[3] Post-Order Traversal
[4] Getting the size of the binary tree
[5] Get the minimum value
[6] Get the maximum value
[7] Get root value
[8] Inserting new elements

My implementation does not include duplication of elements. You may copy the code and test it yourself.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

public class BinaryTree {

private static class TreeNode {
TreeNode left;
TreeNode right;
int nodeValue;
TreeNode(int data) {
left = null;
right = null;
nodeValue = data;
}
}

private TreeNode root;

public BinaryTree() {
root = null;
}

public void constructBinaryTreeHardCoded() {
root = null;

root = new TreeNode(6);
//root = insertData(root, 6);

root = insertData(root, 2);
root = insertData(root, 7);
root = insertData(root, 1);
root = insertData(root, 4);
root = insertData(root, 9);
root = insertData(root, 3);
root = insertData(root, 5);
root = insertData(root, 8);
}

public void testHarness(){
root = null;

Random rand = new Random();
int rootValue = rand.nextInt( 20 ) + 1;
root = new TreeNode(rootValue);
System.out.println("Random seeded root value: " + rootValue);
int numberOfNodes = rand.nextInt( 18 ) + 1;
System.out.println("Random number of children to be generated: " + numberOfNodes);
for (int i = 0; i < numberOfNodes; i++) {
int randValue = rand.nextInt( 30 ) + 1;
System.out.println("Inserting: " + randValue);
root = insertData(root, randValue);
}
}

public TreeNode insertData(TreeNode node, int data) {
if (node == null) {
node = new TreeNode(data);
} else {
if (data < node.nodeValue) {
if (node.left != null) {
node.left = insertData(node.left, data);
} else {
node.left = new TreeNode(data);
System.out.println("Inserted " + data + " to the left of " + node.nodeValue);
}
} else if (data > node.nodeValue) {
if (node.right != null) {
node.right = insertData(node.right, data);
} else {
node.right = new TreeNode(data);
System.out.println("Inserted " + data + " to the right of " + node.nodeValue);
}
} else {
System.out.println("Not inserting " + data + " because it already exists in the tree");
}
}
return(node);
}

public boolean isIdenticalTree(BinaryTree comparedTree) {
return (isIdenticalTree(root, comparedTree.root));
}

private boolean isIdenticalTree(TreeNode first, TreeNode second) {
if (first == null && second == null) {
return true;
} else if (first != null && second != null) {
return (
first.nodeValue == second.nodeValue &&
isIdenticalTree(first.left, second.left) &&
isIdenticalTree(first.right, second.right)
);
} else {
return false;
}
}

public int getSize() {
return(setSize(root));
}

private int setSize(TreeNode node) {
if (node == null) {
return 0;
} else {
return(setSize(node.left) + 1 + setSize(node.right));
}
}

public void printTreeTraversal() {
System.out.print("Inorder Traversal: ");
printInOrder(root);
System.out.print("\nPreorder Traversal: ");
printPreOrder(root);
System.out.print("\nPostorder Traversal: ");
printPostOrder(root);
System.out.println();
}


private void printInOrder(TreeNode node) {
if (node == null) {
return;
}
printInOrder(node.left);
visitTreeNode(node);
printInOrder(node.right);
}

private void printPreOrder(TreeNode node) {
if (node == null) {
return;
}
visitTreeNode(node);
printPreOrder(node.left);
printPreOrder(node.right);
}

private void printPostOrder(TreeNode node) {
if (node == null) {
return;
}
printPostOrder(node.left);
printPostOrder(node.right);
visitTreeNode(node);
}

private void visitTreeNode(TreeNode node){
System.out.print(node.nodeValue + " ");
}

public int getMinValue() {
return (getMinValue(root));
}

private int getMinValue(TreeNode node) {
while (node.left != null) {
node = node.left;
}
return (node.nodeValue);
}


public int getMaxValue() {
return (getMaxValue(root));
}

private int getMaxValue(TreeNode node) {
while (node.right != null) {
node = node.right;
}
return (node.nodeValue);
}

public int getMaxDepth() {
int depth = getMaxDepth(root);
return ((depth > 0) ? (depth - 1) : 0);
}

private int getMaxDepth(TreeNode node) {
if (node == null) {
return 0;
} else {
int leftDepth = getMaxDepth(node.left);
int rightDepth = getMaxDepth(node.right);
return (((leftDepth > rightDepth) ? leftDepth : rightDepth) + 1);
}
}

public boolean containsData(int data) {
return(containsData(root, data));
}

private boolean containsData(TreeNode node, int data) {
if (node == null) {
return false;
}
if (data == node.nodeValue) {
return true;
} else if (data < node.nodeValue) {
return(containsData(node.left, data));
} else {
return(containsData(node.right, data));
}
}

public int getRootValue(){
return root.nodeValue;
}

public boolean containsSumInPath(int total) {
return( containsSumInPath(root, total) );
}

private boolean containsSumInPath(TreeNode node, int total) {
if (node == null) {
return(total == 0);
} else {
int remainder = total - node.nodeValue;
if (containsSumInPath(node.left, remainder) || containsSumInPath(node.right, remainder)) {
addPaths( remainder, node.nodeValue, total);
}
return(containsSumInPath(node.left, remainder) || containsSumInPath(node.right, remainder));
}
}

private ArrayList path = new ArrayList();

private void addPaths(int remainder, int currentNodeValue, int total){
if (!path.contains(currentNodeValue)) {
path.add(currentNodeValue);
}
}

public ArrayList getSumOfPath(){
Collections.reverse(path);
return path;
}

public static void main(String[] args) {
BinaryTree bTree1 = new BinaryTree();
BinaryTree bTree2 = new BinaryTree();

bTree1.constructBinaryTreeHardCoded();
System.out.println("Size of the binary tree: " + bTree1.getSize());
System.out.println("Root value in the binary tree: " + bTree1.getRootValue());
System.out.println("Smallest value in the binary tree: " + bTree1.getMinValue());
System.out.println("Largest value in the binary tree: " + bTree1.getMaxValue());
System.out.println("Maximum depth of the binary tree: " + bTree1.getMaxDepth());
System.out.println("Contains node value 4: " + bTree1.containsData(4));
System.out.println("Path has sum of 30: " + bTree1.containsSumInPath(30) + " = " + bTree1.getSumOfPath());
bTree1.printTreeTraversal();

System.out.println();

bTree2.testHarness();
System.out.println("Size of the binary tree: " + bTree2.getSize());
System.out.println("Root value in the binary tree: " + bTree2.getRootValue());
System.out.println("Smallest value in the binary tree: " + bTree2.getMinValue());
System.out.println("Largest value in the binary tree: " + bTree2.getMaxValue());
System.out.println("Maximum depth of the binary tree: " + bTree2.getMaxDepth());
System.out.println("Contains node value 11: " + bTree2.containsData(11));

Random rand = new Random();
int find = rand.nextInt( 30 ) + 1;
System.out.println("Path has sum of "+ find +": " + bTree2.containsSumInPath(find) + " = " + bTree2.getSumOfPath());
bTree2.printTreeTraversal();

System.out.println("Are identical binary trees: " + bTree1.isIdenticalTree(bTree2));

System.out.println("\nChanged elements in binary tree");
bTree2.constructBinaryTreeHardCoded();
System.out.println("Are identical binary trees: " + bTree1.isIdenticalTree(bTree2));
}
}

Kanye West doesn't like this blog :P

This interesting picture is generated from http://kanyelicio.us
Simply append your desired URL after that domain to see the funny end result.
For example http://kanyelicio.us/http://nicholaskey.blogspot.com :P

Saturday, September 12, 2009

Scraping ISO 3166-1-alpha-2 country codes

I have written a simple XSL to scrape the ISO 2-letter country codes from the ISO website First I copied the table that contains the country names and codes and then I constructed the XSL. This is how the XSL looks like:UPDATE:
Please insert the breakline HTML element in the if block after the translate statement. Because without it, the country codes won't be displayed in separate lines. I have written another blog entry about scraping the codes. Please take a look here.

Friday, September 11, 2009

Grabbing Files from Remote Server

I have written a helpful method to grab files from remote server and save them into a local folder. This example works as follow:
[1] The input file will be read line by line
[2] The resource names will be appended to the URL of the remote server
[3] Resources that are found in the remote server will be written to the local folder
[4] Otherwise, show error messages if the resources are not foundHappy coding everyone :)

Tuesday, September 8, 2009

Replacing whitespace characters in a string

Here is an example of method overloading - same method name with different number of parameters. The complexity of this algorithm is O(n) because the input string is scanned character by character.

But what if there is a input with a massive size? I would want to partition out the string into several portion depending on the size threshold which can be set in the method and the hash the partitioned texts into a hashmap. Threading is possible in this context because the texts will be processed synchronously instead of sequentially.

public static StringBuffer removeSpace(String input){
return removeSpace(input, "%20");
}

public static StringBuffer removeSpace(String input, String fillerString){
StringBuffer sb = new StringBuffer();
int strLength = input.length();
int index = 0;
while(index != (strLength)){
if (input.charAt(index) != ' ') {
sb.append(input.charAt(index));
} else {
sb.append(fillerString);
}
index++;
}
return sb;
}
You may test this code with this sample method calls:

System.out.println(removeSpace("Hello World, I am Nicholas Key"));
System.out.println(removeSpace("Hello World, I am Nicholas Key", "[SPACE]"));

Usefulness of BigInteger

It's way much better than Integer, the primitive type; simply because we won't be restricted with arithmetic overflow issue. An example is in this method to compute factorial.

public static BigInteger factorial(int n){
BigInteger result = BigInteger.ONE;
for (int count = 1; count <= n; count++) {
result = result.multiply(BigInteger.valueOf(count));
}
return result;
}
The precision is still well maintained even if you iterate through the first 38 numbers. Give it a try if you are not convinced :)
UPDATE: there is a fundamental flaw in this loop. In the previous code, I demonstrated for (int count = 1; count < n; count++). It has changed to for (int count = 1; count <= n; count++)

Monday, September 7, 2009

Numbers with commas

Here's a simple method to include commas after every third digit from the right:

public class Utilities{
private static int startingPivot;
private static final int INDENT = 3;

public static StringBuffer decimalize(int input){
String conv = Integer.toString(input);
StringBuffer sb = new StringBuffer();

int commaIndex = conv.length() / INDENT ;
int strLength = conv.length();

startingPivot = (strLength) - (commaIndex * INDENT );
if (startingPivot == 0) {
startingPivot = INDENT ;
}

for (int index = 0; index < strLength; index++) {
if (index == startingPivot) {
sb.append(",");
startingPivot = startingPivot + INDENT;
}
sb.append(conv.charAt(index));
}
return sb;
}
}
You may try this code by making this method call

System.out.println(Utilities.decimalize(1234567890));
and the output is 1,234,567,890
NEAT :D

Sunday, September 6, 2009

String tokenizer by hand

I was thinking of implementing my custom "StringTokenizer" and here it is. The complexity is O(n) which means it depends on the size of the string.

public static ArrayList tokenizer(String input){
ArrayList tokenizedStr = new ArrayList();
StringBuffer str = new StringBuffer();
int strLength = input.length();
int index = 0;
while (index < strLength) {
char curr = input.charAt(index);
if (curr != ' '){
str.append(curr);
} else {
tokenizedStr.add(str);
str = new StringBuffer();
}
if ((index == strLength-1 ) && (curr != ' ')) {
tokenizedStr.add(str);
}
index++;
}
return tokenizedStr;
}
The most interesting part of this method if the condition to check if we have reached the last character of the string and to make sure if it is also not a whitespace character.

UPDATE:
On a second thought, the algorithm in this method is not perfect because it will still retain inline whitespace characters. This is a much better way to tokenize the strings

while (index < strLength) {
char curr = input.charAt(index);
if (curr != ' '){
str.append(curr);
} else {
if (str.length() != 0) {
tokenizedStr.add(str);
}
str = new StringBuffer();
}
if ((index == strLength-1 ) && (curr != ' ')) {
tokenizedStr.add(str);
}
index++;
}
An example of solving this in recursion is at "Tokenizing String Recursively".

Thursday, September 3, 2009

Screencast of my iPhone App

Tuesday, September 1, 2009

Fibonacci Sequence

Here's an interesting usage of "memoization". According to Wikipedia, "In computing, memoization is an optimization technique used primarily to speed up computer programs by having function calls avoid repeating the calculation of results for previously-processed inputs.".

There is actually a drawback if we are using plain and simple recursion to compute the Fibonacci sequence using long datatype (because we are only limited to hold the first 48 Fibonacci numbers). Memoization helps to speed up the computation time by saving already computed values into memory (and we can use BigInteger datatype). An example implementation is as below:

import java.math.BigInteger;
import java.util.ArrayList;

public class Fibonacci {

/** Variables for memoization **/
private static ArrayList fibMemoized = new ArrayList();
static {
fibMemoized.add(BigInteger.ZERO);
fibMemoized.add(BigInteger.ONE);
}

/** Memoized method to retrieve stored computed values **/
public static BigInteger fibonacci(int n) {
if (n >= fibMemoized.size()) {
fibMemoized.add(n, fibonacci(n-1).add(fibonacci(n-2)));
}
return fibMemoized.get(n);
}

/** Old school recursion **/
public static long fib(int n) {
if (n <= 1) return n;
else return fib(n-1) + fib(n-2);
}

/** Driver **/
public static void main(String[] args) {
int N = 45;
System.out.println(fibonacci(N));
System.out.println(fib(N));
}

}
You may try copying the codes and run it locally to observe the difference in performance. The typical recursive method runs slower because it computes the Fibonnaci numbers from scratch many times. Unlike the memoized method, the ArrayList is used to store the previously computed values. While memoized method is more superior in terms of speed, we are actually sacrificing space in order to achieve greater speed.