Tuesday, August 18, 2015

Find minimum number of different type of dishes to be ordered

There are n persons and k different type of dishes. Each person has some preference for each dish. Either he likes it or not. We need to feed all people. Every person should get at least one dish of his choice. What is the minimum number of different type of dishes we can order? 

Input is n x k matrix boolean matrix.For each person a row represent his likes or not likes each row. 

n = 6 k = 7 
1 0 0 0 1 0 0 
1 0 0 0 0 1 0 
1 0 0 0 0 0 1 
0 1 0 0 1 0 0 
0 0 1 0 0 1 0 
0 0 0 1 0 0 1 

Output 
3 

Explanation 
Take dish number 5,6,7.


Update the dishes array with the input vector.
N(i) = (N(i) << 1) | V(i)
void updateDishes(vector<string> list, int **dishes)
{
  int index = 0;
  for (vector<string>::const_iterator i = list.begin(); i != list.end(); ++i)
  {
    *((*dishes)+index) = (*((*dishes)+index) << 1) | (stoi(*i) & 0x1);
    index++;
  }
}    
  
Read the input file and update the dishes array.
int *CreateArrayFromFile(string filename, int &totalDishes, int &totalPersons)
{

  int *num = NULL;
  string line;
  string buf; 
  ifstream inFile(filename);

  // Read line by line for processing
  while ( getline (inFile, line) )
 {

    // Tokenize the line
    stringstream ss(line);
    vector<string> tokens;

    // Store all the tokens in a vector
    while (ss >> buf)
      tokens.push_back(buf);

    // Allocate the memory for the dishes array
    if (NULL == num)
    {
      totalDishes = tokens.size();
      num = new int[totalDishes]();

#ifdef DEBUG
      for (int i=0; i<tokens.size(); i++)
        cout << i << ": " << num[i] << endl;
#endif

}

    // Update the dishes array with person's like/dislike
    updateDishes(tokens, &num);

#ifdef DEBUG
    for (int i=0; i<tokens.size(); i++)
      cout << i << ": " << num[i] << endl;
    
    printVector(tokens);
#endif
    
    totalPersons++;
  }

  // Return the updates dishes array 
  return num;
}
This counts the numbers of bits set in a given numbers. Its a very silly way of counting bits set :(
 int getOnesCount(int num)
{
  int count = 0;

  while(num)
  {
    count = count + (num & 0x1);
    num = num >> 1;
  }

  return count;
}   
  
It interartes over the range (1..2^n) where n is the total number of dishes and create sets which holds the same number of bits set. This data will be used to find all the possible combinations of the same number of bits set in the range.
void getCombinations(vector < vector <int> > &combinations, int totalDishes, int totalPersons)
{

  // Place holders for all the sets
  for (int i=0; i<totalDishes; i++)
  {
    combinations.push_back(vector <int>());
  }

  // Update the sets
  int end = (1 << totalDishes);
  for (int i=1; i<end; i++)
  {
    combinations[getOnesCount(i)-1].push_back(i);
  }

#ifdef DEBUG
  for (int i=0; i<combinations.size(); i++)
  {
    cout << "Vector " << i+1 << " : " ;
    for (vector<int>::iterator it = combinations[i].begin(); it != combinations[i].end(); ++it)
    {
      cout << *it << " ";
    }
    cout << endl;
  }
  cout << endl;
#endif
  
}    
  
Checks if the given combination (bits set in the given num) satisfies all the persons.
bool doesSatisfy(int *dishes, int num, int totalPersons)
{
  int satisfy = (1 << totalPersons) - 1;
  int result = 0;
  int index = 0;
  bool retval = false;
  
  while (num)
  {
    if (num & 0x1)
      result = result | *(dishes+index);

    index++;
    num = num >> 1;
  }

  if(result == satisfy)
    retval = true;

  return retval;
}    
  
This is our main function.
int findMinDishCount(int *dishes, int totalDishes, int totalPersons)
{
  int start = 0;
  int end = totalDishes - 1;
  int index = (int) ((end - start) / 2);
  int retval = -1;

  // Get the combinations with respect to the number of bits set
  vector < vector <int> > combinations;
  getCombinations(combinations, totalDishes, totalPersons);

 /*
  * Here we are using binary search tree traversal to select the numbers of dishes to
  * satisfy all the persons likes.
  */
  while (start != end)
  {
#ifdef DEBUG    
    cout << "[Start:" << start << "] [End:" << end << "]" << endl;
#endif
    index = (int) (start + ((end - start) / 2));
    
    bool foundMatch = false;

    for (vector<int>::iterator it = combinations[index].begin(); it != combinations[index].end(); ++it)
    {
#ifdef DEBUG      
      cout << "[" << index << "] (" << *it << ") ";
#endif
      if (doesSatisfy(dishes, *it, totalPersons) == true)
      {
        foundMatch = true;
        retval = index;
#ifdef DEBUG
        cout << "true" << endl;
#endif

        // If the combination satisfies all the persons likes, We do not need to check
        // with other combinations from the same set
        break;
      }
#ifdef DEBUG
      cout << "false" << endl;
#endif
    }
    
    if (foundMatch == true)
    {
      end = index;
    }
    else
    {
      if (start == end-1)
      {
        if (end == totalDishes - 1 && doesSatisfy(dishes, combinations[end][0], totalPersons) == true)
        {
          retval = end;
        }
        break;
      }
      start = index;
    }    
  }

  return retval + 1;
}    
  
Here is the helper/wrapper function.
int main(int argc, char **argv)
{
  int totalDishes = 0;
  int totalPersons = 0;
  int *dishes = NULL;

  cout << "Filename: " << argv[1] << endl;
  dishes = CreateArrayFromFile(argv[1], totalDishes, totalPersons);
  cout << "Total Dishes: " << totalDishes << endl;
  cout << "Total Persons: " << totalPersons << endl;
  
  cout << endl;
  printLikesDislikes(dishes, totalDishes, totalPersons);
  
  cout << endl;
  int minDishes = findMinDishCount(dishes, totalDishes, totalPersons);
  cout << "Minimun dishes to statisfy everyone: " << minDishes <<endl;
  
  return 0;
}  
  
Supportive hearders.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;    
  
These functions will be used to get the output in verbose mode.This will be useful in debugging.
void printVector(vector<string> list)
{
  for (vector<string>::const_iterator i = list.begin(); i != list.end(); ++i)
  {
    cout << "[" << *i << "] ";
  }
  cout << endl;
}
  
void printLikesDislikes(int *dishes, int totalDishes, int totalPersons)
{
  string heading = "------------";
  cout << "Dishes   :  ";
  for (int j=1; j<=totalDishes; j++)
  {
    cout << j << " ";
    heading = heading + "--";
  }
  cout << endl << heading << endl;
  
  for (int i=totalPersons-1; i>=0; i--)
  {
    string likeDislike = "";
    for (int j=0; j<totalDishes; j++)
    {
      int pos = 1 << i;
      likeDislike = likeDislike + " " + ((pos & *(dishes+j)) == 0 ? "0" : "1");
    }
    cout << "Person " << totalPersons - i << " : " << likeDislike << endl;
  }
}
  

Thursday, July 30, 2015

Write a function which does zig-zag traverse of binary tree and prints out nodes.

All the header files which are needed
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <stdexcept>
    
Brings all the named entities from std namespace into current declarative region
using namespace std;
    
This is the node structure we use to store the values and form the binary tree. For the simplicity, we use int data type to store the node data.
struct node {
  int val;
  struct node *left;
  struct node *right;
};

    
It prints the vector contents for debug purpose.
void printVector(vector<node *> list)
{
  for (vector<node *>::const_iterator i = list.begin(); i != list.end(); ++i)
  {
    if (NULL != *i)
      cout << "[" << (*i)->val << "] -> ";
    else
      cout << "[EMPTY] -> ";
  }
  cout << "NULL" << endl;
}

    
The input vector has all the nodes of a certain level (or depth) in the given tree, stored from left to right. This function is capable of printing either in the same order as the vector is created or in reverse order.
void printLevels(vector<node *>& level, int count, int forward)
{
  
  if (1 == forward) { // Print vector as it is
    for(vector<node *>::iterator it = level.begin(); it != level.end(); ++it) {
      if (*it)
        cout << (*it)->val << " ";
      else
        cout << "- "; // Empty Node
    }
  } else { // Print vector in reverse order
    for(vector<node *>::reverse_iterator it = level.rbegin(); it != level.rend(); ++it) {
      if (*it)
        cout << (*it)->val << " ";
      else
        cout << "- "; // Empty Node
    }
  }
  cout << endl;
}
    
The main function to trave level by level.
void traverse(node *binaryTree, bool ziczac)
{
  string zz = ziczac? "True":"False";
  cout << "ZicZac: [" << zz << "]" << endl;
  
  int count = 1;             // Initial count for the ROOT node (Level 1)
  int countNext = 0;         // Node count in the Next Level
  int forward = 1;           // Decides how to print the list
  vector<node *> nodeList;   // Store nodes level-by-level
  node *tmp = NULL;          // Store the node pointer temporarily 

  // Push the ROOT
  nodeList.push_back(binaryTree);
  
  while (0 != count) {
    // Print the nodes from the current level
    printLevels(nodeList, count, forward);
    
    // Iterate the nodes from current level and get the nodes from
    // the next level
    countNext = 0;
    for (int i=0; i<count;){
      tmp = nodeList.front();

      // Remove the node which is getting processed
      nodeList.erase(nodeList.begin());

      // Node is NULL. Don't count the NULL nodes
      if (NULL == tmp) {
        nodeList.push_back(NULL);
        nodeList.push_back(NULL);
      } else {
        i++;
      
        // Check the left child node
        if (tmp->left) {
          countNext++;
          
          // Push it to the list
          nodeList.push_back(tmp->left);
        } else {
          nodeList.push_back(NULL);
        }
        
        // Check the right child node
        if (tmp->right) {
          countNext++;
          
          // Push it to the list
          nodeList.push_back(tmp->right);
        } else {
          nodeList.push_back(NULL);
        }
      }
    }

    // update the current with the level count from the next level
    count = countNext;
    
    if (true == ziczac) {
      // Toggle the way the level is getting printed
      forward = (forward ^ 0x1) & 0x1;
    }
  }
}
    
Read the file with the following format,
('|' is the delimitor)
   1
   2|3
   4|5| |7
   8|9|0|1| | |2|3

and create the binary tree
node *createBinaryTreeFromFile(string filename)
{
  node *binaryTree = NULL;
  vector<node *> nodeList;
  vector<node *> childNodeList;
  vector<string> stringList;
  string line;
  
  try {

    // Open the given file
    ifstream inFile (filename);

    while ( getline (inFile, line) )
    {
      // First Line => ROOT node
      if (NULL == binaryTree) {
        binaryTree = new node;
        binaryTree->val = stoi(line);
        binaryTree->right = NULL;
        binaryTree->left = NULL;
        nodeList.push_back(binaryTree);
      } else {
        stringList.clear();
        string::size_type prev_pos = 0, pos = 0;
        // Split the line with '|' delimitor 
        while( (pos = line.find('|', pos)) != string::npos )
        {
          std::string substring( line.substr(prev_pos, pos-prev_pos) );
          stringList.push_back(substring);
          prev_pos = ++pos;
        }
        string substring( line.substr(prev_pos, pos-prev_pos) ); // Last word
        stringList.push_back(substring);

        // Create the binary tree here (level by level)
        vector<string>::iterator itStringList = stringList.begin();
        while (!nodeList.empty()) {
          
          if (itStringList >= stringList.end())
            break;

          if (NULL == *(nodeList.begin())) {
            itStringList = itStringList + 2;
          } else {
            // Left Node
            try{
              int val = stoi(*itStringList);
              node *tmp = new node;
              tmp->val = val;
              tmp->left = NULL;
              tmp->right = NULL;
              (*(nodeList.begin()))->left = tmp;
              itStringList++;
              nodeList.push_back(tmp);
            } catch (const invalid_argument& ia) {
              cerr << "Invalid argument: " << ia.what() << '\n';
              nodeList.push_back(NULL);
              itStringList++;
            }

            // Right Node
            try{
              int val = stoi(*itStringList);
              node *tmp = new node;
              tmp->val = val;
              tmp->left = NULL;
              tmp->right = NULL;
              (*(nodeList.begin()))->right = tmp;
              itStringList++;
              nodeList.push_back(tmp);
            } catch (const invalid_argument& ia) {
              cerr << "Invalid argument: " << ia.what() << '\n';
              nodeList.push_back(NULL);
              itStringList++;
            }
          }
          
          // Remove the node which is getting processed
          nodeList.erase(nodeList.begin());
        }
      }
    }
    inFile.close();
  } catch (ifstream::failure e) {
    cerr << e.what() << endl;
  }

  // Print the tree
  traverse(binaryTree, false);
  
  return binaryTree;
}
    
Everything starts from here,

int main(int argc, char** argv)
{
  node *binaryTree = createBinaryTreeFromFile(argv[1]);
  traverse(binaryTree, true);
  return 0;
}

Monday, July 6, 2015

Bash - Few shortcuts to make our life easier


Navigate the cursor inside the current command statement
Ctrl + a - Start of the command
Ctrl + e - End of the command
Ctrl + f - Move to the next character
Ctrl + b - Move to the previous character
Alt + right_arrow - End of the current word or the next word
Alt + left_arrow - Start of the current word or the previous word
                      
Delete
Ctrl + k - Delete from current cursor position to the end of the command
Ctrl + u - Delete from current cursor position to the start of the command
Ctrl + w - Delete one word before the cursor
Ctrl + h - Delete one character before the cursor (Backspace)
Ctrl + d - Delete the current character under the cursor
                      
Search History
Ctrl + r - Find the command with the phrase you type.It searches the
history as you type. For each consecutive hit "Ctrl + r", it finds the
next match in the history and moves to the start of the history.
!! - Repeat the last command
!xyz - Find the latest command starting with xyz from the history and run it
!xyz:p - Print the latest command starting with xyz from the history
!$ - Last argument of previous command
!* - All arguments of previous command
^abc^def - Replace abc with def in the previous command and run it
                      
Process
$$ - Gets the pid of the current bash/script
$! - Pid of the last background process
$? - Exit status of the last command
                      

Tuesday, June 16, 2015

Given a max-heap represented as an array, return the kth largest element without modifying the heap.


  Here are all the header files included to make the compilation successful.
 

    
#include <iostream>
#include <vector>
#include <stack>

#include <math.h>
using namespace std;
 

    
  This is how we heapify the given array of elements.
  

#define SWAP(x,y) \
  x = x ^ y;      \
  y = x ^ y;      \
  x = x ^ y;      \

void siftDown(vector<int> &v, int start, int end)
{
  int root = start;

  while (root*2+1 <= end){
    int child = root*2+1;
    int swap = root;

    if (child <= end && v[swap] < v[child]) {
      swap = child;
    }
    if(child+1 <= end && v[swap] < v[child+1]) {
      swap = child+1;
    }

    if (swap != root) {
      SWAP(v[root], v[swap]);
      root = swap;
    } else {
      return;
    }
  }
}

void heapify(vector<int> &v, int count)
{

  int start = floor((count-2)/2);

  while (start >=0 ) {
    siftDown(v, start, count-1);
    start = start - 1;
  }
}

 

    
  We modify the stack functionality a little to maintain the element order in the stack with the incoming elements.
  
void insertToStack(vector<int> &v, stack<int> &s, int val)
{
  /* Temporary vector to keep the order from the stack */
  vector<int> tmp;

  /* Pop the elements till new value finds its place */
  while(!s.empty() && v[s.top()] > v[val]){
    tmp.insert(tmp.begin(), s.top());
    s.pop();
  }

  /* push the new value into the stack */
  s.push(val);

  /* Push all the elements in the same order 
     which are previously popped out */
  vector<int>::iterator it;
  for (it=tmp.begin(); it<tmp.end(); it++) {
    s.push(*it);
  }
}

 
    
  This function traverses the heap to find the Kth element in log time
  
int find(vector<int> &v, stack<int> &s, int index, int pos, int count)
{
  /* If current element is smaller than the element in the stack,
     update the current element with the top of the stack and 
     push the current element into the stack*/
  if (!s.empty() && v[s.top()] > v[index]) {
    insertToStack(v, s, index);
    index = s.top();
  }

  if (pos == count) {
    /* If the count reaches pos, return the current element */
    return v[index];
  } else {
    int lchild = index*2+1;
    int rchild = lchild+1;

    /* Check if the current element has right child */
    if (rchild > v.size()-1) {
      
      /* Check if the current element has left child */
      if (lchild > v.size()-1) {
        
        /* The current element is the leaf node. Get the top of 
           the stack to proceed further */
        index = s.top();
        s.pop();
      } else {
        
        /* The current element has only left child. */
        if (s.empty() || v[lchild] > v[s.top()]) {
          index = lchild;
        } else {
          index = s.top();
          s.pop();
          insertToStack(v, s, lchild);
        }
      }
    } else {
      
      /* Find the max and min from the child nodes */
      int max = 0;
      int min = 0;
      if (v[lchild] > v[rchild]) {
        max = lchild;
        min = rchild;
      } else {
        min = lchild;
        max = rchild;
      }

      /* Find the highest element among the child nodes & the top
         of the stack, Update the current element with the highest 
         element and push the other two elements into the stack */
      if (s.empty()) {
        insertToStack(v, s, min);
        index = max;
      } else {
        int top = s.top();
        if (v[max] < v[top]) {
          index = top;
          s.pop();
          insertToStack(v, s, min);
          insertToStack(v, s, max);
        } else {
          index = max;
          if (v[min] > v[top]) {
            insertToStack(v, s, min);
          } else {
            s.pop();
            insertToStack(v, s, min);
            insertToStack(v, s, top);
          }
        }
      }
    }
    
    /* Call "find" recursively till "count" reaches "pos" */
    return find(v, s, index, pos, count+1);
  }
}

int findElement(vector<int> &v, int pos)
{
  /* Start with am empty stack */
  stack<int> s;
  return find(v, s, 0, pos, 1);
}
 
  You are NOT A FAN of recursion? Here you go,
 
@@ -1,5 +1,6 @@
 int find(vector<int> &v, stack<int> &s, int index, int pos, int count)
 {
+  while (count <= v.size()) {
   /* If current element is smaller than the element in the stack,
      update the current element with the top of the stack and 
      push the current element into the stack*/
@@ -74,8 +75,7 @@
         }
       }
     }
-    
-    /* Call "find" recursively till "count" reaches "pos" */
-    return find(v, s, index, pos, count+1);
+    }
+    count++:
   }
 }
 
  Here is the main function
    
int main(int argc, char **argv)
{

  /* Store the inputs into a vector */
  vector<int> input;
  int total= stoi(argv[1]);
  for(int c=0; c<total; c++){
    input.insert(input.end(), stoi(argv[c+2]));
  }

  /* Print them */
  vector<int>::iterator it;
  cout << "     my vector contains:";
  for (it=input.begin(); it<input.end(); it++)
    cout << ' ' << *it;
  cout << endl;

  /* Heapify the input vector */ 
  heapify(input, total);
  cout << "my heap vector contains:";
  for (it=input.begin(); it<input.end(); it++)
    cout << ' ' << *it;
  cout << endl << endl;

  for (int count=1; count<=total; count++) {
    int ret = findElement(input, count);
    cout << "(" << count << "):  " << ret << endl;
  }
  return 0;
}
Output:
$ ./kthInHeap 4 10 6 9 1
     my vector contains: 10 6 9 1
my heap vector contains: 10 6 9 1

(1):  10
(2):  9
(3):  6
(4):  1


$ ./kthInHeap 7 5 6 1 3 8 9 2
     my vector contains: 5 6 1 3 8 9 2
my heap vector contains: 9 8 5 3 6 1 2

(1):  9
(2):  8
(3):  6
(4):  5
(5):  3
(6):  2
(7):  1


$ ./kthInHeap 8 6 5 3 1 8 7 2 4
     my vector contains: 6 5 3 1 8 7 2 4
my heap vector contains: 8 6 7 4 5 3 2 1

(1):  8
(2):  7
(3):  6
(4):  5
(5):  4
(6):  3
(7):  2
(8):  1

Wednesday, June 10, 2015

Reconstruct the itinerary in order


Given an bunch of airline tickets with [from, to], for example [MUC, LHR], [CDG, MUC], [SFO, SJC], [LHR, SFO]
please reconstruct the itinerary in order, 
[ CDG, MUC, LHR, SFO, SJC ]. 
Note: tickets can be represented as nodes

#!/usr/bin/env python

import sys

# Reads the given file which contains airline tickets
# and returns 2 hash,
#  * (1) with all the ticket info
#  * (2) wth the starting and ending points
def getTicketsFromFile(filename):
    lines = []

    # Read the file
    with open(filename, "r") as fp:
        lines = lines = fp.readlines()

    lines = map(lambda s: s.strip(), lines)

    tickets = {}
    points = {}
    for line in lines:
        if line !="":
            point = map(lambda s: s.strip(), line[1:-1].split(","))
            tickets[point[0]] = point[1]

            # create 2 nodes for each ticket (start, end) and
            # do this for all the tickets
            for p in point:
                try:
                    # Delete the key from the points if it exists to find the start and end
                    # points for the entire trip.
                    del points[p]
                except:
                    points[p] = ""

    # Find the starting point
    for k in points.keys():
        if k in tickets.keys():
            startPoint = k
            break
        
    return (tickets, startPoint)


if __name__ == "__main__":
    (tickets, startPoint) = getTicketsFromFile(sys.argv[1])

    # print the order
    point = startPoint
    while True:
        print point,
        
        try:
            point = tickets[point]
        except:
            break

Thursday, June 4, 2015

Write a function that subtract two integer streams


You are given two streams 's_a' and 's_b' of digits. Each stream represents an integer 'a' and 'b' from its less significant digit to the most significant digit.
For example, integer 2048 is represented in the stream as 8, 4, 0, 2. 

Write a function that subtract two integers 'a - b' and returns the result as a string. You are not allowed to buffer entire 'a' or 'b' into a single string, i.e. you may access only a single digit per stream at time (imagine that 'a' and 'b' are stored in huge files). You may assume that 'a>=b'.

#include <stdio.h>

/* Subtracts two single digits, prints the reminder and returns 1(carry) if a<b */
int subtract(char c_a, char c_b)
{
  /* Convert the char to interger */
  int i_a = c_a - '0';
  int i_b = c_b - '0';
  int ret = 0;

  /* If a<b, increase 'a' by 10 and return 1(carry) to subtract it from 'a' of the next set */
  if (i_a < i_b) {
    i_a += 10;
    ret = 1;
  }
  
  printf ("%d", i_a - i_b);

  return ret;
}


int main(int agrc, char **argv)
{
  /* Get the two operand streams from input arguments */
  char *s_a = argv[1];
  char *s_b = argv[2];

  int carry_one = 0;
  
  /* Pass one char at a time from each input arguments to function subtract */
  while(*s_b != '\0'){
    /* Subtract carry_one from first operand before sending it to function subtract */
    carry_one = subtract(*s_a - carry_one, *s_b);
    s_a++;
    s_b++;
  }

  /* Print the remining digits from the first operand */
  while(*s_a != '\0'){
    printf("%c", *s_a - carry_one);
    s_a++;
    carry_one = 0;
  }
  printf("\n");
  
  return 0;
}
Output:
  $ ./str_subtract 00051 1005 | rev
  09999
  
  $ ./str_subtract 5 3 | rev
  2
  
  $ ./str_subtract 1234 1233 | rev
  1000

Tuesday, June 3, 2014

Find the conflicting appointments

#include <stdio.h>
#include <stdlib.h>

/* 
   Time interval format: yyymmddhhmm yyyymmddhhmm 

   Example Input:
   --------------
   4
   5 6
   1 9
   7 8
   2 10

   Process:
   --------

   Data Structure
   time_node to store the intervals
    ------------------------------
   | timestamp | is_start | index |
    ------------------------------

   Step 1:
   -------

   - stores the timestamps into an array
   
    -----------   -----------   -----------   -----------
   | 5 | 1 | 0 | | 6 | 0 | 0 | | 1 | 1 | 1 | | 9 | 0 | 1 |
    -----------   -----------   -----------   -----------
         0             1             2             3

    -----------   -----------   -----------   ------------
   | 7 | 1 | 2 | | 8 | 0 | 2 | | 2 | 1 | 3 | | 10 | 0 | 3 |
    -----------   -----------   -----------   ------------
         4             5             6              7

   Step 2:
   -------

   - Sort the array wrt the timestamp value

    -----------   -----------   -----------   -----------
   | 1 | 1 | 1 | | 2 | 1 | 3 | | 5 | 1 | 0 | | 6 | 0 | 0 |
    -----------   -----------   -----------   -----------
         0             1             2             3

    -----------   -----------   -----------   ------------
   | 7 | 1 | 2 | | 8 | 0 | 2 | | 9 | 0 | 1 | | 10 | 0 | 3 |
    -----------   -----------   -----------   ------------
         4             5             6              7
   
   Step 3:
   -------

     3.1 Push the index value to the index_list if it is the start of an interval
     3.2 Delete the index value from the index_list if it is the end of an interval
       3.2.1 add all the index values from the index_list to the conflict_list of the this interval
       3.2.2 add this interval index into the conflict_list of all the index values in the index_list
*/


/* Index to find parent and the childern */
#define LEFT(a) (2*(a+1) -1)
#define RIGHT(a) (2*(a+1))
#define PARENT(a) ((a-1)/2)

typedef enum boolean {
  FALSE = 0,
  TRUE = 1
} bool;

/* To store the calendar appointment intervals */
typedef struct time_node time_node;
struct time_node {
  unsigned long long timestamp;
  bool is_start;
  int index;
};

/* To store the conflicts */
typedef struct index_node index_node;
struct index_node {
  int index;
  index_node *next;
};

/* Swap function */
#define XORSWAP(a, b) ((a.timestamp)^=(b.timestamp),(b.timestamp)^=(a.timestamp),(a.timestamp)^=(b.timestamp), \
                         (a.is_start)^=(b.is_start),(b.is_start)^=(a.is_start),(a.is_start)^=(b.is_start), \
                         (a.index)^=(b.index),(b.index)^=(a.index),(a.index)^=(b.index))

/* Heapify */
void maxheapify (time_node *list, int count, int index)
{
  int left = LEFT (index);
  int right = RIGHT (index);
  
  int largest = index;
  
  if (left <= count-1 && list[left].timestamp > list[largest].timestamp)
    largest = left;
  if (right <= count-1 && list[right].timestamp > list[largest].timestamp)
    largest = right;
  
  if (largest != index)
  {
    XORSWAP (list[index], list[largest]);
    maxheapify (list, count, largest);
  }
}

/* Buids the heap */
void build_max_heap (time_node *list, int count)
{
  for (int i = (count-1)/2; i >= 0; i--)
  {
    maxheapify (list, count, i);
  }  
}

/* Sorts the intervals using heap sort */
void heap_sort (time_node *list, int count)
{
  build_max_heap (list, count);
  
  int tmp_count = count-1;
  for (int i = count-1; i > 0; i--)
  {
    XORSWAP (list[0], list[i]);
    maxheapify (list, i, 0);
  }
}

/* Adds the index node into the list */
bool add_index_node (index_node **list, int index)
{
  if (NULL == *list)
  {
    *list = (index_node *) calloc (1, sizeof (index_node));
    if (NULL == *list)
    {
      fprintf (stderr, "Error: memory allocation failure.");
      return FALSE;
    }
    else
    {
      (*list)->index = index;
      (*list)->next = NULL;
    }
  }
  else
  {
    index_node *t = *list;
    
    while (NULL != t->next)
      t = t->next;

    t->next = (index_node *) calloc (1, sizeof (index_node));
    t = t->next;

    if (NULL == t)
    {
      fprintf (stderr, "Error: memory allocation failure.");
      return FALSE;
    }
    else
    {
      t->index = index;
      t->next = NULL;
    }
  }
  return TRUE;
}

/* Deletes the index node from the list */
void delete_index_node (index_node **list, int index)
{
  if (NULL == *list)
  {
    return;
  }
  else
  {
    index_node *t = *list;
    index_node *lbo = *list;

    while (t->index != index)
    {
      if (t->next->next == NULL)
      {
        lbo = t;
      }
      t = t->next;
    }
    
    if (t == *list)
    {
      *list = (*list)->next;
      free (t);
    }
    else if (NULL == t->next)
    {
      lbo->next = NULL;
      free(t);
    }
    else
    {
      t->index = t->next->index;
      index_node *d = t->next;
      t->next = t->next->next;
      free (d);
    }
  }
}

int main (int argc, char **argv)
{
  time_node *interval_list = NULL;

  /* Reads the input file for the intervals */
  FILE *fp = NULL;
  fp = fopen ("intervals.txt", "r");
  if (NULL == fp)
  {
    fprintf (stderr, "Error: Could not read the file.");
    return -1;
  }

  int count = 0;
  int readcount = 0;
  int tmp_count = 0;
  
  /* Reads the count */
  readcount = fscanf (fp, "%d", &count);
  if (0 >= readcount)
  {
    fprintf (stderr, "Error: Nothing in the file.");
    return -2;
  }
  
  interval_list = (time_node *) calloc (count*2, sizeof (time_node));
  if (NULL == interval_list)
  {
    fprintf (stderr, "Error: Memory allocation failed.");
    return -3;
  }

  /* Reads the intervals */
  printf ("Input:\n");
  for(tmp_count = 0; tmp_count < count; tmp_count++)
  {
    if (feof(fp))
    {
      break;
    }
    unsigned long long start = 0;
    unsigned long long end = 0;
    readcount = fscanf (fp, "%llu %llu", &start, &end);
    printf ("%5d) : %llu <-> %llu\n", tmp_count+1, start, end);
    interval_list[tmp_count*2].timestamp = start;
    interval_list[tmp_count*2].is_start = TRUE;
    interval_list[tmp_count*2].index = tmp_count;
    interval_list[tmp_count*2+1].timestamp = end;
    interval_list[tmp_count*2+1].is_start = FALSE;
    interval_list[tmp_count*2+1].index = tmp_count;
  }
  printf ("\n");
  fclose(fp);

  /* Sort the timestamp values */
  heap_sort (interval_list, count*2);
  
  index_node *index_list = NULL;
  index_node **conflict_list = NULL;
  conflict_list = (index_node **) calloc (count, sizeof (index_node*));
  if (NULL == conflict_list)
  {
    fprintf (stderr, "Error: Memory allocation failed.");
    return -3;
  }

  /* main loop to find the conflicts */
  for (int i = 0; i < count*2; i++)
  {
    if (interval_list[i].is_start == TRUE)
    {
      if (FALSE == add_index_node (&index_list, interval_list[i].index))
      {
        fprintf (stderr, "Error: Memory allocation failed.");
        return -3;
      }
    }
    else
    {
      delete_index_node (&index_list, interval_list[i].index);

      index_node *t = index_list;
      while (t)
      {
        if (FALSE == add_index_node (&(conflict_list[interval_list[i].index]), t->index) || 
            FALSE == add_index_node (&(conflict_list[t->index]), interval_list[i].index))
        {
          fprintf (stderr, "Error: Memory allocation failed.");
          return -3;
        }
        t = t->next;
      }
    }
  }

  /* Print the result */
  printf ("Conflicts:\n");
  for (int i = 0; i < count; i++)
  {
    printf ("%5d : ", i+1);
    index_node *t = conflict_list[i];
    while (t)
    {
      printf ("%d ", t->index+1);
      t = t->next;
    }
    printf ("\n");
  }
  return 0;
}
We can use self-balanced binary search tree to keep the index_list to get a better time complexity.

Thursday, January 16, 2014

In a given 2D binary array, find the area of the biggest rectangle which is filled with 1



   Given array

   1 1 0 1 0 1
   1 1 0 1 1 1
   0 1 1 1 1 1
   0 1 1 1 1 1
   0 0 1 1 1 0
   0 0 0 0 0 0

   Consider each block in the array is an unit and he columns in the array as hanging towers.
   Modify the array in a way that, on each row, the number denotes the height of each column.


   1 1 0 1 0 1
   2 2 0 2 1 2
   0 3 1 3 2 3
   0 4 2 4 3 4
   0 0 3 5 4 0
   0 0 0 0 0 0


   Basic Rules to find the biggest rectangle:
   1. For any tower, the boundaries on each side will be decided by its smaller towers. It means
       that all the towers on each side till we find a smaller tower will be included for the calculation.
   2. Area for the subset equals to (the height of the smaller tower) X (no. of towers in the subset)

   Calculate the area of each subset for each level in the array from top to bottom.

   Level[0] [set 0]              Level[0] [set 1]              Level[0] [set 2]

   1 1 0 1 0 1                   1 1 0 1 0 1                   1 1 0 1 0 1
   ---                                 -                                 -
   2 towers with 1 unit each     1 tower with 1 unit           1 tower with 1 unit
   Maximum Area=2x1=2            Maximum Area=1x1=1            Maximum Area=1x1=1

   Level[0] Maximum Area = 2
   -------------------------------------------------------------------------------
   
   Level[1] [set 0]              Level[1] [set 1]

   2 2 0 2 1 2                   2 2 0 2 1 2
   ---                                 -----
   2 towers with 2 units each    1 tower with 1 unit
   Maximum Area=2x2=4            2 towers with 2 units each
                                 Maximum Area=3x1=3

   For [set 1], even though we have 2 towers with 2 units each in this set, we cannot consider them 
   as a single unit because of the smaller unit's presence in between. So, each tower will be consider 
   as a different subset. But, for the tower with 1 unit has bigger towers around it. So, all the units 
   will be taken (but only one unit from each bigger towers) for the area calculation.

   Level[0] Maximum Area = 4
   -------------------------------------------------------------------------------

   and so on...



int findBigBox (int row, int column, int *matrix)
{
  int max_area = 0;
  int *score = (int *) calloc (row+1, sizeof(int));
  if (NULL != score)
  {
    for (int i=0; i<row; i++)
    {
      for (int j=0; j<column; j++)
      {
        /* Process only if we find 1 */
        if (*(matrix+(i*column)+j) != 0)
        {
          int count = 0;
          int start = j;
          /* Iterate through all the consecutive ones. */
          for (;*(matrix+(i*column)+j) != 0 && j<column; j++)
          {
            /* If it is not the first row, add this element 
               with the previous row element at the same column */
            if (i != 0)
            {
              *(matrix+(i*column)+j) += *(matrix+((i-1)*column)+j);
            }
            *(score+*(matrix+(i*column)+j)) = 1;
          }
          
          getScore (row, column, start, j-1, matrix+(i*column), score);

          for (int s=1; s<=row; s++)
          {
            if (*(score+s))
            {
              int area = s * *(score+s);
              if (max_area < area)
                max_area = area;
            }
          }
          /* Reset the score array to use for the next subset */
          memset (score, 0, (row+1)*sizeof(int));
        }
      }
    }
  }
  free (score);
  
  return max_area;
}
Here the process of finding the number of towers on each subset for each height is call SCORE. This SCORE process can be represented as a tree, which has the following rules, 1. Node structure -> Height -> Score -> Next -> Left -> Right 2. Same numbers on the same set which are non-contiguous will be added as the [Next] node. 3. Same numbers on the same set which are contiguous will increment the [Score] in the first node. 4. Taller tower on its left in the set will be added to the [Left] node (child). 5. Taller tower on its right in the set will be added to the [Right] node (child). 6. [Score] = [Left]->[score] + [Right]->[score] + no of the same [Height] in the set. Example: For the below given set, 3 3 2 3 2 3 1 3 1 3 2 3 1. --------- 2. --------- 3. --------- | H=3|S=1 | | H=3|S=2 | | H=2|S=3 | --------- --------- --------- /L --------- | H=3|S=2 | --------- In the third step, we move the number 2 as the root and 3 as its left as 3 falls on 2's left in the set and 3 is bigger than 2. 4. --------- | H=2|S=4 | --------- /L \R --------- --------- | H=3|S=2 | | H=3|S=1 | --------- --------- We move the number 3 as its right as 3 falls on 2's right in the set 5. --------- N --------- | H=2|S=5 | ---- | H=2|S=0 | --------- --------- /L \R --------- --------- | H=3|S=2 | | H=3|S=1 | --------- --------- We move the number 2 to the [Next] of the existing 2 as they are on the same set still. (Which means it is the ROOT node) 6. --------- N --------- | H=2|S=6 | ---- | H=2|S=0 | --------- --------- /L \R \R --------- --------- --------- | H=3|S=2 | | H=3|S=1 | | H=3|S=1 | --------- --------- --------- This 3 falls on the right side of the second 2, and increase the count on the first 2 7. --------- | H=1|S=7 | --------- /L --------- N --------- | H=2|S=6 | ---- | H=2|S=0 | --------- --------- /L \R \R --------- --------- --------- | H=3|S=2 | | H=3|S=1 | | H=3|S=1 | --------- --------- --------- and so on... Finally, traverse the tree to find the Maximum SCORE for each height.
void getScore (int row, int column, int start, int end, int *matrix_row, int *score)
{
  /* Intervals to be processed to calculate the score for the number */
  int *currentQ = (int *) calloc (column, sizeof(int));
  /* Intervals to be updated for the next number */
  int *nextQ = (int *) calloc (column, sizeof(int));

  /* Interval counts */
  int currentCount = 1;
  int nextCount = 0;

  /* Start with the whole given set */
  currentQ[0] = start;
  currentQ[1] = end;

  for (int i=1; i<=row; i++)
  {
    if (*(score+i))
    {
      int max = 0;
      for (int c=0; c<currentCount; c++)
      {
        int tmp_score = *(currentQ+(c*2)+1) - *(currentQ+(c*2)) + 1;

        /* Update the temporary max */
        if (max < tmp_score)
        {
          max = tmp_score;
        }

        /* Update the intervals for the next bigger number */
        for (int k=*(currentQ+(c*2)); k<=*(currentQ+(c*2)+1); k++)
        {
          /* Find the start of an interval */
          while (*(matrix_row+k) == i && k<=*(currentQ+(c*2)+1))
          {
            k++;
          }
          
          /* End of the current set */
          if (k > *(currentQ+(c*2)+1))
            break;
          
          *(nextQ+(nextCount*2)) = k;

          /* Find the end of that interval */
          while (*(matrix_row+k) != i && k<=*(currentQ+(c*2)+1)) k++;

          if (k > *(currentQ+(c*2)+1)) // End of the current set
          {
            *(nextQ+(nextCount*2)+1) = k-1;
          }
          else
          {
            *(nextQ+(nextCount*2)+1) = k-1;
          }
          nextCount++;
        }
      }

      int *tmp = currentQ;
      currentQ = nextQ;
      nextQ = tmp;
      
      currentCount = nextCount;
      nextCount = 0;
    
      /* Update the score */
      *(score+i) = max;
    }
  }
}

Saturday, January 11, 2014

Number of ways decoding a message

A message containing letters from A-Z is being encoded to numbers using the following mapping:

‘A’ => 1
‘B’ => 2

‘Z’ => 26

Given an encoded message containing digits, determine the total number of ways to decode it.
For example, given encoded message “12″, it could be decoded as “AB” (1 2) or “L” (12). The number of ways decoding “12″ is 2.

Solution:
  1. Find all the subsets where we have 1 and 2 in the sequence continuously and keep the counts of total no of elements in each subset.
    • If the next element is 0 and count is more than 1, subtract the count by 1
    • Else increase the count by 1
  2. find the fibonacci number for each count [0]=1 [1]=1 [2]=2 [3]=3 ...
  3. Multiply all the fibonacci numbers gives the result
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>

int main (int argc, char **argv)
{
  int length = strlen(argv[1]);
  char *result = (char *) calloc (length + 1, sizeof (char));
  int noofways = 1;

  int *fibonacci = (int *) calloc (length, sizeof(int));
  *fibonacci = 1;
  *(fibonacci+1) = 2;

  for (int i=2; i<length; i++)
  {
    *(fibonacci+i) = *(fibonacci+i-1) + *(fibonacci+i-2);
  }

  for (int i=1; i<=26; i++)
  {
    printf ("[%c:%d] ", 'A'+i-1, i);
  }
  printf ("\n");


  char *input = argv[1];

  while (*input != '\0')
  {
    if (*input >= '1' && *input <='2')
    {
      int count = 0;
      for (;*input >= '1' && *input <='2'; input++, count++)
        ;
      if (*input != '\0')
      {
        if ((*(input-1) == '1' && *input >= '1' && *input <= '9') ||
            (*(input-1) == '2' && *input >= '1' && *input <= '6'))
        {        
          count++;
        }
        else if ((*(input-1) == '1' && *input == '0') ||
                 (*(input-1) == '2' && *input == '0'))
        {
          count--;
          if (count == 0)
            count = 1;
        }
      }
      else if (*input == '\0')
      {
        noofways = noofways * *(fibonacci+count-1);
        break;
      }
      noofways = noofways * *(fibonacci+count-1);
    }
    else if (*input == '0')
    {
      noofways = 0;
      break;
    }
    input++;
  }
  printf ("No of ways: %d\n", noofways);
  return 0;
}
Code to get all the decoded strings
Function call: {decode (input, result, 0);}
[input]   => Input String
[output] => Temporary buffer to form the decoded string
[index]   => Index to decoded character
typedef enum boolean { FALSE=0, TRUE=1}bool;

bool decode (char *input, char *output, int index)
{
  static int count = 0;
  if (*input == '\0')
  {
    *(output+index) = '\0';
    count++;
    printf ("%-4d%s\n", count, output);
    return TRUE;
  }
  else if (*input == '0')
  {
    return FALSE;
  }
  else if ((*input == '1' && *(input+1) == '0') ||
           (*input == '2' && *(input+1) == '0'))
  {
    *(output+index) = 'A' + ((*input - '0') * 10) - 1;
    return decode (input+2, output, index+1);
  }
  else
  {
    *(output+index) = 'A' + (*input - '1');
    decode (input+1, output, index+1);
    
    if ((*input == '1' && *(input+1) >= '1' && *(input+1) <= '9') ||
        (*input == '2' && *(input+1) >= '1' && *(input+1) <= '6'))
    {
      *(output+index) = 'A' + (*input - '0') * 10 + *(input+1) - '0' - 1;
      decode (input+2, output, index+1);
    }
  }

  return TRUE;
}

Friday, January 10, 2014

Largest Sum Subarray

You are given a binary array with N elements: d[0], d[1], ... d[N - 1].
d[i] can only be 0 or 1
You can perform AT MOST one move on the array: choose any two integers [L, R], and flip all the elements between (and including) the L-th and R-th bits. L and R represent the left-most and right-most index of the bits marking the boundaries of the segment which you have decided to flip.
What is the maximum number of '1'-bits (indicated by S) which you can obtain in the final bit-string?
import copy

def max_subarray(array):
    # Start & End indices of the max subarray 
    start = end = 0

    # Temporary Variable to hold the new Start
    t_start = 0

    # Holds the latest max sum
    # starts with array[0] because it addresses the 
    # case where all the elements in the array are
    # negative numbers.
    max_ending_here = max_so_far = array[0]

    # Holds the max subarray
    # Starts with the first element array[0]
    maxsubarray = t_maxsubarray = [array[0]]

    for index, x in enumerate(array[1:]):
        # max(x, max_ending_here + x) => max_ending_here
        if x > max_ending_here + x:
            # This is where the set starts
            t_start = index + 1
            t_maxsubarray = []
            max_ending_here = x
        else:
            max_ending_here = max_ending_here + x

        # max(max_so_far, max_ending_here) => max_so_far
        if max_so_far < max_ending_here:
            # The set ends here
            t_maxsubarray.append(x)
            # This is the latest max subarray
            maxsubarray = copy.deepcopy(t_maxsubarray)
            # Update the new Start index
            start = t_start
            # Update the new End index
            end = index + 1
            max_so_far = max_ending_here
        else:
            t_maxsubarray.append(x)

    print maxsubarray
    print start, end
    print max_so_far
Reference: [WIKI] Maximum Subarray Problem

Saturday, January 4, 2014

Spell Check

I am using self balanced binary search tree to create the dictionary because the hash values for the dictionary wordsEn.txt vary from few thousands to few thousands of millions. If I want to map this big range to small one, there may be more collision.

My hash function gives me same hash value for the strings even if the character are jumbled. For example, "add" and "dad" will have the same hash value. I collect the list of words which have the same has value as the given string and find how close these words to the given string. I sort these suggestions in the order where the closest possibility comes first.

To get more words, i repeat this with adding a character each time from 'a' to 'z' with the given string and one more time with removing the character from all the possible indices.
Finally print the list.

Filename: dictionary.hpp
#ifndef __MY_DICTIONARY__
#define __MY_DICTIONARY__

#include <iostream>
#include <string>
using namespace std;

typedef struct word t_word;

class wordlist {
private:
  string dictionaryfile;
  t_word *dictionary;

public:
  wordlist (string dictfile)
  {
    this->dictionaryfile = dictfile;
    this->dictionary = NULL;
  }

  wordlist()
  {
  }

  void setWordFile (string wordfile)
  {
    this->dictionaryfile = wordfile;
  }

  string getWordFile ()
  {
    return this->dictionaryfile;
  }

  ~wordlist ()
  {
  }

  bool generateDictionary ();
  unsigned int calcHash (string);
  t_word *create (string);
  void rotateLeft (t_word*);
  void rotateRight (t_word*);
  void balanceFactors (t_word*, t_word*);
  void balanceLeftRight (t_word*, t_word*);
  void balanceRightLeft (t_word*, t_word*);
  void balance (t_word*, t_word*);
  void insert (string);
  int getScore (string, string);
  int findMatch (string, vector<string>&);
};

#endif
Filename: dictionary.cpp
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <stdlib.h>

using namespace std;

#include "dictionary.hpp"

// Node to store the word and the corresponding hash values
struct word{
  string word;
  unsigned int hash;

  // Pointers to create the self-balanced binary search tree
  t_word *parent;
  t_word *left;
  t_word *right;
  char balanceFactor;
  
  // Pointer to store the words with the same hash value
  t_word *next;
};

// Generates the dictionary (self-balanced binary search tree)
// with the list of words from the given dictionary file.
bool wordlist::generateDictionary ()
{
  ifstream ifs (this->dictionaryfile.c_str());
  string str;
  
  try 
  {
    while (getline (ifs, str))
    {
      // Remove the new line 
      str.resize (str.length()-1);

      // Add the word into the dictionary
      insert (str);
    }
    ifs.close();
  } 
  catch (exception& e)
  {
    cerr << "[Error]: " << e.what() << endl;
    if (ifs.is_open())
    {
      ifs.close();
    }
    return false;
  }
  
  return true;
}

// Calculates the hash value for the given word
// Position of the characters does not have importance here.
unsigned int wordlist::calcHash (string word)
{
  unsigned int hash = 0;
  int val[26] = {0};
  const char *exp = word.c_str();
  while (('a' <= *exp && 
          'z' >= *exp) ||
         '\'' == *exp)
  {
    hash = hash + ((
                    (int(*exp) & 0x01) * 0xcf * 3+ 
                    (int(*exp) & 0x02) * 0xbf * 37+
                    (int(*exp) & 0x04) * 0xaf * 79+
                    (int(*exp) & 0x08) * 0x9f * 131+
                    (int(*exp) & 0x10) * 0x8f * 181+
                    (int(*exp) & 0x20) * 0x7f * 239+
                    (int(*exp) & 0x40) * 0x6f * 293+
                    (int(*exp) & 0x80) * 0x5f * 359) 
                   * (int (*exp) - int ('a') + 1) * 421 ) +
      (int (*exp) - int ('a') + 1) * 17;
      exp++;
  }
  hash += word.length();
  return hash;
}

// Create a new node with the given string and its has value
t_word* wordlist::create (string str)
{
  unsigned int hash = calcHash (str);
  t_word *t = new t_word;
  if (NULL == t)
  {
    cerr << "[Error] memory allocation failed." << endl;
    exit (1);
  }

  // cout << hash << " [" << str << "]" << endl;
  t->word = str;
  t->hash = hash;
  t->parent = NULL;
  t->left = NULL;
  t->right = NULL;
  t->next = NULL;
  t->balanceFactor = '=';
  
  return t;
}

void wordlist::rotateLeft (t_word *n)
{
  t_word *t = n->right;
  
  n->right = t->left;
  if (NULL != t->left)
  {
    t->left->parent = n;
  }
  
  if (NULL != n->parent)
  {
    if (n->parent->left == n)
    {
      n->parent->left = t;
    }
    else
    {
      n->parent->right = t;
    }
  }
  else
  {
    this->dictionary = t;
    t->parent = NULL;
  }
  t->left = n;
  t->parent = n->parent;
  n->parent = t;
}

void wordlist::rotateRight (t_word *n)
{
  t_word *t = n->left;
  
  if (NULL == n->left && NULL == n->right)
    return;
  
  n->left = t->right;
  if (NULL != t->right)
  {
    t->right->parent = n;
  }
  
  if (NULL != n->parent)
  {
    if (n->parent->left == n)
    {
      n->parent->left = t;
    }
    else
    {
      n->parent->right = t;
    }
  }
  else
  {
    this->dictionary = t;
    t->parent = NULL;
  }
  t->right = n;
  t->parent = n->parent;
  n->parent = t;
}

void wordlist::balanceFactors (t_word *ancestor, t_word *newLeaf)
{
  t_word *t = newLeaf->parent;
  while (t != NULL && t != ancestor)
  {
    if (newLeaf->hash <= t->hash)
      t->balanceFactor = 'L';
    else
      t->balanceFactor = 'R';
    
    t = t->parent;
  }
}

void wordlist::balanceLeftRight (t_word *ancestor, t_word *newLeaf)
{
  if (this->dictionary == ancestor)
  {
    ancestor->balanceFactor = '=';
  }
  else
  {
    t_word *t = ancestor;
    if (newLeaf->hash <= ancestor->parent->hash)
    {
      ancestor->balanceFactor = 'R';
      t = ancestor->parent->left;
    }
    else
    {
      ancestor->balanceFactor = '=';
      ancestor->parent->left->balanceFactor = 'L';
    }
    balanceFactors (t, newLeaf);
  }
}

void wordlist::balanceRightLeft (t_word *ancestor, t_word *newLeaf)
{
  if (this->dictionary == ancestor)
  {
    ancestor->balanceFactor = '=';
  }
  else
  {
    t_word *t = ancestor;
    if (newLeaf->hash > ancestor->parent->hash)
    {
      ancestor->balanceFactor = 'L';
      t = ancestor->parent->right;
    }
    else
    {
      ancestor->balanceFactor = '=';
      ancestor->parent->left->balanceFactor = 'R';
    }
    balanceFactors (t, newLeaf);
  }
}

void wordlist::balance (t_word *ancestor, t_word *newLeaf)
{
  // Balanced tree
  if (NULL == ancestor)
  {
    if (newLeaf->hash <= this->dictionary->hash)
    {
      this->dictionary->balanceFactor = 'L';
    }
    else
    {
      this->dictionary->balanceFactor = 'R';
    }
    balanceFactors (this->dictionary, newLeaf);
  }
  // Added to the other side of the balanced factor
  else if ((ancestor->balanceFactor == 'L' &&
            newLeaf->hash > ancestor->hash) ||
           (ancestor->balanceFactor == 'R' &&
            newLeaf->hash <= ancestor->hash))
  {
    ancestor->balanceFactor = '=';
    balanceFactors (ancestor, newLeaf);
  }
  // Added to the same side of the ancestor's child tree
  else if ((ancestor->balanceFactor == 'R' &&
            newLeaf->hash > ancestor->right->hash) ||
           (ancestor->balanceFactor == 'L' &&
            newLeaf->hash <= ancestor->left->hash))
  {
    char bf = ancestor->balanceFactor;
    ancestor->balanceFactor = '=';
    switch (bf)
    {
      case 'R':
        rotateLeft(ancestor);
        break;
      case 'L':
        rotateRight(ancestor);
        break;
    }
    balanceFactors (ancestor->parent, newLeaf);
  }
  // Added to the right of ancestor's left child
  else if (ancestor->balanceFactor == 'L' &&
           newLeaf->hash > ancestor->left->hash)
  {
    rotateLeft(ancestor->left);
    rotateRight(ancestor);
    balanceLeftRight (ancestor, newLeaf);
  }
  // Added to the left of ancestor's right child
  else if (ancestor->balanceFactor == 'R' &&
           newLeaf->hash <= ancestor->right->hash)
  {
    rotateRight(ancestor->right);
    rotateLeft(ancestor);
    balanceRightLeft (ancestor, newLeaf);
  }
  else
  {
    cerr << "[Error]: Not a valid operation." << endl;
    exit (1);
  }
}

void wordlist::insert (string str)
{
  t_word *t = create (str);
  t_word *ancestor = NULL;
  if (NULL == this->dictionary)
  {
    this->dictionary = t;
  }
  else
  {
    t_word *r = this->dictionary;
    while (NULL != r)
    {
      if (r->balanceFactor != '=')
        ancestor = r;
      
      if (t->hash < r->hash)
      {
        if (NULL != r->left)
        {
          r =r->left;
        }
        else
        {
          break;
        }
      }
      else if (t->hash > r->hash)
      {
        if (NULL != r->right)
        {
          r =r->right;
        }
        else
        {
          break;
        }
      }
      else
      {
        while (NULL != r->next)
          r = r->next;
        
        r->next = t;
        return;
      }
    }
    
    t->parent = r;
    
    if (t->hash <= r->hash)
    {
      r->left = t;
    }
    else
    {
      r->right = t;
    }

    // Balance the tree using AVL
    balance (ancestor, t);
  }
}

int wordlist::getScore (string s1, string s2)
{
  int i = 0;
  int j = 0;
  int len = s2.length() * s1.length();
  int *a_scores = new int [len];
  int score = 0;

  /*
  cout << "  ";
  for (i=0; i<s1.length(); i++)
  {
    cout << s1[i] << " ";
  }
  cout << endl;
  */

  for (j=0; j<s2.length(); j++)
  {
    // cout << s2[j] << " ";
    for (i=0; i<s1.length(); i++)
    {
      if (s1[i] == s2[j])
      {
        if (i == 0 || j == 0)
        {
          *(a_scores+(j*s1.length())+i) = 1;
        }
        else
        {
          int x = i-1;
          int y = j-1;
          int t_score = 0;
          for (;x>=0 && y>=0; x--,y--)
          {
            if (*(a_scores+(y*s1.length())+x) != 0)
            {
              t_score = *(a_scores+(y*s1.length())+x);
              break;
            }
          }
          for (x=i-1; x>=0; x--)
          {
            if (*(a_scores+(j*s1.length())+x) != 0)
            {
              if (t_score < *(a_scores+(j*s1.length())+x))
              {
                t_score = *(a_scores+(j*s1.length())+x) - 1;
              }
              break;
            }
          } 
          for (y=j-1; y>=0; y--)
          {
            if (*(a_scores+(y*s1.length())+i) != 0)
            {
              if (t_score < *(a_scores+(y*s1.length())+i))
              {
                t_score = *(a_scores+(y*s1.length())+i) - 1;
              }
              break;
            }
          }
          *(a_scores+(j*s1.length())+i) = t_score + 1;
        }
        if (score < *(a_scores+(j*s1.length())+i))
        {
          score = *(a_scores+(j*s1.length())+i);
        }
      }
      else
      {
        *(a_scores+(j*s1.length())+i) = 0;
      }
      // cout << *(a_scores+(j*s1.length())+i) << " ";
    }
    // cout << endl;
  }

  score = s1.length()-score;

  delete[] a_scores;

  return score;
}

int wordlist::findMatch (string str, vector<string>& result)
{
  unsigned int hash = calcHash(str);
  t_word *t = this->dictionary;
  unsigned int count = 0;
  unsigned int level = 0;

  while (NULL != t)
  {
    level ++;
    if (hash < t->hash)
    {
      t = t->left;
    }
    else if (hash > t->hash)
    {
      t = t->right;
    }
    else
    {
      while (NULL != t)
      {
        result.resize(count+1);
        result.at(count) = t->word;
        t = t->next;
        count++;
      }
      return level;
    }
  }

  return level;
}
Filename: spellCheck.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
#include <sstream>
#include <string>
#include <algorithm>

using namespace std;

#include "dictionary.hpp"

int main ()
{
  wordlist mydict ("wordsEn.txt");
  // My Dictionary
  mydict.generateDictionary ();

  string str;
  // My wordlist which are to be checked
  ifstream ifs ("wordlist.txt");
  while (getline (ifs, str))
  {
    str.resize (str.length()-1);

    vector <string> matches;
    int count  = mydict.findMatch (str, matches);
        
    if (0 < matches.size())
    { 
      for (long index=0; index < matches.size(); index++)
      {
        int score = mydict.getScore (str, matches.at(index));
        ostringstream ss;
        ss << setw(2) << setfill('0') << score;
        matches.at(index) = ss.str() + matches.at(index);

      }
      sort (matches.begin(), matches.end());
      string tmp = matches.at(0);

      // Exact match. Goto the next word in the list
      if ('0' == tmp[0] && '0' == tmp[1])
      {
        cout << "Spelling is CORRECT for (" <<  str << ")" <<endl;
        continue;
      }
    }

    // Add each character from 'a' to 'z' one by one and check if we 
    // get more suggesstions.
    string alpha = "abcdefghijklmnopqrstuvwxyz";
    vector<string> tmp_matches;
    
    for (int i=0; i<alpha.length(); i++)
    {
      mydict.findMatch (str+alpha[i], tmp_matches);
      for (long index=0; index < tmp_matches.size(); index++)
      {

        int score = mydict.getScore (str, tmp_matches.at(index));
        ostringstream ss;
        ss << setw(2) << setfill('0') << score + 1;
        matches.push_back(ss.str() + tmp_matches.at(index));
      }
      tmp_matches.clear();
    }
    
    // Check the suggesstions for the strings by removing one character 
    // in different index and try all the posible index values.
    for (int i=0; i<str.length(); i++)
    {
      string tmp_str = str;
      tmp_str.erase (i, 1);
      mydict.findMatch (tmp_str, tmp_matches);
      for (long index=0; index < tmp_matches.size(); index++)
      {
        int score = mydict.getScore (tmp_str, tmp_matches.at(index));
        ostringstream ss;
        ss << setw(2) << setfill('0') << score + 1;
        matches.push_back(ss.str() + tmp_matches.at(index));
      }
      tmp_matches.clear();
    }

    if (0 < matches.size())
    {
      // Sort all the suggesstions with thr rank
      sort (matches.begin(), matches.end());

      // Remove the rank element from the strings
      for (long index=0; index < matches.size(); index++)
      {
        matches.at(index).erase(0,2);
      }
    
      // Removes duplicate consecutive elements  
      // matches.erase( unique( matches.begin(), matches.end() ), matches.end() );
    
      // Remove all the duplicates
      vector<string> uniqueMatches;
      uniqueMatches.push_back(matches.at(0));
      for (long index=1; index < matches.size(); index++)
      {
        if (uniqueMatches.end() == find (uniqueMatches.begin(), uniqueMatches.end(), matches.at(index)))
        {
          uniqueMatches.push_back(matches.at(index));
        }
      }
    
      // Final result
      cout << "Matcing for (" << str << "): { ";
      for (long index=0; index < uniqueMatches.size(); index++)
      {
        cout <<uniqueMatches.at(index) << " ";
      }
      cout << "}" << endl;
    }
    else
    {
      cout << count << " Matche not found for (" << str << ")" << endl;
    }
  }

  return 0;
}
You can find the wordlist.txt from here

Friday, December 20, 2013

Find the longest palindrome substring

#include <stdio.h>
#include<string.h>
#include <stdlib.h>

/*************************************************************
 * Function    : addSpecialChar
 * Input       : str
 * Output      : newStr
 * Description : This function gets a character array and
 *               inserts # in between each character and
 *               returns the new character array.
 *               Input : abcdef
 *               Output: #a#b#c#d#e#f#
 ************************************************************/
char *addSpecialChar(char *str)
{
  int index = 0;
  char *newStr = (char *) calloc (2*strlen(str)+1, 
                                  sizeof(char));
  if (NULL == newStr)
  {
    fprintf(stderr, 
            "[%s:%d] Memory allocation failed.", 
            __FUNCTION__, __LINE__);
    return NULL;
  }

  while ('\0' != *str)
  {
    newStr[index++] = '#';
    newStr[index++] = *str;
    str++;
  }

  newStr[index++] = '#';
  newStr[index] = '\0';
  return newStr;
}

/*************************************************************
 * Function    : getScore
 * Input       : str, score
 * Output      : maxScore
 * Description : This function calculates the number of 
 *               symmetric characters around each character
 *               in the given string and updates the score
 *               array. It returns the index of the max score
 *               from the score array.
 *               Input : #   a   #   a   #   b   #   c   #   b   #   a   #   
 *               Output: 0   1   2   1   0   1   0   5   0   1   0   1   0
 ************************************************************/
int getScore (char *str, int **score)
{
  int index = 1;
  int maxIndex = 0;
  int maxScore = 0;

  **score = 0;

  while ('\0' != str[index])
  {
    int leftindex = index - 1;
    int rightindex = index + 1;

    /* Calculate the score */
    int tmpScore = 0;
    for (;; leftindex--, rightindex++)
    {
      if (str[leftindex] != str[rightindex])
      {
        break;
      }
      if (leftindex == 0)
      {
        tmpScore++;
        break;
      }
      tmpScore++;
    }

    *((*score)+index) = tmpScore;
    if (maxScore < tmpScore)
    {
      maxScore = tmpScore;
      maxIndex = index;
    }

    /* The score on the left should be identical to the right
     * if the score at the new index is less than the difference
     * between score on the axis (current index) and the offset
     */
    int newIndex = 1;
    for (; newIndex < tmpScore; newIndex++)
    {
      if (*((*score)+index-newIndex) < *((*score)+index)-newIndex)
      {
        *((*score)+index+newIndex) = *((*score)+index-newIndex);
      }
      else
      {
        break;
      }
    }
    index = index + newIndex;

  }

  printf ("Max Index [%d]\n", maxIndex);
  return maxIndex;
}

int main (int agrc, char **argv)
{

  int *score = NULL;
  char *newStr = addSpecialChar (argv[1]);

  if (NULL != newStr)
  {
    score = (int *) calloc (strlen(newStr), sizeof (int));
    if (NULL == score)
    {
      fprintf(stderr, 
              "[%s:%d] Memory allocation failed.", 
              __FUNCTION__, __LINE__);
    }

    /* Print the actual string */
    printf ("%s\n%s\n", argv[1], newStr);

    int maxIndex = getScore (newStr, &score);

    /* Print the new string */
    for (int i=0; i<strlen(newStr); i++)
    {
      printf ("%-4c", newStr[i]); 
    }
    printf ("\n");

    /* Print the scores */
    for (int i=0; i<strlen(newStr); i++)
    {
      printf ("%-4d", score[i]); 
    }
    printf ("\n");

    /* Here is the longest palindrome */
    printf ("Longest Palindrome: ");
    int i = maxIndex/2 - score[maxIndex]/2;
    for (; i <= maxIndex/2 + score[maxIndex]/2; i++)
    {
      printf ("%c", argv[1][i]);
    }
    printf("\n");
  }

  return 0;
}
Output:
[COMMAND] ===>   ./logestPalindrome aabcba
aabcba
#a#a#b#c#b#a#
Max Index [7]
#   a   #   a   #   b   #   c   #   b   #   a   #   
0   1   2   1   0   1   0   5   0   1   0   1   0   
Longest Palindrome: abcba
-----------------------------------------------------------------------
[COMMAND] ===>   ./logestPalindrome aabcbabcbabcba
aabcbabcbabcba
#a#a#b#c#b#a#b#c#b#a#b#c#b#a#
Max Index [15]
#   a   #   a   #   b   #   c   #   b   #   a   #   b   #   c   #   b   #   a   #   b   #   c   #   b   #   a   #   
0   1   2   1   0   1   0   5   0   1   0   9   0   1   0   13  0   1   0   9   0   1   0   5   0   1   0   1   0   
Longest Palindrome: abcbabcbabcba
-----------------------------------------------------------------------
[COMMAND] ===>   ./logestPalindrome aabcbabcbaccba
aabcbabcbaccba
#a#a#b#c#b#a#b#c#b#a#c#c#b#a#
Max Index [11]
#   a   #   a   #   b   #   c   #   b   #   a   #   b   #   c   #   b   #   a   #   c   #   c   #   b   #   a   #   
0   1   2   1   0   1   0   5   0   1   0   9   0   1   0   5   0   1   0   1   0   1   2   1   0   1   0   1   0   
Longest Palindrome: abcbabcba
-----------------------------------------------------------------------
[COMMAND] ===>   ./logestPalindrome babcbabcbaccba
babcbabcbaccba
#b#a#b#c#b#a#b#c#b#a#c#c#b#a#
Max Index [11]
#   b   #   a   #   b   #   c   #   b   #   a   #   b   #   c   #   b   #   a   #   c   #   c   #   b   #   a   #   
0   1   0   3   0   1   0   7   0   1   0   9   0   1   0   5   0   1   0   1   0   1   2   1   0   1   0   1   0   
Longest Palindrome: abcbabcba
-----------------------------------------------------------------------
[COMMAND] ===>   ./logestPalindrome aaaaaaaaaaaaaaa
aaaaaaaaaaaaaaa
#a#a#a#a#a#a#a#a#a#a#a#a#a#a#a#
Max Index [15]
#   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   
0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  14  13  12  11  10  9   8   7   6   5   4   3   2   1   0   
Longest Palindrome: aaaaaaaaaaaaaaa
-----------------------------------------------------------------------
[COMMAND] ===>   ./logestPalindrome aaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaa
#a#a#a#a#a#a#a#a#a#a#a#a#a#a#a#a#
Max Index [16]
#   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   a   #   
0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  15  14  13  12  11  10  9   8   7   6   5   4   3   2   1   0   
Longest Palindrome: aaaaaaaaaaaaaaaa
-----------------------------------------------------------------------
[COMMAND] ===>   ./logestPalindrome a
a
#a#
Max Index [1]
#   a   #   
0   1   0   
Longest Palindrome: a
Reference: http://leetcode.com/2011/11/longest-palindromic-substring-part-i.html

Tuesday, December 17, 2013

[BASH SCRIPTING] Get exit status on the piped process

#!/bin/bash

function logging() {
  while read line; do
    echo "{$(date +'%Y-%m-%d %H:%M:%S')} $line"
  done
}

function stdintoexitstatus() {
  read exitstatus
  return $exitstatus
}

cmds=(
    "cal"
    "cal lkjhsd"
)
for i in $(seq 0 $((${#cmds[@]}-1)))
do
    echo "--------------------------------------------------------"
    echo "[COMMAND] ${cmds[$i]}"
    echo "--------------------------------------------------------"
   ((((eval ${cmds[$i]} 2>&1; echo $? >&3) | logging >&4) 3>&1) | stdintoexitstatus) 4>&1
    echo "Exit Status[$?]"
    echo
done

COMMAND:  eval ${cmds[$i]} 2>&1
The output and the error messages of the eval are redirected to stdout

COMMAND:   echo $? >&3
The status of the eval is stored in the file descriptor 3

COMMAND:   | logging >&4
The (output/error)stdout from eval is piped to logging function where we do logging
and the output of the logging function is stored in file descriptor 4

COMMAND:   3>&1 | stdintoexitstatus
Get the status of eval from file descriptor 3 and update $?

COMMAND:   4>&1
Get the output of the logging function from file descriptor 4 and redirect them to stdout

Reference: http://unix.stackexchange.com/questions/14270/get-exit-status-of-process-thats-piped-to-another

Wednesday, August 14, 2013

Associative Arrays in Bash

#!/bin/bash

# -A declares v to be an associative array
# [key]=vlaue
declare -A v
v=(
    ["var1"]="variable 01"
    ["var2"]="variable 02"
    ["var3"]="variable 03"
    ["var4"]="variable 01"
)

# ${!v[@]} gives us the keys
# to access the value use ${v[key]}
for k in ${!v[@]}
do
    echo "v: [$k] => [${v[$k]}]"
done


# key can have spaces
declare -A vws
vws=(
    ["var 1"]="variable 01"
    ["var 2"]="variable 02"
)

echo "vsw: [var 1] => [${vws['var 1']}]"
echo "vsw: [var 2] => [${vws['var 2']}]"

Output:
v: [var1] => [variable 01]
v: [var3] => [variable 03]
v: [var2] => [variable 02]
v: [var4] => [variable 01]
vsw: [var 1] => [variable 01]
vsw: [var 2] => [variable 02]
Reference: http://www.linuxjournal.com/content/bash-associative-arrays

Thursday, January 17, 2013

Understanding Of U-Boot

  1. INTRODUCTION
    Exciting new embedded Linux devices are appearing at an amazing rate. Installing and booting Linux on these wildly varying boards is not possible without a good boot loader. That'swhere Das U-Boot, a Free Software universal boot loader, steps in.

    1. GENERAL BOOTING PROCESS

      BIOS: ( Basic Input/Output System )
      The BIOS has a firmware in the ROM of a PC. When the PC is powered up, the BIOS is the first program that runs.

      Note: The most fundamental and obvious difference between x86 boards and embedded systems based on PPC, ARM, and others is that the x86 board will ship with one or more layers of manufacturer-supplied "black box" firmware that helps you with power-on initialization and the task of loading the operating system out of secondary storage. This firmware takes the system from a cold start to a known, friendly software environment ready to run your operating system.

      The BIOS contains the following parts:
      • POST ( Power On Self Test ) - a computer's pre-boot sequence. Each time a PC initializes, the BIOS executes a series of tests collectively known as the POST. The test checks each of the primary areas of the system, including the motherboard, video system, drive system, and keyboard, and ensures that all components can be used safely. If a fault is detected, the POST reports it as an audible series of beeps or a hexadecimal code written to an I/O port.
      • The Setup Menu, that lets you set some parameters and lets you adjust the real time clock. Most modern BIOS versions let you set the boot order, the devices that BIOS checks for booting. These can be A (the first floppy disk), C (the first hard disk), CD-ROM and possibly other disks as well. The first device in the list will be tried first. Older BIOS-es have only one boot order: A, C. So the BIOS will try to boot from A first and if there is no diskette in the drive it tries to boot from C.
      • The boot sector loader. This loads the first 512-byte sector from the boot disk into RAM and jumps to it
        • The only thing it knows about disks is how to load the first 512-byte sector. Boot disk can be floppy diskette, hard disk or CD-ROM. The first sector of a boot disk ( If it is hard disk, the first sector is called MBR Master Boot Record ) can be loaded at address 0000:7C00. The last two bytes of the sector are checked for the values 0x55 and 0xAA, this as a rough sanity check. If these are OK, the BIOS jumps to the address 0000:7C00. If it is multi stage boot loader, the MBR program must move itself to an address that is different from 0000:7C00 as it is supposed to load a different boot sector from a partition to address 0000:7C00 and jump to that.
        • Modern BIOS versions can treat a certain file on a CD-ROM as a diskette image. They boot from a diskette by loading the first 512 bytes of the file to 0000:7C00 and jumping to it.
      • The BIOS interrupts. These are simple device drivers that programs can use to access the screen, the keyboard and disks. Boot loaders rely on them, But most operating systems do not (the Linux kernel does not use BIOS interrupts once it has been started). MSDOS does use BIOS interrupts.

      Boot Loader: A boot loader typically consists of three programs.
      • The boot loader can be only 512 bytes in size and is directly loaded by the BIOS at boot time. Because of the size restriction, it has to be written in assemble. A boot sector program cannot do everything you want a boot loader to do. Usually a boot sector program does one of the following things (not all three in one program)
        • Load another boot sector.
        • Load another boot sector.
        • Load the kernel directly.
      • The second stage program is the real boot program and loaded by the boot sector program and it does everything you expect the boot loader to do. It contains the following functions:
        • User interface. It is either a simple command line (old versions of LILO), a menu or both. It allows you to select any number of operating systems and to specify additional parameters to the operating system. The available options are specified by a configuration file. Modern versions of boot loaders can show their menu in a bitmap picture.
        • Operating system loader. loads the operating system into memory and runs it. Alternatively we can load another boot loader specific to another operating system and let it run. This is called chain loading.
      • The boot loader installer is not run when the system is booted, but it is used to install the boot loader and the second stage program onto the boot disk. These have to be stored in special locations, so they cannot be copied with cp. It performs the following tasks:
        • Install the boot sector. If the boot sector will be installed in the MBR of a hard disk or on a DOS file system, not all 512 bytes may be overwritten, but the partition table or the DOS parameter block must be preserved.
        • Tell the boot sector where the second stage boot loader is. Usually it writes one or more sector addresses into the boot loader.
        • Tell the second stage boot loader where all relevant information is (configuration, kernels). This is the case with LILO. LILO creates a map file that contains all relevant sector addresses and puts pointers to the map file in the boot sector and/or second stage boot loader.

    2. BOOT LOADER FOR EMBEDDED SYSTEMS

      It is small piece of software that executes soon after the system is on. In our Desktop Linux PC, BIOS performs various system initializations, once the power is on. Then, it executes the boot loader located in the MBR(master boot record). The boot loader then passes the information to the kernel and then executes the kernel.

      In an embedded system the role of the boot loader is more complicated since these systems do not have a BIOS to perform the initial system configuration. The low level initialization of microprocessors, memory controllers, and other board specific hardware varies from board to board and CPU to CPU. These initializations must be performed before a Linux kernel image can execute.

      At a minimum an embedded boot loader provides the following features:
      • Initializing the hardware, especially the memory controller.
      • Providing boot parameters for the Linux kernel.
      • Starting the Linux kernel.

      Additionally, most embedded boot loaders also provide extra features to simplify the development on the board:
      • Reading and writing arbitrary memory locations.
      • Uploading new binary images to the board's RAM via a serial line or Ethernet.
      • Copying binary images from RAM to FLASH memory.

      Note: MBR - The first sector of the harddrive is master boot record (MBR). It includes the harddrives boot code and partition table. The partition table contains the information about the partition layout of harddisk. The size of the MBR will be 512 bytes, as is the size of every sector on an x86 machines harddisk.

    3. U-BOOT

      U-Boot provides support for hundreds of embedded boards and a wide variety of CPUs including PowerPC, ARM, XScale, MIPS, Coldfire, NIOS, Microblaze, and x86. You can easily configure U-Boot to strike the right balance between a rich feature set and a small binary footprint.

  2. U-BOOT SOURCE CODE HIERARCHY

    |-- board Board dependent files
    |-- common Misc architecture independent functions
    |-- cpu CPU specific files
    |-- 74xx_7xx   Files specific to Freescale MPC74xx and 7xx CPUs
    |-- arm720t Files specific to ARM 720 CPUs
    |-- arm920t Files specific to ARM 920 CPUs
          |-- imx Files specific to Freescale MC9328 i.MX CPUs
          |-- s3c24x0   Files specific to Samsung S3C24X0 CPUs
    |-- arm925t Files specific to ARM 925 CPUs
    |-- arm926ejs Files specific to ARM 926 CPUs
    |-- at91rm9200 Files specific to Atmel AT91RM9200 CPUs
    |-- i386 Files specific to i386 CPUs
    |-- ixp Files specific to Intel XScale IXP CPUs
    |-- mcf52x2 Files specific to Freescale ColdFire MCF52x2 CPUs
    |-- mips Files specific to MIPS CPUs
    |-- mpc5xx Files specific to Freescale MPC5xx CPUs
    |-- mpc5xxx Files specific to Freescale MPC5xxx CPUs
    |-- mpc8xx Files specific to Freescale MPC8xx CPUs
    |-- mpc8220 Files specific to Freescale MPC8220 CPUs
    |-- mpc824x Files specific to Freescale MPC824x CPUs
    |-- mpc8260 Files specific to Freescale MPC8260 CPUs
    |-- mpc85xx Files specific to Freescale MPC85xx CPUs
    |-- nios Files specific to Altera NIOS CPUs
    |-- nios2 Files specific to Altera Nios-II CPUs
    |-- ppc4xx Files specific to IBM PowerPC 4xx CPUs
    |-- pxa Files specific to Intel XScale PXA CPUs
    |-- s3c44b0 Files specific to Samsung S3C44B0 CPUs
    |-- sa1100 Files specific to Intel StrongARM SA1100 CPUs
    |-- disk Code for disk drive partition handling
    |-- doc Documentation (don't expect too much)
    |-- drivers Commonly used device drivers
    |-- dtt Digital Thermometer and Thermostat drivers
    |-- examples Example code for standalone applications, etc.
    |-- include Header Files
    |-- lib_arm Files generic to ARM architecture
    |-- lib_generic Files generic to all architectures
    |-- lib_i386 Files generic to i386 architecture
    |-- lib_m68k Files generic to m68k architecture
    |-- lib_mips Files generic to MIPS architecture
    |-- lib_nios Files generic to NIOS architecture
    |-- lib_ppc Files generic to PowerPC architecture
    |-- net Networking code
    |-- post Power On Self Test
    |-- rtc Real Time Clock drivers
    |-- tools Tools to build S-Record or U-Boot images, etc.

  3. PREREQUISITES

    Before building and installing U-Boot you need a cross-development tool chain for your target architecture. Generally, the term tool chain means a C/C++ compiler, an assembler, a linker/loader, associated binary utilities and header files for a specific architecture, like PowerPC or ARM. Collectively these programs are called a tool chain.

    A cross-development tool chain executes on one CPU architecture, but generates binaries for a different architecture. In my case the host architecture is x86 while the target architecture is ARM and PowerPC. Sometimes this process is also referred to as cross-compiling.

    Using cross-development tools makes developing embedded systems using Linux as the host development workstation.

  4. CONFIGURING & BUILDING

    Building U-Boot for one of the supported platforms is straight forward and there are ready-to-use default configurations available. To setup a default configuration for a particular board, type the following commands in the shell prompt after untarring the u-Boot tarball.
    
    # cd 
    # make mrproper
    # make _config 
    
    Note: Here <board_name> is one the supported boards.

    Configuration depends on the combination of board and CPU type; all such information is kept in a configuration file "include/configs/<board_name>.h". You can fine tune the default configuration for your particular environment and board by editing this configuration file. This file contains several C-preprocessor #define macros that you can modify for your needs.

    Now to build the binary image, u-boot.bin, type the following
    
    # make all
    

    After a successful compilation, you should get some working U-Boot images.

    • "u-boot.bin" is a raw binary image
    • "u-boot" is an image in ELF binary format
    • "u-boot.srec" is in Motorola S-Record format

  5. U-BOOT CODE FLOW FOR OMAP5912OSK BOARD

    Starts here,
    Directory : cpu/arm926ejs/
    File : start.S [This asm file]
    • sets CPU to SVC32 mode ( value: 0xD3 )
    • relocates U-Boot to RAM
    • does CPU_init_crit
      • flush I/D caches
      • disables MMU & caches
    • configures SPSR
    • takes care of exception handling for interrupts
    • resets CPU
    • calls start_armboot function from 'lib_arm' directory.

    Directory : lib_arm
    File : board.c [This asm file]
    Function : start_armboot() calls from start.S of cpu/arm926ejs/
    'init_sequence' is an array of initializing functions to be called in an order. 
                init_fnc_t *init_sequence[] = {
                        cpu_init,               /* basic cpu dependent setup */
                        board_init,             /* basic board dependent setup */
                        interrupt_init,         /* set up exceptions */
                        env_init,               /* initialize environment */
                        init_baudrate,          /* initialize baud rate settings */
                        serial_init,            /* serial communications setup */
                        console_init_f,         /* stage 1 init of console */
                        display_banner,         /* say that we are here */
                        dram_init,              /* configure available RAM banks */
                        display_dram_config,
                #if defined(CONFIG_VCMA9)
                        checkboard,
                #endif
                        NULL,
                };
    Functions called from this start_armboot()

    • cpu_init() from cpu/arm926ejs/cpu.c
      • IRQ_STACK_START, FIQ_STACK_START are assigned for stack.
    • board_init() from board/omap5912osk/omap5912osk.c
      • arch_number = 234
      • boot_params = 0x10000100

    Functions called from board_init()

    • set_muxconf_reg() from board/omap5912osk/omap5912osk.c
      • FUNC_MUX_CTRL_0 - 0xFFFE1000
      • Functional multiplexing control 0 register
      Ref: OMAP5912_Technical_Reference_Guide.pdf – 454

    • peripheral_power_enable() from board/omap5912osk/omap5912osk.c
      • SOFT_REQ_REG - 0xFFFE0834
      • ULPD soft clock request register
      • value stored is 0x0200
      Ref: OMAP5912_Technical_Reference_Guide.pdf - 559

    • flash__init() from board/omap5912osk/omap5912osk.c
      • EMIFS_GlB_Config_REG - 0xFFFECC0C
      • EMIFS_CONFIG_REG
      • value stored is 0x0001
      Ref: OMAP5912_Technical_Reference_Guide.pdf - 157

    • ether__init() from board/omap5912osk/omap5912osk.c
      • 0xFFFECE08 - MPU Idle Enable Contol Register
        • ARM_IDLECT2
      • Enable clock for all the controllers, peripherals, etc.
      • all other register are for I2C configuration.
      • I2C1_CNT
      • - 0xfffb3818 - I2C1 Data Counter Register
      • I2C1_CON
      • - 0xfffb3824 - I2C1 Configuration Register
      • I2C1_SA
      • - 0xfffb382C - I2C1 Slave Address Register
      • I2C1_PSC
      • - 0xfffb3830 - I2C1 Clock Prescaler Register
      • I2C1_SCLL
      • - 0xfffb3834 - I2C1 SCL Low Timer Register
      • I2C1_SCLH
      • - 0xfffb3838 - I2C1 SCL High Timer Register
      Ref: OMAP5912_Technical_Reference_Guide.pdf - 1131

    • interrupt_init() from cpu/arm926ejs/interrupts.c
      • CFG_TIMERBASE - 0xFFFEC500
      • LOAD_TIM - 4
      • TIMER_LOAD_VAL - 0xFFFFFFFF
      • Registers:
        • 0xFFFEC504 - MPU_LOAD_TIMER1 (32 bit ) ( to use TIMER 1 )
          • value loaded is 0xFFFFFFFF
        • 0xFFFEC500 - MPU_CNTL_TIMER1 ( 32 bit )
          • value loaded is 0x3F - enabling all
        • 0xFFFEC508 - MPU_READ_TIMER1
          • value of the timer
      Ref: OMAP5912_Technical_Reference_Guide.pdf - 1032

    • env_init() from common
      depends on where it is located.
      • ./common/env_dataflash.c:70:int env_init(void)
      • ./common/env_eeprom.c:77:int env_init(void)
      • ./common/env_flash.c:99:int env_init(void)
      • ./common/env_flash.c:252:int env_init(void)
      • ./common/env_nowhere.c:58:int env_init(void)
      • ./common/env_nvram.c:137:int env_init (void)

    • init_baudrate() form ./lib_arm/board.c
      • check the environment variable starts with "baudrate"
      • if it is >0, load it in gd->bd->bi_baudrate
      • else load CONFIG_BAUDRATE from ./include/configs/omap5912osk.h

    • serial_init () from drivers/serial.c
      • get the clok_divisor
      • calls NS16550_init() from ./drivers/ns16550.c

    • console_init_f() from ./common/console.c
      • gd->have_console = 1

    • dram_init() from ./board/omap5912osk/omap5912osk.c
      • gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
      • gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
      • PHYS_SDRAM_1 from ./include/configs/omap5912osk.h

    • display_dram_config() from ./lib_arm/board.c
      • print the information about dram from gd->bd->bi_dram.

    • Note: If something wrong in these initialization, it goes into infinite loop. We have to restart the board.

    • flash_init() from board/omap5912osk/flash.c
      • get the information about the flash devices
      • set protection status for monitor and environment sectors.

    • mem_malloc_init() from lib_arm/board.c
      • initialize the memory area for malloc()

    • get IP Address and MAC Address

    • devices_init() from common/devices.c
      • Functions called from here
        • i2c_init
        • drv_lcd_init
        • drv_video_init
        • drv_keyboard_init
        • drv_logbuff_init
        • drv_system_init
        • drv_usbtty_init

    • console_init_r() from common/console.c
      • initialize console as a device

    • misc_init_r() from board/omap5912osk/omap5912osk.c
      • currently function is empty.

    • enable_interrupts () from cpu/arm926ejs/interrupts.c

    • main_loop() from common/main.c

  6. CONFIGURE U_BOOT FOR A NEW ARCHITECTURE

    If the system board that you have is not listed, then you will need to port U-Boot to your hardware platform. To do this, follow these steps:
    • Add a new configuration option for your board to the toplevel "Makefile" and to the "MAKEALL" script, using the existing entries as examples. Note that here and at many other places boards and other names are listed in alphabetical sort order. Please keep this order.
    • Create a new directory to hold your board specific code. Add any files you need. In your board directory, you will need at least the "Makefile", a "<board>.c", "flash.c" and "u-boot.lds".
    • Create a new configuration file "include/configs/<board>.h" for your board
    • If you're porting U-Boot to a new CPU, then also create a new directory to hold your CPU specific code. Add any files you need.
    • Run "make _config" with your new name.
    • Type "make", and you should get a working "u-boot.srec"(Motorola format) or “u-boot.bin” file to be installed on your target system.
    • Debug and solve any problems that might arise. [Of course, this last step is much harder than it sounds.]

  7. REFERENCES