Showing posts with label Python. Show all posts
Showing posts with label Python. Show all posts

Wednesday, November 6, 2013

How to Embed Python into C++

Below is a simple example how to embed Python into C++.
#include <iostream>
#include <Python.h>

int main(int argc, char* argv[]) {
    Py_Initialize();
    PyRun_SimpleString("import math; a = 100; result = math.log10(100)");
    PyObject* module = PyImport_AddModule("__main__");
    PyObject* dictionary = PyModule_GetDict(module);
    PyObject* result = PyDict_GetItemString(dictionary, "result");
    double resultValue = PyFloat_AsDouble(result);
    std::cout << "result: " << resultValue << std::endl;
    Py_Finalize();
    return 0;
}
Output:
result: 2

Tuesday, February 19, 2013

Rebasing in SVN

Suppose you are creating a branch from a trunk and you need to merge the commits from the trunk to the branch. Unlike Git, SVN does not really have a concept of rebasing. To do that in SVN, it requires quite a bit of work. To simplify the tasks of rebasing in SVN, I created small tools, one in Go and the other one in Python.
svnrebase.go
package main

import (
    "bufio"
    "bytes"
    "errors"
    "fmt"
    "io"
    "os"
    "os/exec"
    "strings"
)

const BaseRevFile = "base_rev.txt"

func getLatestBaseSVNRev(svnBaseURL string) (string, error) {
    out, e1 := exec.Command("svn", "info", svnBaseURL).Output()
    if e1 != nil {
        return "", errors.New("Unable to execute svn info " +
            svnBaseURL)
    }
    r := bufio.NewReader(bytes.NewReader(out))
    for {
        l, _, e2 := r.ReadLine()
        if e2 == io.EOF {
            break
        }
        s := string(l)
        if strings.Contains(s, "Revision:") {
            svnRev := strings.TrimSpace(strings.Split(s, ":")[1])
            return svnRev, nil
        }
    }
    return "", errors.New("Unable to get the SVN revision number")
}

func getOldBaseSVNRev() (string, error) {
    f, e := os.Open(BaseRevFile)
    if e != nil {
        return "", errors.New(BaseRevFile + " does not exist. " +
            "You need to create this file initially!")
    }
    defer f.Close()
    r := bufio.NewReader(f)
    l, _, _ := r.ReadLine()
    return strings.TrimSpace(string(l)), nil
}

func updateBaseSVNFile(newBaseRev string) error {
    f, e := os.OpenFile(BaseRevFile, os.O_WRONLY, 0666)
    if e != nil {
        return e
    }
    defer f.Close()
    f.Write([]byte(newBaseRev))
    return nil
}

func SVNRebase(svnBaseURL string, dryRun bool) error {
    oldBaseRev, e1 := getOldBaseSVNRev()
    if e1 != nil {
        return e1
    }
    newBaseRev, e2 := getLatestBaseSVNRev(svnBaseURL)
    if e2 != nil {
        return e2
    }
    if oldBaseRev == newBaseRev {
        fmt.Println("Your repo has already had the latest revision")
        return nil
    }
    cmd := "svn"
    args := []string{"merge"}
    if dryRun {
        args = append(args, "--dry-run")
    }
    args = append(args, svnBaseURL + "@" + oldBaseRev)
    args = append(args, svnBaseURL + "@" + newBaseRev)
    fmt.Println("Command:", cmd + " " + strings.Join(args, " "))
    c := exec.Command(cmd, args...)
    c.Stdout = os.Stdout
    c.Stdin = os.Stdout
    c.Stderr = os.Stderr
    e3 := c.Run()
    if e3 != nil {
        return e3
    }
    if !dryRun {
        updateBaseSVNFile(newBaseRev)
    }
    return nil
}

func printUsage() {
    fmt.Println("Usage:", os.Args[0], "<svn_base_url> [--dry-run]")
}

func validateArgs() {
    if len(os.Args) == 1 || len(os.Args) > 3 {
        printUsage()
        os.Exit(1)
    }
    if len(os.Args) == 3 {
        if os.Args[2] != "--dry-run" {
            fmt.Println("Error: Invalid option:", os.Args[2])
            os.Exit(1)
        }
    }
}

func main() {
    validateArgs()
    baseSVNURL := os.Args[1]
    dryRun := false
    if len(os.Args) == 3 {
        dryRun = true
    }
    if e := SVNRebase(baseSVNURL, dryRun); e != nil {
        fmt.Println("Error:", e)
    }
}
Usage: ./svnrebase  [--dry-run]
svnrebase.py
#!/usr/bin/env python
import sys, subprocess, os

BASE_REV_FILE = 'base_rev.txt'

def get_latest_base_svn_rev(svn_base_url):
    p = subprocess.Popen(['svn', 'info', svn_base_url], stdout=subprocess.PIPE)
    for line in p.communicate()[0].split(os.linesep):
        if line.startswith('Revision:'):
            return line.split(":")[1].strip()
    return None

def get_old_base_svn_rev():
    if not os.path.exists(BASE_REV_FILE):
        raise Exception(BASE_REV_FILE + ' does not exist. ' + 
                        'You need to create this file initially!')
    f = open(BASE_REV_FILE, 'r')
    return f.read().strip() 

def update_base_svn_file(new_base_rev):
     f = open(BASE_REV_FILE, 'w')
     f.write(new_base_rev)
     f.close()

def svn_rebase(svn_base_url, dry_run):
    old_base_rev = get_old_base_svn_rev()
    new_base_rev = get_latest_base_svn_rev(svn_base_url)
    if old_base_rev == new_base_rev:
        print 'Your repo has already had the latest revision'
        return
    cmd = ['svn', 'merge']
    if dry_run:
        cmd.append('--dry-run')
    cmd.append(svn_base_url + '@' + old_base_rev)
    cmd.append(svn_base_url + '@' + new_base_rev)
    print 'Command:', ' '.join(cmd)
    subprocess.call(cmd)
    if not dry_run:
       update_base_svn_file(new_base_rev)

def print_usage():
    print 'Usage:', sys.argv[0], '<svn_base_url> [--dry-run]'

def validate_args():
    if len(sys.argv) == 1 or len(sys.argv) > 3:
        print_usage()
        sys.exit(1)
    if len(sys.argv) == 3:
        if sys.argv[2] != '--dry-run':
            print 'Error: Invalid option:', sys.argv[2]
            sys.exit(1)

if __name__ == '__main__':
    validate_args()
    base_svn_url = sys.argv[1]
    dry_run = True if len(sys.argv) == 3 else False
    try:
        svn_rebase(base_svn_url, dry_run)
    except Exception, e:
        print 'Error:', e
Usage: ./svnrebase.py  [--dry-run]
Initially, you need to create base_rev.txt that specifies which revision your branch was created. Subsequently, the base_rev.txt will be automatically updated by the tool.

Monday, December 17, 2012

How to Solve Cutting Rod Problem

This solution uses memoization.
#!/usr/bin/env python

def find_max(list_tuples):
    if len(list_tuples) == 0:
        return None
    maximum = list_tuples[0]
    for i in xrange(1, len(list_tuples)):
        if maximum[0] < list_tuples[i][0]:
            maximum = list_tuples[i]
    return maximum

memo = {}
def cutting_rod(prices, ncuts):
    if ncuts == 0:
        return (0, [])
    if ncuts in memo:
        return memo[ncuts]
    tmp = []
    for i in xrange(0, ncuts):
        r = cutting_rod(prices, ncuts-i-1)
        new_list = list(r[1])
        new_list.append(i)
        value = prices[i] + r[0]
        tmp.append((value, new_list))
    result = find_max(tmp)
    memo[ncuts] = result
    return result

if __name__ == '__main__':
    p = [2, 5, 6, 7]
    r = cutting_rod(p, len(p))
    print "Prices:", p
    print "Optimal value:", r[0]
    print "Indices:", r[1]
    print "Cuts:", [p[x] for x in r[1]]
Output:
Prices: [2, 5, 6, 7]
Optimal value: 10
Indices: [1, 1]
Cuts: [5, 5]

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

Friday, July 13, 2012

Compressing Characters in Python

This is an in-place algorithm for compressing characters, e.g.
AABBCCCDDXYYZ --> A2B2C3D2XY2Z
The reason why the output isn't A2B2C3D2X1Y2Z1 is because adding 1 for only any non-repeated contagious character can make the compressed data bigger than the actual data, e.g.
ABCD --> A1B1C1D1 (A1B1C1D1 is larger than ABCD)
#!/usr/bin/env python

def compress(l):
    if len(l) == 0: return []
    counter = 1
    tmp = l[0]
    i = 1
    while i < len(l):
        if l[i] != tmp:
            new_index = update(i, counter, l)
            i = new_index + 1
            tmp = l[i]
            counter = 1
        else:
            counter += 1
        i += 1
    update(i, counter, l)
    return l

def update(current_index, counter, l):
    if counter == 1: return current_index - 1
    new_index = current_index - (counter - 1)
    l[new_index] = str(counter)
    shift(current_index, new_index+1, l)
    return new_index

def shift(source_index, destination_index, l):
    last_index = len(l)
    i = 0
    while (source_index + i) < last_index:
        l[destination_index+i] = l[source_index+i]
        i += 1
    last_index = destination_index + i
    del l[last_index:]

if __name__ == "__main__":
    assert (['A', '4', 
            'B', '2', 
            'C', 
            'D', '3', 
            'E', '2', 
            'A', '2', 
            'X', 
            'Y', '5', 
            'Z'] 
            == 
            compress(["A", "A", "A", "A",
                      "B", "B",
                      "C",
                      "D", "D", "D",
                      "E", "E",
                      "A", "A",
                      "X",
                      "Y", "Y", "Y", "Y", "Y",
                      "Z"]))

Converting Relative Path to Absolute Path in Python

#!/usr/bin/env python

def get_absolute_path(path):
    files = path.split("/")
    l = []
    for f in files:
        if f == "..":
            l.pop()
        else:
            l.append(f)
    return "/".join(l)

if __name__ == "__main__":
    assert "/windows/temp/" == get_absolute_path("/windows/abs/../temp/new/../")
    assert "windows/temp/" == get_absolute_path("windows/abs/../temp/new/../")
    assert "/windows/temp" == get_absolute_path("/windows/abs/../temp/new/..")

Wednesday, July 11, 2012

Implementing Word Completion in Python

#!/usr/bin/env python

class Node(object):
    def __init__(self, value=None):
        self.value = value
        self.children = []
        
class Trie(object):
    def __init__(self):
        self.root = Node("Root")
    
    def add(self, key):
        self._add(self.root, key, 0)

    def _add(self, node, key, index):
        if len(key) == index: return
        next_node = None
        for n in node.children:
            if n.value == key[index]:
                next_node = n
                break
        if next_node is None:
            next_node = Node(key[index])
            node.children.append(next_node)
            print "Adding", next_node.value, "into", node.value
        self._add(next_node, key, index+1)
    
    def find(self, key):
        return self._find(self.root, key, 0)
    
    def _find(self, node, key, index):
        if len(key) == index: return node
        found = False
        for n in node.children:
            if n.value == key[index]:
                found = True
                last_found_node = self._find(n, key, index+1)
        if not found: return None
        else: return last_found_node
        
    def search(self, key):
        result = []
        last_node = self.find(key)
        if last_node is None: return result
        self._search(last_node, key, "", result)
        for i in xrange(0, len(result)):
            result[i] = key + result[i]
        return result
    
    def _search(self, node, key, char, result):
        if len(node.children) == 0:
            result.append(char)
            return
        for n in node.children:
            self._search(n, key, char + n.value, result)
        
    
class WordCompletion(object):
    def __init__(self, words):
        self.trie = Trie()
        for word in words:
            print "===== Inserting", word, "====="
            self.trie.add(word)
    
    def search(self, prefix):
        return self.trie.search(prefix)
        
if __name__ == "__main__":
    words = ["ABCD", "ABCE", "AFG", "AFHIJ", "AFHIK", "XY"]
    wc = WordCompletion(words)
    
    assert ['ABCD', 'ABCE', 'AFG', 'AFHIJ', 'AFHIK'] == wc.search("A")
    assert ['AFHIJ', "AFHIK"] == wc.search("AFHI")
    assert ['AFHIJ', 'AFHIK'] == wc.search("AFH")
    assert ['ABCD', 'ABCE'] == wc.search("ABC")
    assert [] == wc.search("whatever")

Wednesday, July 4, 2012

Implementing Tic-Tac-Toe in Python

This is my simple tic-tac-toe implementation in Python.
#!/usr/bin/env python

class TicTacToe(object):
    def __init__(self, n=3):
        self.n = n
        self.board = []
        for i in xrange(self.n):
            self.board.append([])
            for j in xrange(self.n):
                self.board[i].append(" ")
        
    def draw(self):
        for x in self.board:
            print x
            
    def move(self, player, x, y):
        if x >= self.n or y >= self.n:
            raise Exception("Invalid move!")
        if self.board[x][y] != " ":
            raise Exception("Invalid move!")
        self.board[x][y] = player
    
    def win(self, player):
        same = True
        for i in xrange(self.n):
            if self.board[0][i] != player: 
                same = False
                break
        if same: return True
        
        same = True
        for i in xrange(self.n):
            if self.board[i][0] != player:
                same = False
                break
        if same: return True
        
        same = True        
        for i in xrange(self.n):
            if self.board[self.n-1][i] != player:
                same = False
                break
        if same: return True

        same = True
        for i in xrange(self.n):
            if self.board[i][self.n-1] != player:
                same = False
                break
        if same: return True
        
        same = True
        for i in xrange(self.n):
            if self.board[i][i] != player:
                same = False
                break
        if same: return True
        
        same = True
        x = -1
        y = self.n
        for i in xrange(self.n):
            x += 1
            y -= 1
            if self.board[x][y] != player:
                same = False
                break
        if same: return True
        return False
                

if __name__ == "__main__":
    player1 = "X"
    player2 = "O"
    
    t3 = TicTacToe()
    
    t3.move(player1, 2, 0)
    t3.move(player2, 1, 2)
    
    t3.move(player1, 1, 1)
    t3.move(player2, 2, 1)
    
    t3.move(player1, 0, 2)
    
    t3.draw()
    
    print "Player1", "won" if t3.win(player1) else "lost"
    print "Player2", "won" if t3.win(player2) else "lost"

Tuesday, July 3, 2012

How to Generate a List of Possible Words in a Phone Number in Python

Example, if we type 2 -> 2 -> 3. The we have can have words like "AAD", "AAE", "AAF", etc.
#!/usr/bin/env python

numbers = {"2" : ["A", "B", "C"],
           "3" : ["D", "E", "F"],
           "4" : ["G", "H", "I"],
           "5" : ["J", "K", "L"],
           "6" : ["M", "N", "O"],
           "7" : ["P", "Q", "R"],
           "8" : ["S", "T", "U"],
           "9" : ["V", "W", "X"],
           "0" : ["Y", "Z"]}

def generate(input_list):
    return gen(input_list, 0, "")

def gen(input_list, index, n):
    if index > len(input_list)-1: return [n]
    output_list = []
    for i in input_list[index]:
        index += 1
        for x in numbers[i]:
            tmp = gen(input_list, index, x)
            for t in tmp:
                output_list.append(n + t)
    return output_list
    
if __name__ == "__main__":
    for i in generate(["2", "4", "3", "6"]): print i

Wednesday, May 30, 2012

How to Pass Some Arguments to BaseHTTPRequestHandler in Python

Let's say we have an argument, which is a function that we want to pass to BaseHTTRequestHandler to handle a request and return an appropriate response based the request. By looking at HTTPServer class definition, it may not be really obvious how to do it.

It's actually pretty simple and straightforward how to do it. First we need to subclass HTTPServer and override the constructor that takes in our own new arguments. From the RequestHandler class, there'll be a property named server that gives us access to the HTTPServer instance. And since we've subclassed HTTPServer class, we can define as many properties as we want that those properties will be accessible in the server property of the HTTPRequestHandler. The example is shown below.

#!/usr/bin/env python

import logging
from BaseHTTPServer import HTTPServer
from BaseHTTPServer import BaseHTTPRequestHandler

class HttpServerHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers.getheader("Content-Length"))
        request = self.rfile.read(content_length)
        logging.info("Request: %s" % request)
        # BaseHTTPRequestHandler has a property called server and because
        # we create MyHTTPServer, it has a handler property
        response = self.server.handler(request)
        logging.info("Response: %s" % response)
        self.send_response(200)
        self.end_headers()
        self.wfile.write(response)
    
class MyHTTPServer(HTTPServer):
    """this class is necessary to allow passing custom request handler into
       the RequestHandlerClass"""
    def __init__(self, server_address, RequestHandlerClass, handler):
        HTTPServer.__init__(self, server_address, RequestHandlerClass)
        self.handler = handler
            
class HttpServer:
    def __init__(self, name, host, port, handler):
        self.name = name
        self.host = host
        self.port = port
        self.handler = handler
        self.server = None
        
    def start(self):
        logging.info('Starting %s at %s:%d' % (self.name, self.host, self.port))
        # we need use MyHttpServer here
        self.server = MyHTTPServer((self.host, self.port), HttpServerHandler,
                                   self.handler)
        self.server.serve_forever()
    
    def stop(self):
        if self.server:
            logging.info('Stopping %s at %s:%d' % (self.name, self.host,
                                                   self.port))
            self.server.shutdown()

def server_handler(request):
    if request == "foo":
        return "bar"
    elif request == "bar":
        return "foo"
    else:
        return "foobar"

if __name__ == "__main__":
    logging.basicConfig(format='%(asctime)s [%(levelname)s] %(message)s', 
                        level=logging.INFO)
    server = HttpServer("test server", "localhost", 9999, server_handler)
    server.start()

Thursday, May 24, 2012

How to Implement DFS and BFS in Python

#!/usr/bin/env python

class Graph(object):
    def __init__(self):
        # the key is the vertex, the value is the list of adjacent vertices
        self.adjacents = {}
        self.nedges = 0

    def num_vertices(self):
        return self.adjacents.keys()

    def num_edges(self):
        return self.nedges

    def add_edge(self, v, w):
        if v not in self.adjacents: self.adjacents[v] = []
        self.adjacents[v].append(w)
        if w not in self.adjacents: self.adjacents[w] = []
        self.adjacents[w].append(v)
        self.nedges += 1

    def adjacent(self, v):
        return self.adjacents[v]

class DepthFirstSearch(object):
    def __init__(self, graph, start):
        self.count = 0
        self.markeddict = {}
        self.edge_to = {}
        self.start = start
        self._dfs(graph, start)

    def _dfs(self, graph, vertex):
        self.markeddict[vertex] = True
        self.count += 1
        for v in graph.adjacent(vertex):
            if not self.marked(v):
                self.edge_to[v] = vertex
                self._dfs(graph, v)

    def marked(self, vertex):
        return vertex in self.markeddict

    def has_path_to(self, vertex):
        return self.marked(vertex)

    def path_to(self, vertex):
        if not self.has_path_to(vertex): return None
        path = []
        path.append(vertex)
        while vertex != self.start:
            vertex = self.edge_to[vertex]
            path.append(vertex)
        
        path.reverse()
        return path

class BreadthFirstSearch(object):
    def __init__(self, graph, start):
        self.count = 0
        self.markeddict = {}
        self.edge_to = {}
        self.start = start
        self._bfs(graph, start)

    def _bfs(self, graph, vertex):
        self.markeddict[vertex] = True
        self.count += 1
        q = []
        q.append(vertex)
        while q:
            key = q.pop(0)
            for v in graph.adjacent(key):
                if not self.marked(v):
                    q.append(v)
                    self.count += 1
                    self.markeddict[v] = True
                    self.edge_to[v] = key

    def marked(self, vertex):
        return vertex in self.markeddict

    def has_path_to(self, vertex):
        return self.marked(vertex)

    def path_to(self, vertex):
        if not self.has_path_to(vertex): return None
        path = []
        path.append(vertex)
        while vertex != self.start:
            vertex = self.edge_to[vertex]
            path.append(vertex)
        
        path.reverse()
        return path

if __name__ == "__main__":
    # key is the vertex and value is the list of adjacent vertices
    graph = Graph()
    
    graph.add_edge("0", "2")
    graph.add_edge("3", "5")
    graph.add_edge("3", "4")
    graph.add_edge("0", "1")
    graph.add_edge("1", "2")
    graph.add_edge("2", "3")
    graph.add_edge("2", "4")
    graph.add_edge("0", "5")

    dfs = DepthFirstSearch(graph, "0")
    assert "0" == "-".join(dfs.path_to("0"))
    assert "0-2-1" == "-".join(dfs.path_to("1"))
    assert "0-2" == "-".join(dfs.path_to("2"))
    assert "0-2-3" == "-".join(dfs.path_to("3"))
    assert "0-2-3-4" == "-".join(dfs.path_to("4"))
    assert "0-2-3-5" == "-".join(dfs.path_to("5"))
    assert 6 == dfs.count
    
    bfs = BreadthFirstSearch(graph, "0")
    assert "0" == "-".join(bfs.path_to("0"))
    assert "0-1" == "-".join(bfs.path_to("1"))
    assert "0-2" == "-".join(bfs.path_to("2"))
    assert "0-2-3" == "-".join(bfs.path_to("3"))
    assert "0-2-4" == "-".join(bfs.path_to("4"))
    assert "0-5" == "-".join(bfs.path_to("5"))
    assert 6 == bfs.count

Wednesday, May 23, 2012

How to Reverse Order of Words in Python

#!/usr/bin/env python

def reverse_words(string):
    reverse(string, 0, len(string)-1)
    
    prev_space_index = 0
    for i in xrange(0, len(string)):
        if string[i] == " ":
            reverse(string, prev_space_index, i-1)
            prev_space_index = i + 1

    # the last word hasn't been reversed    
    if prev_space_index < len(string):
        reverse(string, prev_space_index, len(string)-1)

def reverse(string, beg, end):
    i = beg
    j = end
#    print string[beg:end]
    while i < j:
        string[i], string[j] = string[j], string[i]
        i += 1
        j -= 1
    
if __name__ == "__main__":
    l = list("my first name is foo and my last name is bar")
    reverse_words(l)
    
    assert "bar is name last my and foo is name first my" == "".join(l)    

Sunday, May 20, 2012

How to Implement Permutations in Python

#!/usr/bin/env python

def permutate(l, n, nl):
    if n == 0:
        if len(nl) != len(set(nl)): return
        nl1 = []
        for i in nl: nl1.append(l[i])
        print nl1 
    else:
        n = n - 1 
        nl1 = [x for x in nl] 
        for i in xrange(0, len(l)):
            nl = [x for x in nl1]
            nl.append(i)
            permutate(l, n, nl) 
            del nl[:]

def permutations(l):
    permutate(l, len(l), [])

if __name__ == "__main__":
    permutations([1, 2, 3, 4])

Search Algorithms in Python

Below are some popular implementations of searching algorithms.
#!/usr/bin/env python

class SequentialSearchDict(object):
    class Node(object):
        def __init__(self, key, value):
            self.key = key
            self.value = value
            self.next = None
    
    def __init__(self):
        self.first = None
        self.size = 0
       
    def put(self, key, value):
        self._put(key, value)
    
    def _put(self, key, value):
        n = self._get(key)
        if n:
            n.value = value
            return 0
        else:
            # add the new node into the first
            tmp = self.first
            self.first = SequentialSearchDict.Node(key, value)
            self.first.next = tmp
            self.size += 1
            return 1
   
    def _get(self, key):
        n = self.first
        while n:
            if n.key == key: return n
            n = n.next
        return None
   
    def get(self, key):
        n = self._get(key)
        if n: return n.value
        return n
   
class BinarySearchDict(object):
    class Node(object):
        def __init__(self, key, value):
            self.key = key
            self.value = value
    
    def __init__(self):
        self.size = 0
        self.l = []
       
    def put(self, key, value):
        # the elements must be kept sorted for the binary search to work
        index = self._get(key)
        if index < 0:
            self.l.append(BinarySearchDict.Node(key, value))
            self.size += 1
            return
        n = self.l[index]
        if n.key == key:
            n.value = value
        else:
            self.l.append(BinarySearchDict.Node(key, value))
            # shift all the elements to the right
            if (index+1) < (len(self.l)-1):
                for i in xrange(len(self.l)-1, index, -1):
                    self.l[i] = self.l[i-1]
            self.size += 1
           
    def get(self, key):
        # search using binary search
        index = self._get(key)
        if index < 0: return None
        n = self.l[index]
        if n.key == key: return n.value
        return None
       
    def _get(self, key):
        lo = 0
        hi = len(self.l) - 1
        mid = (lo + hi) / 2
        while lo <= mid and hi >= mid:
            if self.l[mid].key > key:
                hi = mid - 1
                mid = (lo + hi) / 2
            elif self.l[mid].key == key:
                return mid
            elif self.l[mid].key < key:
                lo = mid + 1
                mid = (lo + hi) / 2
        return mid
       
class BinarySearchTreeDict(object):
    class Node(object):
        def __init__(self, key, value):
            self.key = key
            self.value = value
            self.left = None
            self.right = None
            
    def __init__(self):
        self.size = 0
        self.root = None
       
    def put(self, key, value):
        self.root = self._put(key, value, self.root)
   
    def get(self, key):
        return self._get(key, self.root)
        
    def _put(self, key, value, node):
        if node == None:
            self.size += 1
            return BinarySearchTreeDict.Node(key, value)
        if node.key == key:
            node.value = value
            return node
        elif node.key < key: node.left = self._put(key, value, node.left)
        else: node.right = self._put(key, value, node.right)
        return node
        
    def _get(self, key, node):
        if node == None: return None
        if node.key == key: return node.value
        elif node.key < key: return self._get(key, node.left)
        else: return self._get(key, node.right)
   
class BalancedSearchTreeDict(object):
    class Node(object):
        RED = True
        BLACK = False
        
        def __init__(self, key, value):
            self.key = key
            self.value = value
            self.left = None
            self.right = None
            self.color = BalancedSearchTreeDict.Node.RED
            
        def is_red(self, node):
            if node == None: return False
            return node.color == BalancedSearchTreeDict.Node.RED
        
        def rotate_left(self, node):
            x = node.right
            node.right = x.left
            x.left = node
            node.color = BalancedSearchTreeDict.Node.RED
            return x 
        
        def rotate_right(self, node):
            x = node.left
            node.left = x.right
            x.right = node
            node.color = BalancedSearchTreeDict.Node.RED
            return x
        
        def flip_colors(self, node):
            node.color = BalancedSearchTreeDict.Node.RED
            node.left.color = BalancedSearchTreeDict.Node.BLACK
            node.right.color = BalancedSearchTreeDict.Node.BLACK
            
    def __init__(self):
        self.size = 0
        self.root = None
       
    def put(self, key, value):
        self.root = self._put(key, value, self.root)
        self.root.color = BalancedSearchTreeDict.Node.BLACK
   
    def _put(self, key, value, node):
        if node == None:
            self.size += 1
            return BalancedSearchTreeDict.Node(key, value)
        if node.key == key:
            node.value = value
            return node
        elif node.key < key: node.left = self._put(key, value, node.left)
        else: node.right = self._put(key, value, node.right)
        
        # these are the properties of Red-Black tree for balancing
        # the tree
        if node.is_red(node.right) and not node.is_red(node.left):
            node = node.rotate_left(node);
        if node.is_red(node.left) and node.is_red(node.left.left):
            node = node.rotate_right(node);
        if node.is_red(node.left) and node.is_red(node.right):
            node.flip_colors(node);
      
        return node
        
    def get(self, key):
        return self._get(key, self.root)
    
    def _get(self, key, node):
        if node == None: return None
        if node.key == key: return node.value
        elif node.key < key: return self._get(key, node.left)
        else: return self._get(key, node.right)
   
class HashDict(object):
    # choose this M to be a prime number
    M = 977
    
    def __init__(self, n=M):
        self.size = 0
        self.l = []
        for i in xrange(0, n):
            self.l.append(SequentialSearchDict())
            
    def _hash(self, key):
        return (hash(key) & 0x7ffffff) % HashDict.M
    
    def put(self, key, value):
        d = self.l[self._hash(key)]
        n = d._put(key, value)
        self.size += n
   
    def get(self, key):
        return self.l[self._hash(key)].get(key)
 
if __name__ == "__main__":
    searches = [SequentialSearchDict(),
                BinarySearchDict(),
                BinarySearchTreeDict(),
                BalancedSearchTreeDict(),
                HashDict()]
    for s in searches:                                                                                                                                                                                                                  
        assert None == s.get("foo")
        s.put("1", "a")
        s.put("2", "b")
        s.put("3", "c")
        assert 3 == s.size
        assert "b" == s.get("2")
        assert "c" == s.get("3")
        assert "a" == s.get("1")
        s.put("3", "d")
        assert 3 == s.size
        assert "d" == s.get("3")
        assert "b" == s.get("2")
        assert "a" == s.get("1")
        assert None == s.get("bar")

Thursday, May 17, 2012

How to Implement Pascal Triangle in Python

My implementation of Pascal Triangle.
#!/usr/bin/env python
def pascal(n):
    if n == 0: 
        return [1]
    else:
        l1 = pascal(n-1)
        print l1
        l2 = [1]
        for i in xrange(1, len(l1)):
            l2.append(l1[i-1] + l1[i])
        l2 += [1]
        return l2

if __name__ == "__main__":
    import sys
    if len(sys.argv) != 2:
        print "Usage:", sys.argv[0], "n"
        sys.exit(1)
    pascal(int(sys.argv[1]))

How to Implement Binary Search in Python

My simple implementations of binary search algorithms (iterative and recursive) in Python.
#!/usr/bin/env python

def search(l, i, func):
    lo = 0
    hi = len(l) - 1
    mid = (lo + hi) / 2
    return func(l, i, lo, mid, hi)
    
def recursive_binary_search(l, i, lo, mid, hi):
    if lo > mid or hi < mid: return -1

    if l[mid] > i:
        hi = mid - 1
        mid = (lo + hi) / 2
        return recursive_binary_search(l, i, lo, mid, hi)
    elif l[mid] == i:
        return mid
    elif l[mid] < i:
        lo = mid + 1
        mid = (lo + hi) / 2
        return recursive_binary_search(l, i, lo, mid, hi)

def iterative_binary_search(l, i, lo, mid, hi):
    while lo <= mid and hi >= mid:
        if l[mid] > i:
            hi = mid - 1
            mid = (lo + hi) / 2
        elif l[mid] == i:
            return mid
        elif l[mid] < i:
            lo = mid + 1
            mid = (lo + hi) / 2
    return -1
    
if __name__ == "__main__":
    l = [x for x in xrange(0, 10)]
    print "Using recursive binary search"
    print "Input:", l
    for i in xrange(0, len(l)):
        index = search(l, i, recursive_binary_search)
        print "Searching for", i, ", got index", index
        assert i == index
    i = 10
    index = search(l, i, recursive_binary_search)
    print "Searching for", i, ", got index", index

    print

    print "Using iterative binary search"
    print "Input:", l
    for i in xrange(0, len(l)):
        index = search(l, i, iterative_binary_search)
        print "Searching for", i, ", got index", index
        assert i == index
    i = 10
    index = search(l, i, iterative_binary_search)
    print "Searching for", i, ", got index", index

Sunday, April 22, 2012

How to Implement Queue in Python

Below are my simple implementations of queue (FIFO) using array list (some wasted space) and linked list (no wasted space). The LinkedQueue uses the linked list implementation as described here.
#!/usr/bin/env python

class Queue(object):
    def __init__(self):
        self.head = 0
        self.tail = 0
        self.n = 0
        self.l = []
    
    def enqueue(self, element):
        # this will create a lot of wasted space. Use something like
        # linked list
        self.l.append(element)
        self.tail += 1
        self.n += 1
    
    def dequeue(self):
        if self.n == 0: return None
        e = self.l[self.head]
        self.head += 1
        self.n -= 1
        return e
        
    def size(self):
        return self.n
    
    def elements(self):
        return [self.l[i] for i in xrange(self.head, self.tail)]

class LinkedQueue(object):
    def __init__(self):
        import linkedlist
        self.l = linkedlist.LinkedList()
    
    def enqueue(self, element):
        self.l.append(element)
    
    def dequeue(self):
        return self.l.front()
        
    def size(self):
        return self.l.size()
    
    def elements(self):
        return [x for x in self.l.elements()]
    
if __name__ == "__main__":
    q = Queue()
    
    assert None == q.dequeue()
    
    q.enqueue(1)
    q.enqueue(2)
    q.enqueue(3)

    assert 1 == q.dequeue()
    assert 2 == q.dequeue()
    assert 3 == q.dequeue()

    q.enqueue(1)
    q.enqueue(2)
    q.enqueue(3)
    q.enqueue(4)
    q.enqueue(5)
    
    assert 1 == q.dequeue()
    assert 2 == q.dequeue()
    assert 3 == q.dequeue()
    assert 4 == q.dequeue()
    assert 5 == q.dequeue()
    
    lq = LinkedQueue()
    
    assert None == lq.dequeue()
    
    lq.enqueue(1)
    lq.enqueue(2)
    lq.enqueue(3)

    assert 1 == lq.dequeue()
    assert 2 == lq.dequeue()
    assert 3 == lq.dequeue()

    lq.enqueue(1)
    lq.enqueue(2)
    lq.enqueue(3)
    lq.enqueue(4)
    lq.enqueue(5)
    
    assert 1 == lq.dequeue()
    assert 2 == lq.dequeue()
    assert 3 == lq.dequeue()
    assert 4 == lq.dequeue()
    assert 5 == lq.dequeue()

How to Implement Stack in Python

Below are my simple implementations of stack (LIFO) using array list (some wasted space) and linked list (no wasted space). The LinkedStack uses the linked list implementation as described here.
#!/usr/bin/env python

class Stack(object):
    def __init__(self):
        self.l = []
        self.n = 0
        
    def push(self, element):
        if len(self.l) > self.n:
            self.l[self.n] = element
        else:
            self.l.append(element)
        self.n += 1
        
    def pop(self):
        if self.n == 0: return None
        self.n -= 1
        return self.l[self.n]
    
    def size(self):
        return self.n
    
    def elements(self):
        return [self.l[i] for i in xrange(0, self.n)]

class LinkedStack(object):
    def __init__(self):
        import linkedlist
        self.l = linkedlist.LinkedList()
        
    def push(self, element):
        self.l.append(element)
        
    def pop(self):
        return self.l.back()
    
    def size(self):
        return self.l.size()
    
    def elements(self):
        return [x for x in self.l.elements()]
        
if __name__ == "__main__":
    s = Stack()

    assert None == s.pop()
    
    s.push(1)
    s.push(2)
    s.push(3)
        
    assert 3 == s.pop()
    assert 2 == s.pop()
    assert 1 == s.pop()
    
    s.push(1)
    s.push(2)
    s.push(3)
    s.push(4)
    s.push(5)
    
    assert 5 == s.pop()
    assert 4 == s.pop()
    assert 3 == s.pop()
    assert 2 == s.pop()
    assert 1 == s.pop()
    
    ls = LinkedStack()

    assert None == ls.pop()
    
    ls.push(1)
    ls.push(2)
    ls.push(3)
        
    assert 3 == ls.pop()
    assert 2 == ls.pop()
    assert 1 == ls.pop()
    
    ls.push(1)
    ls.push(2)
    ls.push(3)
    ls.push(4)
    ls.push(5)
    
    assert 5 == ls.pop()
    assert 4 == ls.pop()
    assert 3 == ls.pop()
    assert 2 == ls.pop()
    assert 1 == ls.pop()

How to Implement Doubly Linked List in Python

This is my simple implementation of doubly linked list in Python.
#!/usr/bin/env python

class Node(object):
    def __init__(self):
        self.next = None
        self.previous = None
        self.element = None
    
class LinkedList(object):
    def __init__(self):
        self.n = 0
        self.last = Node()
        self.first = self.last
        
    def append(self, element):
        self.last.element = element
        self.last.next = Node()
        tmp = self.last
        self.last = self.last.next
        self.last.previous = tmp
        self.n += 1
    
    def front(self):
        if self.n == 0: return None
        e = self.first.element
        self.first = self.first.next
        self.n -= 1
        return e
        
    def back(self):
        if self.n == 0: return None
        e = self.last.previous.element
        self.last = self.last.previous
        self.last.next = Node()
        self.n -= 1
        return e
        
    def size(self):
        return self.n
    
    def elements(self):
        i = self.first
        while i.element:
            yield i.element
            i = i.next
        
if __name__ == "__main__":
    l = LinkedList()
    
    assert None == l.front()
    assert None == l.back()
    
    l.append(1)
    l.append(2)
    l.append(3)
    
    assert 1 == l.front()
    assert 2 == l.front()
    assert 3 == l.front()

    l.append(1)
    l.append(2)
    l.append(3)
    
    assert 3 == l.back()
    assert 2 == l.back()
    assert 1 == l.back()

    l.append(1)
    assert 1 == l.back()
    
    l.append(1)
    assert 1 == l.front()

How to Implement Priority Queue in Python

Below a simple implementation of priority queue using binary heap.
#!/usr/bin/env python

class PriorityQueue(object):
    def __init__(self, compare=cmp):
        self.pq = []
        self.n = 0
        self.compare = compare
        
    def insert(self, element):
        self.swim(element)
        
    def remove(self):
        if self.n == 0: return None
        e = self.pq[0]
        self.sink()
        return e
    
    def elements(self):
        return [self.pq[i] for i in xrange(0, self.n)]
        
    def swim(self, element):
        self.n += 1
        if len(self.pq) >= self.n:
            self.pq[self.n-1] = element
        else:
            self.pq.append(element)
        
        current_pos = self.n
        parent_pos = current_pos / 2
        # python uses 0-based index, hence always minus the position by 1
        while (self.compare(self.pq[current_pos-1], self.pq[parent_pos-1]) > 0
               and current_pos > 1):
            self.pq[current_pos-1], self.pq[parent_pos-1] = (self.pq[parent_pos-1], 
                                                             self.pq[current_pos-1])
            current_pos = parent_pos
            parent_pos = current_pos / 2
        
    def sink(self):
        current_pos = 1
        # since it's a binary heap, a parent can only have max 2 children
        self.pq[current_pos-1] = self.pq[self.n-1]
        self.n -= 1
        child_pos = self.get_child_position(current_pos)
        if child_pos == -1: return
        
        while self.compare(self.pq[child_pos-1], self.pq[current_pos-1]) > 0:
            self.pq[child_pos-1], self.pq[current_pos-1] = (self.pq[current_pos-1],
                                                            self.pq[child_pos-1])
            current_pos = child_pos
            child_pos = self.get_child_position(current_pos)
            if child_pos == -1: break
    
    def get_child_position(self, current_pos):
        first_child_pos = 2 * current_pos
        second_child_pos = (2 * current_pos) + 1
        child_pos = -1 # no child
        # no child
        if first_child_pos > self.n: return child_pos
        # there's only one child
        if second_child_pos > self.n: child_pos = first_child_pos
        else: # there are two children
            if self.compare(self.pq[first_child_pos-1], self.pq[second_child_pos-1]) > 0:
                child_pos = first_child_pos
            else:
                child_pos = second_child_pos
        return child_pos
        
    def size(self):
        return self.n
    
def min_compare(x, y):
    if x < y: return 1
    elif x == y: return 0
    else: return -1
    
if __name__ == "__main__":
    pq = PriorityQueue()
    pq.insert(4)
    pq.insert(5)
    pq.insert(1)
    pq.insert(8)
    pq.insert(2)
    pq.insert(3)
    pq.insert(10)
    pq.insert(7)
    pq.insert(9)
    pq.insert(6)
    
    assert 10 == pq.remove()
    assert 9 == pq.remove()
    assert 8 == pq.remove()
    assert 7 == pq.remove()
    assert 6 == pq.remove()
    assert 5 == pq.remove()
    assert 4 == pq.remove()
    assert 3 == pq.remove()
    assert 2 == pq.remove()
    assert 1 == pq.remove()

    pq.insert(4)
    pq.insert(5)
    assert 5 == pq.remove()
    assert 4 == pq.remove()

    assert None == pq.remove()
    
    pq.insert(4)
    pq.insert(5)
    pq.insert(1)
    pq.insert(8)
    pq.insert(2)
    pq.insert(3)
    pq.insert(10)
    pq.insert(7)
    pq.insert(9)
    pq.insert(6)
    
    assert 10 == pq.remove()
    assert 9 == pq.remove()
    assert 8 == pq.remove()
    assert 7 == pq.remove()
    assert 6 == pq.remove()
    assert 5 == pq.remove()
    assert 4 == pq.remove()
    assert 3 == pq.remove()
    assert 2 == pq.remove()
    assert 1 == pq.remove()
    
    pq = PriorityQueue(min_compare)
    pq.insert(4)
    pq.insert(5)
    pq.insert(1)
    pq.insert(8)
    pq.insert(2)
    pq.insert(3)
    pq.insert(10)
    pq.insert(7)
    pq.insert(9)
    pq.insert(6)
    
    assert 1 == pq.remove()
    assert 2 == pq.remove()
    assert 3 == pq.remove()
    assert 4 == pq.remove()
    assert 5 == pq.remove()
    assert 6 == pq.remove()
    assert 7 == pq.remove()
    assert 8 == pq.remove()
    assert 9 == pq.remove()
    assert 10 == pq.remove()
    
    pq.insert(4)
    pq.insert(5)
    assert 4 == pq.remove()
    assert 5 == pq.remove()

    assert None == pq.remove()
    
    pq.insert(4)
    pq.insert(5)
    pq.insert(1)
    pq.insert(8)
    pq.insert(2)
    pq.insert(3)
    pq.insert(10)
    pq.insert(7)
    pq.insert(9)
    pq.insert(6)
    
    assert 1 == pq.remove()
    assert 2 == pq.remove()
    assert 3 == pq.remove()
    assert 4 == pq.remove()
    assert 5 == pq.remove()
    assert 6 == pq.remove()
    assert 7 == pq.remove()
    assert 8 == pq.remove()
    assert 9 == pq.remove()
    assert 10 == pq.remove()