Remove dups in sorted vector

rawpixel-600789-unsplash

To remove duplicates of an array, use a hash map and array elements as keys, then extract keys. This requires extra space for storing the hash and time. Following algorithm does not need any extra space and time.

The algorithm is uses 3 iterators and moves the duplicate elements at the start of vector and erases the rest of vector. Pseudo code given as follows:

  1. take iterator ​`​start` that points to beginning of vector.
  2. take another iterator `i` that points to next element to start.
  3. move  i to next index until elements are duplicate.
  4. replace start with next element and increase start pointer.
  5. at the end erase elements from start+1 to end from vector.
#include <iostream>  // std::cout 
#include <vector>   
#include <cstdlib>  // std::srand
#include <ctime>    // std::time

int main(){
 std::vector<int> v(100);
 std::srand(std::time(nullptr)); // use current time as seed for random generator
 
// generate 1000 random numbers between 0 to 99
 for(int i = 0; i < 1000; i++){
   int random_variable = std::rand()%100;
   v.push_back(random_variable);
   std::cout << random_variable << ' ';
 }

// sort
std::sort(v.begin(), v.end());


std::vector<int>::iterator start = v.begin();
std::vector<int>::iterator end = v.end();
auto i = start+1; // std::vector<int>::iterator i = start+1;
 while(i != end-1){
   if(*start == *i){
     i++;
   }else{
     start++;
     *start = *i;
   }
 }

v.erase(start+1, end);
 for(const auto & i:v) std::cout << i << ' ';
}

Quick Sort using iterators

Lately I have been experimenting various algorithms using std iterators and tried to implement quick sort algorithm using just iterators instead of passing on the vector by reference. Following is the implementation of the algorithm.

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

auto partition(std::vector<int>::iterator start, std::vector<int>::iterator end_it){
   auto partition_idx = start;
   for(auto i = start; i != end_it; i++){
     if(*i <= *end_it){
       std::iter_swap(i, partition_idx);
       partition_idx++;
     }
   }
   std::iter_swap(partition_idx, end_it);
   return partition_idx;
}

void quick_sort(std::vector<int>::iterator start, std::vector<int>::iterator end_it){
  int size = std::distance(start, end_it);
  if (size <= 1) return;
  auto partition_idx = partition(start, end_it);
  quick_sort(start, partition_idx-1);
  quick_sort(partition_idx, end_it);
}

int main(){
  std::vector<int> v{72, 23, 65, 53, 36, 90, 76, 50, 1, 20, 64, 18, 26, 39, 34, 91, 86, 21, 81, 7, 58, 27, 9, 61, 77, 2, 88, 70, 79, 3, 100, 44, 94, 51, 83, 48, 68, 13, 96, 30, 98, 24, 95, 67, 55, 8, 56, 19, 52, 85, 6, 69, 43, 16, 93, 74, 60, 41, 37, 84, 66, 99, 78, 57, 33, 14, 62, 35, 31, 46, 59, 38, 12, 92, 73, 25, 32, 22, 28, 63, 54, 97, 29, 47, 15, 40, 87, 80, 17, 71, 11, 4, 75, 89, 49, 10, 5, 45, 42, 82};
  quick_sort(v.begin(), v.end()-1); // one element before end
  for(const auto & i:v){
    std::cout << i << ' ';
  }
 return 0;
}

Count ones in binary representation

The task is to find ones in the binary representation of a number in given range. For an example: 1 is represented a 1 in binary so the number is 1’s in 1 is 1. Another example: 4 is represented as 100 in binary so number of 1’s in binary representation of 4 is 1.

In order to find 1’s in a very large range between 1 and 10,000,000 sounds complicated but can solved with following algorithm

#include <iostream>
#include <algorithm>
#include <cmath>

long long ccb(int col, int n) {
  double division = (n + 1) / double(2 << col);
  int sum = static_cast<int>(division);
  long long rest = std::max(0.0, (division - sum) * (2 << col) - (1 << col));
  return sum * (1 << col) + rest;
}

long long cab(int n) {
  long long bits = 0;
  for (int i = 0; i < 30; i++) {
  bits += ccb(i, n);
 }
 return bits;
}

long long countOnes(int left, int right) {
 return cab(right) - cab(left - 1);
}

Multiply large numbers as strings

This algorithm is very much like factorial. Multiplication of very large numbers represented as strings because they go out of the integer range.

#include <iostream>
#include <vector>
#include <string>
#include <sstream>

std::string multiply(std::string a, std::string b) {
  // take a vector of length 200 and initialize all of its elements to 0.
  std::vector<int> multiplication(200, 0); 

 int place = 0;
 for(int i = a.size() - 1 ; i >= 0; i--){
   int carry = 0;
   std::vector<int>::iterator it = multiplication.begin() + place;
   for(int j = b.size() - 1 ; j >= 0; j--){
     int a_element = a[i] - '0';
     int b_element = b[j] - '0';
     int prod = a_element*b_element + carry + *it;
     *it = prod % 10;
     carry = prod / 10;
     it++;
     while (carry){
       int current_carry = carry + *it;
       *it += current_carry % 10;
       it++;
       carry = current_carry / 10;
    }
  }
   place++;
 }

std::stringstream ss;
for(int i = multiplication.size(); i >= 0; i--){
 ss << multiplication[i];
}
 return ss.str();
}

Reverse a number

Algorithm for reversing the number is as follows:

#include <cmath> // for finding out the length of number
 
// find the length of the number to find out the highest power of 10
// then divide the number by 10 and take remainder to find digit 
// at the unit's place.
// multiply the digit with power of 10. repeat length times.
int reverse(int x) {
  int length = (int)log10(abs(x)); // magic formula to find length
  int reversed = 0;
  int remainder = 0;
  for(int i = length; i > 0 ; --i){
    remainder = x % 10;
    x = x / 10;
    reversed += remainder * pow(10, i);
  }
  reversed += x;
  return reversed;
 }

 

Factorial of a large number

Factorial of an integer is found by multiplying all the numbers starting from 1 up to the number. So factorial for 5 is 5! = 5 x 4 x 3 x 2 x 1 = 120.

A recursive algorithm for finding factorial is given as

int factorial(int num){
  return num > 1 ? : num * factorial(num - 1) : 1;
}

The issue is factorial quickly grows out of the range of int/double/float limit.

Example:

factorial of 100 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

factorial of 1000 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Following is program I wrote to find factorials and store them as strings instead of numbers.

#include <iostream> // for cout 
#include <vector> // used to store the numbers
#include <string> 
#include <sstream>

// method to multiply each number passed with each element 
// within the vector. If there is a carry, just add it to the next
// number. 
void multiply_vector(std::vector<int> & v, int multiply_num){
  int carry = 0;
  for(size_t i = 0; i < v.size(); i++){
    int prod = v[i] * multiply_num + carry;
    v[i] = prod % 10;
   carry = prod / 10;
 }

 while (carry)
 {
   int current_carry = carry % 10;
   v.push_back(current_carry);
   carry = carry / 10;
  }
}

// instead of recursion use loop and vector to store result 
// of multiplication
std::string factorial(int num){
   std::vector<int> factorial_digits;
   factorial_digits.push_back(1);
   for(int i = 2; i <= num; i++){
     multiply_vector(factorial_digits, i);
   }

// received the result in vector but need to reverse it..
  std::stringstream ss;
  for(int i = factorial_digits.size()-1; i >= 0; i--){
    ss << factorial_digits[i];
  }
  return ss.str();
}


int main(){
  // find factorial of 1000
  std::cout << factorial(1000) << '\n';
  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