Naboo

Thursday, April 21, 2011

Java Pitfall: pass by value? by reference?
I ran into this pitfall trying to print out all valid combinations of n pair of parenthesis. The recursive code I wrote was pretty straightforward:

public static void recurPrint(int l, int r, String str) {
    if (l==0 && r==0) {
        System.out.println(str);
     }
    else {
        if(l>0) {
            str+='(';
             recurPrint(l-1, r, str);
         }
        if (r>0) {
            str+=')';
            recurPrint(l, r-1, str);
        }
    }
}

public static void main(String[] args) {
   recurPrint(2,2,"");
}

However, instead of giving me "()(), (())", it keeps giving me "(()), (()()". l and r seems to behave just the way I want during recursion, so it's gotta be the only other parameter that's screwing up the recursion: str. It indeed is.

Correct code:
public static void recurPrint(int l, int r, String str) {
    if (l==0 && r==0) {
        System.out.println(str);

     }
    else {
        if(l>0) {
            str+='(';
             recurPrint(l-1, r, str str+'(');
         }
        if (r>0) {
            str+=')';
            recurPrint(l, r-1, str str+')');
        }
    }
}

Make the code work is easy. Understand what's happening here takes a little more effort.
Back to Java 101:
All strings are instances of String class. Java pass by value for primitive types and reference for objects.

The incorrect "(()()" is caused by Java passing by reference, while str still possess the "((" value from last recursion. My brain tends to go nuts trying to imagine full recursion cycles, and using reference during recursion is only gonna make it worse. Therefore, always try pass by value for recursion.

BTW: Strings are constants. All strings are initialized at create time and can't be changed afterwards. When we do str += ')', what's happening behind the scene is:
  • a string buffer is created.
  • content of str is copied to string buffer
  • string buffer is appended with ')'
  • new memory chunk is allocated and copied with content of string buffer
  • str is assigned with the new memory chunk reference.
So if you have a loop that's doing this += a lot, try create a StringBuffer outside the loop and do these += with the StringBuffer inside the loop. It'll save you a lot of object creation and destruction.

Wednesday, April 20, 2011

A Different Thinking Process for "Count the number of two's from 1 to n"

Careercup-150 solves this problem by this approach:
Pattern: 0-10: 1 2s; 0-100: 20 2s; 0-1000: 300 2s; between 0 and 10^n, there are n*(10^n-1) 2s. Let f(n)=n*(10^n-1), we have: between 0 and x*10^n, number of 2s becomes:
  • x>2  -- x*f(n) + 10^(n-1)
  • x=2  -- x*f(n) + 1
  • x<2 -- f(n-1)
For 2145, we have to consider these 4 intervals: 1-2000, 2000-2099, 2100-2139, 2140-2145. Pattern solves counting in intervals starting from 0 or 1, I am too dumb to see how this split is going to use the pattern. Surprisingly, code in the book seems to be exactly same as mine, which indicates that my thinking process should be correct. Hence the elaboration below:

Think of the problem as your car pedometer, the numbers roll up, over and push the next column. Patter: every 10 miles, the digit for 2 rolls once; Every 100 miles, the 10's digit rolls 2 10 times; Every 1000, the 3rd digit rolls 2 100 times. Take the number 2145, starting from 5 as p0 slot, we have p3p2p1p0 four slots. Number of 2's occurred for each slot would be:
  • p0: (214+1)*1   //pedometer slot 0 was rolled from 0-9 214 times, plus 1 to reach 5
  • p1: (21+1)*10  //pedometer slot 1 was in 2 position for 22 times, which includes rolling 0-9 for 21 times, and 1 time before it reaches 4
  • p2: 2*100        //pedometer slot 2 was rolled from 0-9 2 times, i.e., 200-299, and 1200-1299.
  • p3: 146            //bcoz p3=2 and p3 is the highest slot, this slot has stayed at 2 from 2000 for 146 times.
In a nutshell: First look at left slot to calculate how many "full roll" current has gone through, multiple it by 10^(slotPosition-1). Then, depending on whether current slot is <2, 2 or >2, do corresponding calculation.

Code(shorter than Careercup hooray!)
public static int CountTow(int n) {       
        int sum = 0;
        int temp = n;
        int base = 1;
        while(temp>10) {           
            sum += base * temp/10 + (temp%10>1? 1:0);
            temp = temp/10;
            base*=10;
        }
        if (temp==2) {
            sum += (n-2*base+1);
        }else if(temp >2) {
            sum += base;
        }
        return sum;
    }

Unitest
CountTow(-1)   - 0
CountTow(0)    - 0
CountTow(1)    - 0
CountTow(2)    - 1
CountTow(12)  - 2
CountTow(20)  - 3
CountTow(29)  - 13
CountTow(100) -20
CountTow(1000)  -300
CountTow(2145)   -786

Thursday, April 07, 2011

Checklist for Commodity Java Programmer

Commodity Java programmer is in general a sad thing to be. However, same as the fact that good anything is hard to find, a full blown Java programmer with all the right armor is scarce too. At a time hiring is finally heating up again, be, or at least appear to be a good Java programmer will come in handy. Hence the checklist.

First of all, think about what companies hire Java programmers for.
Hardcore infrastructure ground zero? Rarely. They should already been built for most cases unless it's a pre-startup bunch of people with just an idea and at most seed money.
Data processing for specific areas like video, cognitive, mechanics, games etc? Rarely. Those are C family dominated areas with heavy stress on embedded possibilities.
Java programmers are pretty much left with the highly abstract, application level development, the most common among e-commerce, web services and (high-level) automation tools. Basically business logic heavy performance sensitive scalability essentially relatively not-sexy but revenue visible part of the software.

With this in mind, here comes the skill-set checklist:
  • Algorithm - pre-requisite for any decent programmer. 
  • Patterns - these are the building blocks. Should be able to slam out code for most of them.
  • SQL - complicated queries, performance, stored procedure, schema design.
  • Ajax - a deep understanding of what happens behind the scene gains you insight into all platforms.
  • I18n & l10n - get yourself familiar with unicode, utf-8
  • Cloud & cluster - distributed systems, ways they talk, and key elements in each of the communication categories.
  • Security - encryption, protocol, standard and elevated practices for identity control of web apps
  • VM, garbage collection, strong/weak reference, lazy loading, aka the Java specifics in and out.
  • Testing - code coverage, path coverage, security test, stress test, regression. Spend 2h familiarize yourself with the concepts.
  • Your resume - any question on your resume is fair question. Try to remember your projects.
With the right amount of domain knowledge, one with decent insight into all the above areas would make a very strong candidate. If he/she knows scripting, then it's a must-hire, and it's a sweet spot for a commodity Java programmer to be =)

Wednesday, January 14, 2009

(C#)Serialize image file into string

To convert an image file to Base64 string, use the code below. It's also easy to modify it to return in other string formats.

Image im = Image.FromFile(imagePath);
MemoryStream ms = new MemoryStream();
im.Save(ms, im.RawFormat);
byte[] array = ms.ToArray();
string result = Convert.ToBase64String(array);




Monday, October 20, 2008

How to debug spring mvc application with tomcat?
I found myself lost when I needed to debug into the simplest web service client code, which is behind Spring mvc. I have a web app up and running. Instead of the old-school way of finding glitches by gazing at it, e.g., a typo in buildproperties, or unmatching bean names between controller and viewer, we want to debug it. How to debug into your controller or deeper code?
I don't recommend turning on remote debugging from eclipse. It was a pain and never worked. What worked was adding a target to build.xml and tomcat-start-debug from build.xml dir. Detail look at

http://ptrthomas.wordpress.com/2006/03/25/how-to-start-and-stop-tomcat-from-ant/

Thursday, December 14, 2006

Thread Safe Hashtable (C#)
There are not a lot articles around about Hashtable thread safety, oh maybe yes, but blame google.

Between thread-safe and thread-unsafe, there is something called "conditional thread-safe", which means each individual operation may be thread-safe, but certain sequences of operations may require external synchronization. The most common example of conditional thread safety is traversing an iterator returned from Hashtable or Vector(Java), or Collection(C#).
Example:

List stringList = new List();
stringList.Add("a");//pretty much synchronized
foreach(string s in stringList)
{
Console.WriteLine(s); //not safe. Add is allowed to happen within the foreach loop
}


Thus, if you do need loop the collection a lot while Add and Remove are also called frequently, you will get a lot "InvalidOperationException: Collection was modified, enumeration not allowed". The way to solve this will be to 2 steps:

  1. Wrap the collection with another class implement thread-safety for it.
  2. Whenever enumeration is needed, lock.
Example:
Step 1:
public class ThreadSafeDictionary : Dictionary
{
private object _syncRoot = new object();
public object SyncRoot()
{ return _syncRoot; }
public void SyncAdd(KeyFacetTuple key, ISet value)
{

lock(_syncRoot) { Add(key, value); }
}
public void SyncRemove(KeyFacetTuple key)
{
lock (_syncRoot) { Remove(key); }
}
public void SyncBatchRemove(ICollection removes)//To avoid too frequent locking/unlocking
{
lock (_syncRoot) {

foreach (string key in removes) { Remove(key); }
}
} }

Step 2:
put lock(threadSafeDictionary.SyncRoot) around any "foreach KeyValuePair" for this class

lock(threadSafeDictionary.SyncRoot)
{
foreach(KeyValuePair pair in threadSafeDictionary)
{
//do stuff
}
}

Of course, this implementation only ensures the foreach loop won't encounter embarrasing moments, remember the elements in the threadSafeDictionary could be non-primitive data types and they are not locked. E.g. it can be an dicationary, then you must be careful about what you want to do with ArrayList and ISet too.

Another way for thinking about this whole problem is, can we implement a data structure so that it keeps track of the Enumerators. If there is any Enumerators alive, no Add/Remove can be executed. Whether this thought is worthwhile depends on performance: using SyncRoot VS. tracking Enumerators, which one consumes less resource?

I am also planning to write up an interface for thread-safe data structure built on conditional-thread-safe data structure. Will update this entry when I am done.

Thursday, April 20, 2006

How to Deploy Project from Dev Machine to UT Machine
This article is written for TGP lobbyist and campaign consulting project, which developes on EBB, and deployes to WEBTOP.

1. On EBB, check in solution in VS.NET
2. From BAY, on which dev database is running, duplicate database to Webtop(refer to previous article)
3. On Webtop, open VS.NET, create a new project with exactly same name as the project to be deployed. If it says 404 error on not being able to locate source on xxxx/Techonrati/xxxxx folder, select the option of creating folder on different location, and delete the Technorati in the path.
4. After creating new project, go to File->Source Control->Change Source Control, connect to VSS on BAY and bind.
5. Browse to the new project on VSS, open from there. It will warn you there is conflict. Say ok to everything.
6. Do a "Get latest(recursive)", till you see all good files loaded from VSS.
7. Exclude Web.config from VSS.