Friday, November 18, 2011

Find all possible ways of representing a number n

During one of my recent interview with a giant software company, I was asked this question:

Given an array of numbers, find all possible ways of representing a number n. For example, let's assume we have [2, 3, 5] in an array, and the target number is 10.
Well... I fail this interview in that I'm trying to work out a iterative solution given the stressful condition. I went home and I suddenly realize this is a manageable problem as long as I'm not greedy.



  • Tip 1: for all "combination" / "subset" questions, you should always start with hacking a recursive solution, because it's the most intuitive one. 
  • Tip 2: never try to provide the "best" answer to your interviewer. Don't worry, they will challenge you and ask you to propose a better answer later. 
Some people might argue that tip 2 looks stupid, especially if you know that recursive is usually awful in terms of space complexity. Don't get me wrong here, the time complexity for a permutation style question is O(N!), factorial, and for a subset style question is O(2^N), exponential. But hey...this is not the side effect of recursive, but it is the nature that the space you have to search !! Yes, the space complexity is awful, and you may fix by Dynamic Programming or Iterative solution. However, what you need in the interview is not a perfect answer, but is to show you ability of coding, and analyzing complexity. And don't worry, if you get this simple answer quickly, they will ask you to improve it. That's the time for "iterative" solution.



Here is the simple way of doing it:
import java.util.ArrayList;
import java.util.Arrays;

public class FindAllComb {
    public static void main(String[] args) {
        int[] ar = {3,5, 2};
        printCombForN(ar,10,0, new ArrayList());
    }


    //try = 0, meaning we start from the first element in the array
    public static boolean printCombForN(int[] ar, int target, int idx, ArrayList buffer){
        //base case: if no more choice
        if(target == 0) {
            return true;
        }
        else if (target < 0) {
            return false;
        }

        // for all possible choice
        for(int i=idx; i < ar.length; i++){
            //make a choice
            buffer.add(ar[i]);
            target-=ar[i];
            if (printCombForN(ar, target, i, buffer)){
                //print buffer
                System.out.println(Arrays.toString(buffer.toArray()));
            }
            //unmake the choice
            buffer.remove(buffer.size() -1);
            target += ar[i];
        }
        return false;
    }
}
It may looks hard at its first glance but essentially this is a simple back-tracking problem. For back-tracking problem, here is the template I follow:
bool Solve(configuration conf) //Credit: Zelenski, Julie
{
    if (no more choices) // BASE CASE
        return (conf is goal state);

    for (all available choices) {
        try one choice c;
        // solve from here, if works out, you're done
        if (Solve(conf with choice c made)) return true;
        unmake choice c;
    }
    return false; //tried all choices, no soln found
}

Can we do better?

Yes, with the help of DP.
The idea is that we can "memorize" things we did before.


For example, if we know th only possible choice of making 5 are (2,3) or (5), we can simple save it in a HashMap so that we don't have to go over same path again.

So let's slightly change the problem, what if we don't need you to print all possible combination, but we just want you to return number of possible combinations?

The idea here is Num(array, 10) = the sum of the following
  1. Num(array, 8)  + 1 (we deal with 2)
  2. Num(array, 7)  + 1 (we deal with 3)
  3. Num(array, 5)  + 1 (we deal with 5)
So you get the big picture now, if we have an array that index is the "target", which is the remainder after we recursively call the function , and the value is the "# of possible combinations" we already know. We can simple sum them up.

I will add answer later, but one thing you should keep in mind is that to make things faster, often times the price is space. In this example, we need extra space for tracking counts. Though, here (the revised question) the cost is acceptable.


Note that all back-tracking problem can be accelerated by some heuristic pruning. That is, you may "return false" earlier if you know there's no way you can get a goal state along the path.

Wednesday, August 17, 2011

Log (logging) in Python

Logging is always an important topic when you try to develop a "real-world" app. I once wrote my own logging system, but apparently the best practice is to use something provided by Python Standard Library, not to reinvent the wheel.

Here, I have no intent to write a complete tutorial of teaching the python's logging framework. I extract the most useful/simple part(s) of logging from my viewpoints, which I believe it solves 90% cases I(you) need.


Firstly, you should try to build a customized logger. It is impractical to use the logging module directly via changing basicConfig() because you cannot tell where the log comes from if you have multiple modules in your app. This is one of the reason why I write this article.

To get a "customized" logger, firstly you should assign a name to it.
mlogging = logging.getLogger("test_log") #Get a logging for this module

If you would like to have some beautiful format on logging records, logging.Formatter is something you need to set it up. Sure you should do it because the default one seems to be a little clumsy. To change the date format (that is, %(asctime)s), please refer to things used in time.strftime(). And to create a format for a record, the related variables can be found in attributes of LogRecord.

# -- Set up Formatter --
log_format = '%(asctime)s(%(name)s--%(levelname)s):%(message)s'
log_date_format = '[%m/%d/%y %H:%M:%S]'
uniform_fmt = logging.Formatter(fmt=log_format, datefmt=log_date_format)

Mostly, we store logs in a file, so you need a file handler.
# -- Log to File --
hdlr = logging.FileHandler('OnlyOneFile.log')   # or "mlogger.name + 'log' if you would like to separate logs
hdlr.setFormatter(uniform_fmt)

If you would like to see log in your screen, say, for debugging, you have to link it to STDOUT.
# -- Log to Console --
hdlrConsole = logging.StreamHandler(sys.__stdout__)
hdlrConsole.setFormatter(uniform_fmt)

Do not forget to link your handler with your logger.
mlogging.addHandler(hdlr)
mlogging.addHandler(hdlrConsole)

Finally, you have to assign a log level so that you can get all the details. Otherwise, The default level is WARNING. (All default levels)
mlogging.setLevel(logging.DEBUG) #this is the most detailed level

Putting all together, here is an example:
import sys
import logging

mlogging = logging.getLogger("test_log") #Get a logging for this module
"""
logging.basicConfig(
    #filename=mlogging.name + '.log', #Use the name of logger as log file name
    filename='onefile.log', #Use the name of logger as log file name
    level=logging.DEBUG,
    format='%(asctime)s(%(name)s--%(levelname)s):%(message)s',
    datefmt='[%m/%d/%y %H:%M:%S]'
"""

# -- Set up Formatter --
log_format = '%(asctime)s(%(name)s--%(levelname)s):%(message)s'
log_date_format = '[%m/%d/%y %H:%M:%S]'
uniform_fmt = logging.Formatter(fmt=log_format, datefmt=log_date_format)

# -- Log to File --
hdlr = logging.FileHandler('OnlyOneFile.log')
hdlr.setFormatter(uniform_fmt)

# -- Log to Console --
hdlrConsole = logging.StreamHandler(sys.__stdout__)
hdlrConsole.setFormatter(uniform_fmt)

mlogging.addHandler(hdlr)
mlogging.addHandler(hdlrConsole)
mlogging.setLevel(logging.DEBUG)

mlogging.debug('This is debug msg')
mlogging.info('Ok~ info now')
mlogging.warning('Warning here')

try:
    x = 4/0
except Exception as e:
    mlogging.exception(e)

Before we leave the discussion, you should pay attention to mlogging.exception(e). This is the way we log an exception, including its trace-back information.

Tuesday, July 12, 2011

Git Version Control Resource

I'm a heavily Subversion (SVN) developer. Recently, I join several projects that use git as their version control frameworks. Thus, I document some useful resource as follows:


To learn more about git:

Firefox 5 on ubuntu 10.04 LTS

For people who are using ubuntu 10.04, the default version of Firefox is 3.6. (Seriously?) It's suggested that you update to the latest stable version of ubuntu.

To install the latest "stable" version of ubuntu, add the following ppa repository:

sudo add-apt-repository ppa:mozillateam/firefox-stable


This is nothing more than add a mozillateam-firefox-stable-lucid.list to "/etc/apt/sources.list.d".

Than, do "sudo apt-get update && sudo apt-get upgrade" and you are done.

Tuesday, March 8, 2011

MySQL Remote Access

By default, the mysql (5.x) allows login within localhost. What if you need to access a MySQL database from another computer?

I found this tutorial is quite helpful:
how-do-i-enable-remote-access-to-mysql-database-server

Unfortunately, I still get the following errors
chucheng@laptop:~$ mysql -ufoo -pcrap mysql.ucla.edu
ERROR 1044 (42000): Access denied for user 'foo'@'laptop' to...

After trying several solution, I finally realized that in the statement GRANT ALL ON db_name.* TO foo@'%' IDENTIFIED BY 'PASSWORD'; you cannot skip "IDENTIFIED BY password".

It turns out that you will "override" existing passwords with an empty password if you did not provide corresponding inputs.

Just in case that you still have problems:
Please make sure that
(1) Your bind-address in /etc/mysql/my.cnf has been changed to "real" IP.
(2) your port is listening
netstat -an | grep 3306
(3) You grant remote access permission to the user accounts.
p.s if you encounter any problems when login from localhost, instead of granting foo@'%', please grant foo@'localhost' as well.

Friday, February 4, 2011

Ubuntu Application

I would like to document several apps that, I believe, are very useful as follows. Though there are many choices in WWW. The followings are really handy ones.

Programming Tools:
  • WingIDE (Python)
  • IntelliJ IDEA (Java)
  • Eclipse (C++/Java)
  • Rabbit VCS (Version Control)

MISC:
  • Mendeley
  • Stardict (Dictionary)

Tuesday, February 1, 2011

Brightness Control on T410 (T410s)

I find the brightness control seems to be not working after installing ubuntu 10.04 on my Thinkpad T410s.

Here are two solutions:

(1) Switch to console (CTRL+ALT+F2) and adjust the brightness. Then switch back to GNOME (CTRL+ALT+F7)

(2) Edit /etc/X11/xorg.conf
Under the "DEVICE" section, add the following OPTION
Option "RegistryDwords" "EnableBrightnessControl=1"


Done! Enjoy it!

Tuesday, January 25, 2011

Install Sun Java SDK 6 on Ubutnu 10.04

Since Ubuntu 10.04, Sun(Oracle?) SDK is not existed in multiverse anymore.

If you would like to install Sun Java SDK, you have to use "partner" repository.


sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
sudo apt-get update
sudo apt-get install sun-java6-jdk


Is that all? Not quitely.

Choosing the default Java to use



Just installing new Java flavours does not change the default Java pointed to by /usr/bin/java. You must explicitly set this:


* Open a Terminal window
* Run sudo update-java-alternatives -l to see the current configuration and possibilities.
* Run sudo update-java-alternatives -s XXXX to set the XXX java version as default. For Sun Java 6 this would be sudo update-java-alternatives -s java-6-sun
* Run java -version to ensure that the correct version is being called.

You can also use the following command to interactively make the change;

* Open a Terminal window
* Run sudo update-alternatives --config java
* Follow the onscreen prompt

Ref: https://help.ubuntu.com/community/Java

Wednesday, December 1, 2010

Windows 7 HotKey in Ubuntu

As a bi-OS user, I am always confused with the hot-key setting while I switch between Operating System. No offense, while I said bi-OS user, I refer to Windows 7 and Ubuntu Lucid. (Not Mac OS).

Some hotkeys introduced in Windows 7 are very userful for myself. For example, Windows + Left / Right / Up / Down

If you never try above hotkeys, try it on a Windows O/S, and you will know what would happen.
Long story short, I would like to resize my windows the the left/right window. What should I do?

(1) You have to install wmctrl package
 sudo apt-get install wmctrl


(2) Open "System"-->"Preference"-->"Keyboard Shortcuts".
Bound Windows + Left to ==> wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz;wmctrl -r :ACTIVE: -e 0,0,20,1920,1150
Bound Windows + Right to ==> wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz;wmctrl -r :ACTIVE: -e 0,960,20,960,1150

To Maximize a windows:
Bound Windows + Up to ==> wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz;wmctrl -r :ACTIVE: -e 0,0,20,1925,1150


Would you like to learn more?
Read here: wmctrl tutorial

Tuesday, November 23, 2010

Where is my "Ctrl + Alt + Backspace" ?

After installing ubuntu 10.04, I quickly realized that CRTL-ALT-F1 (for opening a terminal) and CRTL-ALT-BACKSPACE (for killing X-server) are gone. Luckily, here is the solution I found:

Enabling Ctrl-Alt-Backspace for Ubuntu 10.04

  1. Select “System”->”Preferences”->”Keyboard”
  2. Select the “Layouts” tab and click on the “Layout Options” button.
  3. Select “Key sequence to kill the X server” and enable “Control + Alt + Backspace”
Enjoy your hot keys :)

Thursday, October 14, 2010

Move window buttons (Min, Max, Close) back to right in ubuntu 10.04

One of the most controversial change in ubuntu 10.04 is to have window buttons on the left side. Although this change favors many mac(apple) users. As a user worked in dual O/S, windows 7 and ubuntu, the change is somehow inconvenient. Here I explain how to move them back. (The min, max, and close button)

1. Open the configuration editor of gnome.
gconf-editor


2. Click on the + button next to the “apps” folder, then click “metacity” in the list of folders expanded for apps, and then click on the “general” category. The button layout can be now changed by editing the “button_layout” key.

3. Change it to:
menu:minimize,maximize,close


Save, close, and you are done. (Restart X Window to take effect)

Tuesday, August 24, 2010

Weired ssh-agent error in Ubuntu

To protect your private key, one might add a long pass-phrase for avoiding the burglary. However, somehow I see the following error while trying to add my private key to ssh-agent.
chucheng@ubuntuVM:~$ ssh-add
Could not open a connection to your authentication agent.

Here is the solution:
exec ssh-agent bash

Don't know why, but it just works :)

Results:
chucheng@ubuntuVM:~$ ssh-add
Enter passphrase for /home/chucheng/.ssh/id_rsa:
Identity added: /home/chucheng/.ssh/id_rsa (/home/chucheng/.ssh/id_rsa)

Tuesday, July 6, 2010

Rename mutliple files at once in ubuntu / linux

I would like to rename multiple files at once in my Ubuntu 10.04.
I google around and I found people suggest the following command:
rename .bak .new *.bak

However, this magic does not work in my Ubuntu.
To rename a batch of files with their extension, the following syntax works:

rename 's/\.bak$/\.csv/' *.bak

The above command would rename all files with the extension ".bak" to the new extension ".csv".

Tuesday, June 22, 2010

Ubuntu 10.04 hang after login

For some unknown reason(s), my newly install Ubuntu 10.04 went panic last Friday. Simply put, the ubuntu 10.04 hang after entering login information. I spend lost of hours on finding the problem. However, I still cannot see why it happens. It turns out that some package contains bugs and cause the o/s crashed after login.

I have tried the following means and none of them works:
- sudo apt-get install --reinstall ubuntu-desktop
- Update every package installed in the system
- Use the default xorg.conf setting (Without Xinerma)
- ... rm -rf home directory ...

Anyway, after keep trial and errors, here explains how I solve the problem.

1. Reboot to Recovery Model
It's a little tricky in Ubuntu 10.04 because by default the grub2 won't show up a start menu for you. The "default" in Ubuntu 10.04 always try to select the default booting item after power on the system. In addition, there's no more /boot/grub/menu.lst in ubuntu 10.04.

Here are solutions:
(1) Comment out "#GRUB_HIDDEN_TIMEOUT=0" through editing /etc/default/grub
(2) Run update-grub (or update-grub2 ?)
(3) Reboot and you will see the grub menu. Select the recovery mode and you are done.

2. Installed the following two package
sudo aptitude install libpam-gnome-keyring=2.92.92.is.2.30.0-0ubuntu3
sudo aptitude install gnome-keyring=2.92.92.is.2.30.0-0ubuntu3


If it works for you as well, please simply leave a comment here :)

Wednesday, November 18, 2009

Upgrade Debian 3.1(sarge) to 4.0(etch)

It look like that to upgrade from Debian 3.1 to 4.0 should be fairly easy; however, the truth is that you will somehow trap by "libc6" loop. Here is a note to solve the problem.


  1. Update 3.1 as best as possible. Modified the /etc/apt/sources.list
    #OldStable
    #deb http://security.debian.org/ lenny/updates main contrib non-free
    #deb http://ftp.us.debian.org/debian/ oldstable main contrib non-free

    sudo apt-get update

    sudo apt-get upgrade

  2. Switch to the etch sources, and update the kernel.
    #etch
    deb http://security.debian.org/ etch/updates main contrib non-free
    deb http://ftp.us.debian.org/debian/ etch main contrib non-free

    sudo apt-get update

    sudo apt-get install linux-image-2.6.18-6-686

  3. Pre-Processing
    apt-get install locales

    Make sure we handle all the dependency issue:
    apt-get install -f

  4. Install the kernel.

    sudo apt-get install linux-image...

  5. Update Grub by running: update-grub

    Edit /boot/grub/menu.lst, set the Default to correct kernel

  6. Edit the tow links to the right kernel:
    /boot/initrd.img initrd.img -> initrd.img-2.6.8-3-686-smp
    /boot/vmlinuz -> vmlinuz-2.6.8-3-686-smp
    , and then Reboot


Tuesday, November 10, 2009

Install Postfix on Ubuntu

A step by step instruction to install a postfix server on ubuntu 8.10:

  1. Install package.
    sudo apt-get install postfix

    1. type of mail configuration: Internet Site

    2. enter your domain name: e.g. not.exist.edu (You have to register a domain name first) Free Register



  2. Install mail utilities if you want to send a email through command line.
    sudo apt-get install mailutils

  3. Write a testing email.
    echo testing_message | mail -s Subject_Not_Important youremail@some.domain.name
    You should get your email in a second. If not, check your SPAM filter/box.

  4. By default, the log files locate at /var/log
    ls -l /var/log | grep mail
    Check log files if you encounter any errors.

Monday, November 9, 2009

How to move mysql datadir to new location

By default the mysql install the datadir at /var/lib/mysql. Unfortunately, people usually did partition their hard disk, or buy a new hard drive later. In such a case, you would like to move the *huge* datadir to another disk to both boost the speed by parallel in I/O and utilize space smartly. Here's what you should do:


  1. Stop your mysql service.
    sudo /etc/init.d/mysql stop

  2. Copying all files from old location to new location and preserver the ownership and timestamp information.
    sudo cp -r -p /var/lib/mysql /newlocation/

  3. Update your mysql configuration file:
    sudo vim /etc/mysql/my.cnf
    datadir     = /newlocation/mysql #old: /var/lib/mysql

  4. Update the second configuration file for apparmor:
      /newlocation/mysql/ r, #/var/lib/mysql/ r,
    /newlocation/mysql/** rwk, #/var/lib/mysql/** rwk,

  5. (Optional) Rename the old folder to prevent confusing.
    sudo mv /var/lib/mysql /var/lib/mysql.bak

  6. Restart your apparmor & mysql service.
    sudo /etc/init.d/apparmor reload
    sudo /etc/init.d/mysql start

  7. Delete the old location
    sudo rm -rf /var/lib/mysql.bak


Tuesday, September 29, 2009

Recursively download entire website from a ftp

The easiest way is the following command:
wget -r ftp://user:password @domain.name here



The only problem is that this method doesn't support "resume" function :)

Friday, September 25, 2009

Intall Python 3 on Ubuntu

0. Install related packages:
sudo apt-get install build-essential libncursesw5-dev libreadline5-dev libssl-dev libgdbm-dev libbz2-dev libc6-dev libsqlite3-dev tk-dev g++ gcc

1. Download the file to /tmp:
cd /tmp
wget http://www.python.org/ftp/python/3.1.1/Python-3.1.1.tgz

2. Unzip the tar zip file:
tar xzvf Python-3.1.1.tgz

3. Run configuration command ./configure
* In case you encounter some problem, install build-essential

4. make (optional)

5. Install the program to system:
sudo make install

Monday, August 17, 2009

Appending to Your Python Path


Question:

How do you append directories to your Python path?

Answer:

Your path (i.e. the list of directories Python goes through to search for modules and files) is stored in the path attribute of the sys module. Since path is a list, you can use the append method to add new directories to the path.

For instance, to add the directory /home/me/mypy to the path, just do:
    import sys
sys.path.append("/home/me/mypy")


src: Here