Thursday, October 11, 2012

How to Create an Executable Zip File

Python has the ability to execute a zip file that contains Python files. This makes it very handy to create an executable zip file. Here's an example how to do it.
test.py
#!/usr/bin/env python

def say_something(): print "Hello World"
def main(): say_something()
__main__.py
#!/usr/bin/env python

import test

if __name__ == "__main__": test.main()
The __main__.py must be in the root directory of the zip file.

Zip all the Python files so that it looks like below. We don't need to use .zip extension, we can name it anything we want.

test.zip
|-- __main__.py
`-- test.py
To execute it:
python test.zip
and you will see the output as
Hello World

Wednesday, October 3, 2012

How to Capture StdOut/StdErr in Java

package test;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.io.StringWriter;

public class Main {
    public static interface Function {
        void execute();
    }
    
    public static String capture1(PrintStream ps, Function func)
        throws IOException {
        PipedOutputStream pos = new PipedOutputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(
            new PipedInputStream(pos)));
        StringWriter sw = new StringWriter();
        String output = null;
        try {
            PrintStream old = ps;
            System.setOut(new PrintStream(pos));

            func.execute();
            System.out.flush();

            pos.close();

            System.setOut(old);

            int charsRead;
            char[] cbuf = new char[4096];
            while ((charsRead = br.read(cbuf, 0, cbuf.length)) != -1) {
                sw.write(cbuf, 0, charsRead);
            }
            output = sw.toString();
        }
        finally {
            br.close();
            sw.close();
        }
        return output;
    }
    
    public static String capture2(PrintStream ps, Function func)
        throws IOException {
        String output = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            PrintStream old = System.out;
            System.setOut(new PrintStream(baos));

            func.execute();
            System.out.flush();

            System.setOut(old);

            output = baos.toString();
        }
        finally {
            baos.close();
        }
        return output;
    }
    
    public static void main(String[] args) throws Exception {
        String output = capture1(System.out, new Function() {
            @Override
            public void execute() {
                System.out.println("Hello World");
                System.out.println("Bye World");
            }
        });
        System.out.println(output);
        
        
        output = capture2(System.out, new Function() {
            @Override
            public void execute() {
                System.out.println("Hello World");
                System.out.println("Bye World");
            }
        });
        System.out.println(output);
    }
}

Monday, September 10, 2012

How to Parse Java Source Code using Oracle/Sun Java Compiler API

NOTE: using compiler API (com.sun.*) packages can be dangerous since they are supposed to be internal packages.
package test;

public class Foo {
    public String getSomething() {
        return "Hello World";
    }
}
package test;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.StatementTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.SimpleTreeVisitor;

public class Test {
    public static void main(String[] args) throws Exception {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> fileObjects = fileManager
            .getJavaFileObjects("test/Foo.java");
        JavacTask javac = (JavacTask) compiler.getTask(null, fileManager, null, null, null,
            fileObjects);
        Iterable<? extends CompilationUnitTree> trees = javac.parse();
        for (CompilationUnitTree tree : trees) {
            tree.accept(new CompilationUnitVisitor(), null);
        }
    }
    
    static class CompilationUnitVisitor extends SimpleTreeVisitor<Void, Void> {
        @Override
        public Void visitCompilationUnit(CompilationUnitTree cut, Void p) {
            System.out.println("Package name: " + cut.getPackageName());
            for (Tree t : cut.getTypeDecls()) {
                if (t instanceof ClassTree) {
                    ClassTree ct = (ClassTree) t;
                    ct.accept(new ClassVisitor(), null);
                }
            }
            return super.visitCompilationUnit(cut, p);
        }
    }
    
    static class ClassVisitor extends SimpleTreeVisitor<Void, Void> {
        @Override
        public Void visitClass(ClassTree ct, Void p) {
            System.out.println("Class name: " + ct.getSimpleName());
            for (Tree t : ct.getMembers()) {
                MethodTree mt = (MethodTree) t;
                mt.accept(new MethodVisitor(), null);
            }
            return super.visitClass(ct, p);
        }
    }
    
    static class MethodVisitor extends SimpleTreeVisitor<Void, Void> {
        @Override
        public Void visitMethod(MethodTree mt, Void p) {
            System.out.println("Method name: " + mt.getName());
            for (StatementTree st : mt.getBody().getStatements()) {
                if (st instanceof ReturnTree) {
                    ReturnTree rt = (ReturnTree) st;
                    rt.accept(new ReturnTreeVisitor(), null);
                }
            }
            return super.visitMethod(mt, p);
        }
    }
    
    static class ReturnTreeVisitor extends SimpleTreeVisitor<Void, Void> {
        @Override
        public Void visitReturn(ReturnTree rt, Void p) {
            System.out.println("Return statement: " + rt.getExpression());
            return super.visitReturn(rt, p);
        }
    }
}

Tuesday, August 14, 2012

How to Solve 3-Sum Problem

Given a set S of n integers, are there elements a, b, c in S such that a + b + c = 0?
package main

import (
    "fmt"
    "sort"
)

func ThreeSum(numbers []int) {
    for i := 0; i < len(numbers); i++ {
        for j := 0; j < len(numbers); j++ {
            nSearch := -(numbers[i] + numbers[j])
            index := sort.SearchInts(numbers, nSearch)
            if index < len(numbers) && numbers[index] == nSearch {
                fmt.Println(numbers[i], numbers[j], numbers[index])
            }
        }
    }
}

func main() {
    numbers := []int{-40, 30, -10, 50, 20}
    sortedNumbers := sort.IntSlice(numbers)
    sort.Sort(sortedNumbers)
    ThreeSum(sortedNumbers)
}

Monday, August 13, 2012

A Tool to Escape HTML Characters in Go

I created a handy tool to escape HTML characters, especially for pasting code in a blog like this.
Usage: ./escapehtml  [dest_dir]
If the source is a directory, the tool will scan the whole directory and escape each file found and output the escaped string to stdout (if dest_dir isn't specified) or to a file (if dest_dir is specified).
escapehtml.go
package main

import (
    "fmt"
    "os"
    "errors"
    "path/filepath"
    "io/ioutil"
    "html"
    "strings"
)

func printUsage() {
    fmt.Println("Usage:", os.Args[0],
        "<source_file/source_dir>", "[dest_dir]")
}

func errorMessage(s string) string {
    return "Error: " + s
}

type fileType struct {
    directory bool
    regularFile bool
}

func fileExists(path string) (*fileType, error) {
    file, err := os.Open(path)
    if err != nil {
        if os.IsNotExist(err) {
            return nil, errors.New(
                errorMessage(path + " does not exist"))
        }
    }
    defer file.Close()
    fileInfo, err := file.Stat()
    if err != nil {
        return nil, err
    }
    if fileInfo.IsDir() {
        return &fileType{directory: true}, nil
    }
    return &fileType{regularFile: true}, nil
}

func validateArgs() (bool, error) {
    if len(os.Args) != 2 && len(os.Args) != 3 {
        return false, nil
    }

    if _, err := fileExists(os.Args[1]); err != nil {
        return false, err
    }
    if len(os.Args) == 3 {
        ft, _ := fileExists(os.Args[2])
        if ft != nil && !ft.directory {
            return false, errors.New(
                errorMessage(os.Args[2] + " must be a directory"))
        }
    }
    return true, nil
}

func printHeader(header string) {
    fmt.Println(strings.Repeat("=", 72))
    fmt.Println(header)
    fmt.Println(strings.Repeat("=", 72))
}

func escapeHTML(srcPath string, destPath string) {
    filepath.Walk(srcPath,
        func(path string, info os.FileInfo, err error) error {
            if info.IsDir() {
                return nil
            }

            b, err := ioutil.ReadFile(path)
            if err != nil {
                return nil
            }

            escapedString := html.EscapeString(string(b))
            if destPath == "" {
                printHeader(path)
                fmt.Println(escapedString)
            } else {
                if ft, _ := fileExists(destPath); ft == nil {
                    if e := os.MkdirAll(destPath, 0775); e != nil {
                        errors.New("Unable to create directory: " +
                            destPath)
                    } else {
                        fmt.Println("Creating directory: " + destPath)
                    }
                }
                newPath := filepath.Join(destPath,
                    filepath.Base(path) + ".txt")
                fmt.Println("Creating", newPath)
                e := ioutil.WriteFile(newPath, []byte(escapedString), 0644)
                if e != nil {
                    return e
                }
            }
            return nil
        })
}

func main() {
    if valid, err := validateArgs(); !valid {
        if err != nil {
            fmt.Println(err)
            os.Exit(1)
        } else {
            printUsage()
            os.Exit(1)
        }
    }

    srcPath := os.Args[1]
    destPath := ""
    if len(os.Args) == 3 {
        destPath = os.Args[2]
    }
    escapeHTML(srcPath, destPath)
}
To build it, just type
go build escapehtml.go

Sunday, August 12, 2012

How to Implement Union Find Algorithms

package unionfind

type UnionFind interface {
    Find(int, int) bool
    Union(int, int)
}
//================================================
type QuickFind struct {
    Nodes []int
}

func (qf *QuickFind) Find(x, y int) bool {
    return qf.Nodes[x] == qf.Nodes[y]
}

func (qf *QuickFind) Union(x, y int) {
    tmp := qf.Nodes[x]
    qf.Nodes[x] = qf.Nodes[y]
    for i := 0; i < len(qf.Nodes); i++ {
        if qf.Nodes[i] == tmp {
            qf.Nodes[i] = qf.Nodes[y]
        }
    }
}
//================================================
type QuickUnion struct {
    Nodes []int
}

func (qu *QuickUnion) Find(x, y int) bool {
    return qu.root(x) == qu.root(y)
}

func (qu *QuickUnion) Union(x, y int) {
    rootX := qu.root(x)
    rootY := qu.root(y)
    qu.Nodes[rootX] = qu.Nodes[rootY]
}

func (qu *QuickUnion) root(x int) int {
    for qu.Nodes[x] != x {
        x = qu.Nodes[x]
    }
    return x
}
//================================================
type WeightedQuickUnion struct {
    Nodes []int
    sizes []int
}

func (wqu *WeightedQuickUnion) Find(x, y int) bool {
    return wqu.root(x) == wqu.root(y)
}

func (wqu *WeightedQuickUnion) Union(x, y int) {
    rootX := wqu.root(x)
    rootY := wqu.root(y)
    if wqu.sizes[rootX] < wqu.sizes[rootY] {
        wqu.Nodes[rootX] = wqu.Nodes[rootY]
        wqu.sizes[rootY] += wqu.sizes[rootX]
    } else {
        wqu.Nodes[rootY] = wqu.Nodes[rootX]
        wqu.sizes[rootX] += wqu.sizes[rootY]
    }
}

func (wqu *WeightedQuickUnion) root(x int) int {
    for wqu.Nodes[x] != x {
        x = wqu.Nodes[x]
    }
    return x
}

Tuesday, July 31, 2012

My .vimrc

set tabstop=4
set shiftwidth=4
set expandtab
set autoindent
set smartindent
set number
set ruler
set hlsearch
set ignorecase