How to minify Angular JS ? Angular Minification

It’s very common to minify a JS file. However when it comes to an Angular file, it might become a different story.

No matter if you are using a website compressor or you are using a YUI compressor. If you directly compress a angular js file, you might get an error about :$injector stuff in the browser console.

The main reason for this is that the compressor changes the arguments name of a function in the minified version of JS file, but this makes Angular confused.

You could follow the official doc about minification. However, if you are using angular in a more complicated way, the better solution might use a two-step to compress. (Better here I really means is safer).

In my case, I am also setting $interpolateProvider for the app. So the official doc seems only to tell me about $scope but not $interpolateProvider one.

Step One:

Install ngmin.  This could be done by 

npm install -g ngmin

If you have npm installed.

Then run

ngmin somefile.js somefile.annotate.js

This basically generates a minify safe version of angular file. Say you have somefile.js which is an angular JS file. Then after running this, somefile.annotate.js is a minify safe JS file. 

Step Two:

Use whatever you use to minify JS file to minify somefile.annotate.js you just got from Step One. Then the new minified angular JS file would work. 

How to customize error page in google app engine

Google app engine has its default error page for web error like 404, 500.

But it’s usually nice to have our own styling error page.

In app.yaml file


# here is specifying custom error page for all error

- file: templates/errorpages/error.html

# here is specifying custom error page for a certain kind of error

- error_code: over_quota

 file: templates/errorpages/error404.html

You can specify that for different error, load different pages.

If not, you can say, okay loading same custom error page for all kind of error.

Make sure the path for the error page does not match any of the handlers you specify.

How to remove mysql completely from a Mac

I was having this problem because I installed a wrong version of mysql.

So I have to remove previous version.

I got this steps online and it works for me.

First of all, remember to stop the mysql server.

You can stop the server by System Preferences -> MySQL, Stop MySQL Server

1 Sudo edit file  /etc/hostconfig

Remove line MYSQLCOM=-YES-

Actually I don’t have this line in the file

2 Open up terminal and run the following commands

sudo rm /usr/local/mysql
sudo rm -rf /usr/local/mysql*
sudo rm -rf /Library/StartupItems/MySQLCOM
sudo rm -rf /Library/PreferencePanes/MySQL*
sudo rm -rf /Library/Receipts/mysql*
sudo rm -rf /Library/Receipts/MySQL*
sudo rm /etc/my.conf

For some of the files I still don’t have in my Mac. Maybe because I did not have a full installation of mysql before.

Shortcuts tips for Using Terminal In Mac

Once you have been a programmer for a while, you will find how powerful a terminal is.

Here is some shortcuts tips for using terminal.

Command + N  open a new terminal. (Remember to specify open by current working directory in the settings if you want to do so)

Command + T  open a new tab.

Command + {} switching between different terminal.

Control + A   move the cursor to the head of line

Control + E   move the cursor to the tail of line

LeetCode: Palindrome Partitioning II


Given a string s, partition s such that every substring of the partition is a palindrome.

Return the minimum cuts needed for a palindrome partitioning of s.

For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.


Since we have solved the first Palindrome Partitioning problem, this problem seems much easier for us.

By computing a two-dimension array isPa[][], we could know if any substring in given string s is a palindrome.

Now in this problem, instead of computing all possible solutions, we need to know which cut is best.

A similar way is used in this problem.  Define m[i] the minimum cut for substring s[i][s.length-1].

Initialize this array with the upper bound for each entry. Say for m[0], the uppder bound would be s.length-1.

For a substring s[i][j] of string s, we have a k from i to j. We check if s[i][k] is a palindrome. If not we continue to check the next k.

If yes, we comapre m[i] with m[k] + 1, and choose the less one to be new m[i].

After running all possible k, we will know the right answer of m[i].

So running i from s.length -1 to 0, we will find the answer of this problem in m[0].


public class Solution {
 public int minCut(String s) {
 // Start typing your Java solution below
 // DO NOT write main() function
 boolean[][] isPa = new boolean[s.length()][s.length()];
 int[] minCuts = new int[s.length()];
 calculateIsPa(s, isPa);
 calculateminCuts(s,minCuts, isPa);
 return minCuts[0];

//init minCuts with upper bound
 public void initminCuts(int[] minCuts, int size){
 for (int i = 0; i < size; i++){
 minCuts[i] = size - i - 1;

public void calculateminCuts(String s, int[] minCuts, boolean[][] isPa){
 for (int i = s.length() -1; i >=0; i --){
 for (int j = i; j < s.length(); j++){
 if (isPa[i][j]){
 if (j < s.length() - 1){
 //if substring [i][s.length] itself is a palindrome then the minCuts[i] should be 0
 minCuts[i]= 0;

 public void calculateIsPa(String s, boolean[][] isPa){
 for (int l = 0 ; l < s.length(); l ++){
 for (int i = 0; i < s.length() - l; i ++){
 if (i == i + l){
 isPa[i][i+l] = true;
 else if (i == i + l -1){
 isPa[i][i+l] = (s.charAt(i) == s.charAt(i+l));
 isPa[i][i+l] = (s.charAt(i) == s.charAt(i+l)) && isPa[i+1][i+l-1];

LeetCode : Palindrome Partitioning


Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

For example, given s = "aab",





What is a Palindrome? A palindrome is like a string “aba” where it’s the same no matter if you read from left to right or right to left.

This problem has a optimal structure. If we cut a string s into s1 and s2. Now we need to find out a palindrome partitioning both for s1 and s2. These are new subproblems.

The first idea would be divide and conquer. However, we need to check all the partitioning which means that we cannot simply cut at a point in the string and divide the problem.

So dynamic programming might be a good try.

The idea is like the Rod Cut Problem in book <Introduction to Algorithm>. Suppose string s has length n. We have i from 1 to n, check if substring 0 to i in string s is a palindrome. If not we don’t need to do more, if yes we add this substring into the solution space of partitioning problem for substring i+1 to n. After checking all the possible position, we will get the answer.

One more thing is that we need to quickly check if a certain substring in string s is a palindrome. In order to do so, we build a auxiliary array isPa to keep in mind if that certain substring is palindrome. To calculate this array, we do another dynamic programming.


public class Solution{
 public ArrayList<ArrayList<String>> partition(String s) {
 // Start typing your Java solution below
 // DO NOT write main() function</p>
 boolean[][] isPa = new boolean[s.length()][s.length()];
 //isPa[i][j] means if substring i to j in s is a Palindrome
 calculateIsPa(s, isPa);
 //calculate the boolean array isPa
 return findPa(s, 0, isPa);
 //return the result
 public ArrayList<ArrayList<String>> findPa(String s, int start, boolean[][] isPa){
 ArrayList<ArrayList<String>> pa = new ArrayList<ArrayList<String>>();
 //Solution space for this problem
 if (start == s.length()){
 //if we reach the end of the string add empty array to solution space
 pa.add(new ArrayList<String>());
 return pa;

 for (int i = start; i < s.length(); i ++){
 //if [start][i] is a palindrome
 //add this palindrome to all possible solution
 //for subproblem from i + 1 to the end
 if (isPa[start][i]){
 ArrayList<ArrayList<String>> postPas = findPa(s,i + 1, isPa);
 for (ArrayList<String> subPa: postPas){
 subPa.add(0,s.substring(start, i + 1));
 }//if isPa
 }//for i
 return pa;

public void calculateIsPa(String s, boolean[][] isPa){
 for (int l = 0 ; l < s.length(); l ++){
 for (int i = 0; i < s.length() - l; i ++){
 if (i == i + l){
 isPa[i][i+l] = true;
 else if (i == i + l -1){
 isPa[i][i+l] = (s.charAt(i) == s.charAt(i+l));
 }//else if
 isPa[i][i+l] = (s.charAt(i) == s.charAt(i+l)) && isPa[i+1][i+l-1];
 }//for int i
 }//for int l

A Pinterest like photo sharing website by Ruby on Rails

For the source code:

A photo sharing website with simple and beautiful user interface.

User could register new account, upload photos, follow other users, comment on posted photos and search for users or photos.


Here is the first look of this app. User could login or register.


When a user who hasn’t logined manually type ‘localhost:3000/home’ which requires logined user, he will get this error page.


When registering a new account, user has to provide a valid email address and also avatar image.Image

When user registered a new account successfully, he will receive a welcome email to the email address he provides.


This is a page for a user. All pictures posted by him will list right here.


On the home page, all the pictures posted by yourself and by the users you have followed would be listed. Newest posted pictures always come first in the order.

You can also see your profile, see your following, see your followed by or simply logout by using the menu on the right side that pops up when clicking on the button with your username.


Of course, you can use the search bar on the left top. If you do not provide any keyword there, you will get all users and pictures as follows. You can search for a username, a picture tag or a picture detail. Search result are listed separately, with users on the left and pictures on the right.


You could also comment on a posted picture. All comments are listed below the picture.

You could also tweet this page if you want. However, in a local version of this website, you cannot do so. If you are the user who posts this picture, you will also see the “Delete” button and “Edit” button.


So I think that’s pretty it.

Note: If you want, you can visit the online version of this website,

However, making it as the same as local version requires extra work that I haven’t done.

So a online version:

All pictures will be gone after a certain time.(Because heroku does not support to store images in folder /public/…..  Solution: Actually, I think using Amazon S3 service may be helpful. Just store all the images on Amazon server, then the database in this app restores the reference for how to retrieve image from Amazon server.)

User will not receive welcome email after registering. (Because extra add-on is needed for doing so. I didn’t buy the add-on on heroku)


Feel free to contact me,