Sublime Build System

{
"cmd": "g++ -std=c++17 \"${file}\" -o \"${file_path}/${file_base_name}\" && \"${file_path}/${file_base_name}\"",
   "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
   "working_dir": "${file_path}",
   "selector": "source.c, source.c++",
   "shell": true,
   "variants":
   [
    
     {
       "name": "Run",
      "cmd": "g++ -std=c++17 \"${file}\" -o \"${file_path}/${file_base_name}\" && \"${file_path}/${file_base_name}\""
     }
   ]
  }

Vector back inserter example + algorithm

The problem is pretty simple: there is a list of time ranges for meetings and need to show the meetings as continuous block in calendar.

70940aec3ea953621db1b8faf619a5ca_2

As per modern c++ I have used std::back_inserter_iterator for vector instead of passing vector by value or by reference. This approach is much cleaner, modern and saves a lot of copying of data compared to old style.

// i/p: [(0, 1), (3, 5), (4, 8), (10, 12), (9, 10)]
// o/p: [(0, 1), (3, 8), (9, 12)]

#include <iostream>
#include <vector>
#include <algorithm>

struct Meeting; // define meeting

using it = std::vector<Meeting>::iterator;
// use an back inserter iterator to pass as function argument instead
// of passing vector by reference or creating vector on heap
using bi = std::back_insert_iterator<std::vector<Meeting>>;

struct Meeting{
  int start_time, end_time;
  // default constructor
  Meeting() = default;
 // parameterized constructor
  Meeting(int start_time, int end_time):start_time{start_time},end_time{end_date}{}
  
  // override < operator used for sorting.
  bool operator <(const Meeting &other) const{
    return start_date < other.start_date;
  }

static void merge(it start, it finish, bi merged_meeting_bi){
  int start_time = start->start_time;
  int end_time = start->end_time;
  while(start < finish){
    start++;
    if(start->start_time > end_time){
      merged_meeting_bi = {start_time, end_time}; // create meeting using parameterized constructor
      start_time = start->start_time; 
      end_time = start->end_time;
    }else{
      end_time = std::max(start->end_time, end_time);
     }
   }
  }
};

int main(){
  std::vector<Meeting> meetings{{0, 1}, {3, 5}, {4, 8}, {10, 12}, {9, 10}};
  std::vector<Meeting> merged_meetings;
  auto bi = std::back_insert_iterator<std::vector<Meeting>>(merged_meetings);
  auto start = meetings.begin();
  auto finish = meetings.end();
  // sort by first time
  std::sort(start, finish);
  
for(const auto &meeting : meetings){
std::cout << meeting.start_time << ' ' << meeting.end_time << '\n';
}
Meeting::merge(start, finish, bi);

for(const auto & meeting: merged_meetings){
std::cout << meeting.start_time << ' ' << meeting.end_time << '\n';
}
return 0;
}

Dutch National Flag – Algorithm + TDD

640px-Flag_of_the_Netherlands.svg

The algorithm is pretty simple and achievable in O(n) time where n is the number of elements. Instead of using indexes, I am using 3 set of iterators and added bunch of test cases.

#include <gtest/gtest.h>
#include <algorithm> // random_shuffle
#include <vector>
#include <numeric> // accumulate

using it = std::vector<int>::iterator; // using typedef

void dnf(it less, it equal, it greater, int pivot){
  while(equal <= greater){
    if(*equal < pivot){
      std::iter_swap(less, equal);
      less++;
      equal++;
    }else if(*equal == pivot){
      equal++;
    }else{
      std::iter_swap(equal, greater);
      greater--;
    }
  }
}

TEST(RandomTest, dnfTest){
  std::vector<int> v{2, 2, 0, 1, 1, 0, 2, 1, 0, 1, 0, 1, 0, 2, 2};
  int pivot = 1;
  for(int i = 0; i < 1000; i++){
    dnf(v.begin(), v.begin(), v.end()-1, 1);
    std::string output = std::accumulate(std::next(v.begin()), v.end(), 
                               std::to_string(*v.begin()),
                               [](std::string s, int i){return s+= std::to_string(i);});

    EXPECT_EQ(output, "000001111122222");
  }
}

TEST(RandomTestTwoNumbers, dnfTest){
  std::vector<int> v{0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1};
  int pivot = 1;
  for(int i = 0; i < 1000; i++){
    dnf(v.begin(), v.begin(), v.end()-1, 1);
    std::string output = std::accumulate(std::next(v.begin()), v.end(), 
                               std::to_string(*v.begin()),
                               [](std::string s, int i){return s+= std::to_string(i);});

    EXPECT_EQ(output, "000000001111111");
  }
}

TEST(RandomTestTwoNumbersMidPivot, dnfTest){
  std::vector<int> v{0, 0, 0, 0,0,9,9,9,9,9,9,9,9};
  int pivot = 1;
  for(int i = 0; i < 1000; i++){
    dnf(v.begin(), v.begin(), v.end()-1, 1);
    std::string output = std::accumulate(std::next(v.begin()), v.end(), 
                               std::to_string(*v.begin()),
                               [](std::string s, int i){return s+= std::to_string(i);});

    EXPECT_EQ(output, "0000099999999");
  }
}

TEST(RandomTestTwoNumbersHighPivot, dnfTest){
  std::vector<int> v{0, 0, 0, 0,0,9,9,9,9,9,9,9,9};
  int pivot = 10;
  for(int i = 0; i < 1000; i++){
    dnf(v.begin(), v.begin(), v.end()-1, 1);
    std::string output = std::accumulate(std::next(v.begin()), v.end(), 
                               std::to_string(*v.begin()),
                               [](std::string s, int i){return s+= std::to_string(i);});

    EXPECT_EQ(output, "0000099999999");
  }
}

int main(int argc, char**argv, char**envArg)
{
    testing::InitGoogleTest(&argc, argv);
    return(RUN_ALL_TESTS());
}

Iterators – look and say sequence algorithm

Look and say sequence is fun little exercise.. here is the code

#include <iostream>
#include <vector>
#include <string>
#include <numeric>

std::string looknsay(int num){
  // initialize vector with vector of ints.
  // add default seed value to it [1].
  std::vector<std::vector<int>> look_n_say_seq{{1}};
  // iterate over until the number n is reached.
  for(int n = 0; n <= num; n++){
    auto latest_sequence = look_n_say_seq.back();
    std::vector<int> next_sequence;
   // keep a pair of iterators to move across the latest sequence from vector.
    auto i = latest_sequence.begin();
    auto j = latest_sequence.begin();
    while(i < latest_sequence.end()){
      for(;*i==*j && j < latest_sequence.end();++j){}
      // distance will give the count
      next_sequence.push_back(std::distance(i, j));
      // *i will give the actual number to iterate on
      next_sequence.push_back(*i);
      i = j;
    }
    // insert newly created sequence into the vector.
    look_n_say_seq.push_back(next_sequence);
  }
  auto latest_sequence = look_n_say_seq.back();
 // accumulate - join vector of ints to make string and return
  return std::accumulate(std::next(latest_sequence.begin()), 
                         latest_sequence.end(),
                          std::to_string(*latest_sequence.begin()),
                          [](std::string s, int i){return s += std::to_string(i);});
}
int main(){
  std::cout << looknsay(0) << '\n';
  std::cout << looknsay(1) << '\n'; // 11
  std::cout << looknsay(2) << '\n'; // 21
  std::cout << looknsay(3) << '\n'; // 1211
  std::cout << looknsay(4) << '\n'; // 111221
  std::cout << looknsay(5) << '\n'; // 312211
}

Implicit type conversion – tricky scenario

Here are some of the scenarios where the implicit  type conversion can be unintuitive  and tricky.

  • implicit conversion between int, float and bool
    #include <iostream>
    
    void print(char x){
      std::cout << "in the print method that has char arg\n";
    
    }
    
    void print(int x){
      std::cout << "in the print method that has int arg\n";
    }
    
    void print(bool x){
      std::cout << "in the print method that has bool arg\n";
    }
    
    int main(){
    int x =1;
    char ch = 'c';
    char * c = &ch;
    print(*c); // in the print method that has char arg
    print(*c+1); //in the print method that has int arg
    return 0;
    }

Quick Concepts Part 1 – Introduction to RDMA

ZCopy

This is the first post in a three post series on getting started. By the end of the getting started series my goal is to get you ready to start coding with a sample program that will demonstrate the performance benefits of RDMA. In this post I will review RDMA concepts in a simple minded way. Later I intend to come back and do more detailed posts on each concept.

What is RDMA

Image: Simple Minded View of RDMA

RDMA is Remote Dynamic Memory Access which is a way of moving buffers between two applications across a network. RDMA differs from traditional network interfaces because it bypasses the operating system. This allows programs that implement RDMA to have:

  1. The absolute lowest latency
  2. The highest throughput
  3. Smallest CPU footprint

How Can We Use It

To make use of RDMA we need to have a network interface card that implements an RDMA engine.

We call this an HCA…

View original post 912 more words