Lunatic Server Solutions Interview Question for Developer Program Engineers


Country: United States
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
0
of 0 vote

i think this one is the toughest problem, no one in the community can solve this problem.

- Anonymous May 29, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

tl;dr.

- Anonymous May 30, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

I believe the answer to 1st input is 3. Below are sequence of events

PID TIME ALLOCATED BALANCE_MEM
2 0 30 70
3 0 70 0
4 0 <Killed> 0
2 2 <Killed> 30
3 2 30 0
1 3 <Killed> 0
## De-allocation events ##
3 3 100 100

So process 1, 2 and 4 gets killed. Now one may argue that, there is a de-allocation event also a time t=3. So we can very well de-allocate the memory first and then use that memory for PID 1(and i believe that is what a good memory manager must do). But PS states that if there are two events at the same instant of time, then the event with smaller PID is processes first. So hence i believe process 1 gets killed. Is my understanding correct ? If yes then below is the code for it. If not then we may need to tweak the below code a bit. The below implementation is a very loose one. My aim was not on performance but on implementing the logic.
The idea is simple.
1. Create a list of events sorted in chronological order. Only two kinds of events are possible. Allocation and deallocation
2. maintain a heap of free memory slots. For every allocation event look in to this heap to get the smallest free memory inside which the requested memory can fit in
3. For every de-allocation event, free all the memory allocated chunks by the process and merge any available adjacent free memory chunks to create a bigger free slot and then insert this in to heap.

Haven't tested the code much, so let me know if you find any bugs.

/*! ----------------------------------------------------------
 *
 *  \file       memory_manager.cc
 *
 *  \brief
 *
 *
 *  \details
 *      Simulating Best Fit Alogorithm of memory manager
 *
 *  \history
 *      05/29/12 03:00:52 PDT Created By Prakash S
 *
 *  ----------------------------------------------------------*/
#include<iostream>
#include<bitset>
#include<queue>
#include<list>
#include<map>
using namespace std;

class mem_chunk {
  private:
  public:
    mem_chunk(int, int, int);
    ~mem_chunk() {};
    void resize(int, int, int);
    int start_i;
    int end_i;
    int size;
};

mem_chunk::mem_chunk(int start, int end, int mem) :
                     start_i(start),
                     end_i(end),
                     size(mem) 
{
}

class compare {
  private:
  public:
    bool operator() (mem_chunk* &a, mem_chunk* &b) {
      if(a->size > b->size) {
        return(true);
      } else {
        return(false);
      }
    }
};

void
mem_chunk::resize(int start, int end, int mem)
{
  start_i = start;
  end_i = end;
  size = mem;
}

static void 
custom_radix(int a[][4], int N);
static void
swap(int a[][4], int , int);
static int 
process_events(int event_queue[][4], int N, int P, int max_event);
static int 
allocate(int pid, int mem, int N, 
             vector< list<mem_chunk*>* > &mem_per_process,
             priority_queue<mem_chunk*, vector<mem_chunk*>, compare> &free_memory_slots);
static void 
deallocate(int pid, int N,
           list<mem_chunk*>* &process_list, 
           priority_queue<mem_chunk*, vector<mem_chunk*>, compare> &free_memory_slots);
int main() {
  int event_queue[65][4] = {0};
  int temp;
  int N;
  cin >> N;
  int P;
  cin >> P;
  temp = P;
  int index = 0;
  while(temp--) {
    int pid, start, end, mem;
    cin >> pid >> start >> end >> mem;
    /* Allocate event */
    event_queue[index][0] = pid;
    event_queue[index][1] = start;
    event_queue[index][2] = mem;
    event_queue[index++][3] = 1;

    /* Deallocate event */
    event_queue[index][0] = pid;
    event_queue[index][1] = end;
    event_queue[index][2] = mem;
    event_queue[index++][3] = 0;
  }

  int R;
  cin >> R;
  temp = R;
  while(temp--) {
    int pid, start, mem;
    cin >> pid >> start >> mem;
    event_queue[index][0] = pid;
    event_queue[index][1] = start;
    event_queue[index][2] = mem;
    event_queue[index++][3] = 1;
  }
  custom_radix(event_queue, index);
  for(int i=0; i< index; i++) {
    for(int k=0; k<4; k++) {
      cout << event_queue[i][k] << " " ;
    }
    cout << endl;
  }
  cout << process_events(event_queue, N, P, index) << endl;
}

static void 
custom_radix(int a[][4], int N) {
  /*First in-place sort based on process id */
  int k;
  k=0;
  for(int i=0; i<N; i++) {
    for(int j=0; j<(N-i-1); j++) {
      if(a[j][k] > a[j+1][k]) {
        swap(a, j, j+1);
      }
    }
  }  

  /* Then in-place sort based on time */
  k=1;
  for(int i=0; i<N; i++) {
    for(int j=0; j<(N-i-1); j++) {
      if(a[j][k] > a[j+1][k]) {
        swap(a, j, j+1);
      }
    }
  }  
}

void 
swap(int a[][4], int j, int k) {
  int tmp[4];
  tmp[0] = a[j][0];
  tmp[1] = a[j][1];
  tmp[2] = a[j][2];
  tmp[3] = a[j][3];

  a[j][0] = a[k][0];
  a[j][1] = a[k][1];
  a[j][2] = a[k][2];
  a[j][3] = a[k][3];

  a[k][0] = tmp[0];
  a[k][1] = tmp[1];
  a[k][2] = tmp[2];
  a[k][3] = tmp[3];
}

static int 
process_events(int event_queue[][4], int N, int P, int max_event) {
  map<int, int> deleted_process;
  vector< list<mem_chunk*>* > mem_per_process(P);
  priority_queue<mem_chunk*, vector<mem_chunk*>, compare> free_memory_slots;

  for(int i=0; i<=P; i++) {
    mem_per_process[i] = new list<mem_chunk*>;
    deleted_process[i] = 0; 
  }
 
  mem_chunk *tmp_chunk = new mem_chunk(0, N-1, N);
  free_memory_slots.push(tmp_chunk);

  for(int i=0; i<max_event; i++) {
    if((deleted_process[event_queue[i][0]] != 1)) {
      if(event_queue[i][3] == 1) {
        /*Allocation event*/
        int status = allocate(event_queue[i][0] /*pid*/,
            event_queue[i][2] /*mem*/,
            N,
            mem_per_process,
            free_memory_slots);
        if(status == 0) {
          /* Unsuccsfull allocation */
          deleted_process[event_queue[i][0]] = 1;
        } 
      } else {
        /*De-allocation event*/
        deallocate(event_queue[i][0], N, mem_per_process[event_queue[i][0]], free_memory_slots);
      }
    }
  }

  int count;
  for(int i=0; i<=P; i++) {
    if(deleted_process[i] == 1) {
      count++;
    } 
  }
  return(count);
}

static int 
allocate(int pid, int mem, int N, 
             vector< list<mem_chunk*>* > &mem_per_process,
             priority_queue<mem_chunk*, vector<mem_chunk*>, compare> &free_memory_slots) {
  list<mem_chunk*> tmp_list;
  bool slot_found = false;
  if(free_memory_slots.empty()) {
    /* ran out of memory */
    deallocate(pid, N, mem_per_process[pid], free_memory_slots);
    return(0);
  }
  do
  {
    mem_chunk *tmp_chunk = free_memory_slots.top();
    free_memory_slots.pop();
    if(tmp_chunk->size >= mem) {
      /* Slot found */
      slot_found = true;
      mem_chunk* alloted_chunk = new mem_chunk(tmp_chunk->start_i, tmp_chunk->start_i+mem-1, mem);
      if(tmp_chunk->size == mem) {
      } else {
        mem_chunk* free_chunk = new mem_chunk(tmp_chunk->start_i+mem, tmp_chunk->end_i, tmp_chunk->size-mem);
        free_memory_slots.push(free_chunk);
      }
      mem_per_process[pid]->push_back(alloted_chunk);
      delete tmp_chunk;
    } else {
      tmp_list.push_back(tmp_chunk);
    }
  } while(!slot_found);

  if(!slot_found) {
    /* Time to terminate the process */
    deallocate(pid, N, mem_per_process[pid], free_memory_slots);
    return(0);
  } else {
    list<mem_chunk*>::iterator it;
    for(it=tmp_list.begin(); it!=tmp_list.end(); it++) {
      free_memory_slots.push(*it);
    }
    return(1);
  }
}

static void 
deallocate(int pid, int N,
           list<mem_chunk*>* &process_list, 
           priority_queue<mem_chunk*, vector<mem_chunk*>, compare> &free_memory_slots) {
  bitset<1000> mem_map;
  mem_map.set();
  mem_chunk *tmp_chunk;
  while(!free_memory_slots.empty()) {
    tmp_chunk=free_memory_slots.top();
    free_memory_slots.pop();
    for(int i= tmp_chunk->start_i; i<= tmp_chunk->end_i; i++) {
      mem_map[i] = 0;
    }
    delete tmp_chunk;
  }

  /*Deallocate the memory of process pid*/
  list<mem_chunk*>::iterator it;
  for(it=process_list->begin(); it!=process_list->end(); it++) {
    tmp_chunk=*it;
    for(int i= tmp_chunk->start_i; i<= tmp_chunk->end_i; i++) {
      mem_map[i] = 0;
    }
    delete tmp_chunk;
  }

  /*Create a new heap */
  bool free;
  int block_index = 0;
  if(mem_map[0] == 1) {
    free = false;
  } else {
    free = true;
  }
  for(int i=0; i<N-1; i++) {
    if(mem_map[i] != mem_map[i+1]) {
      /*Change of block*/
      if(mem_map[i] == 0) {
        /* End of free block */
        tmp_chunk = new mem_chunk(block_index, i, i-block_index+1);
        free_memory_slots.push(tmp_chunk);
        block_index = i+1;
      }
    }
  }
}

- Prakash May 30, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

hi prakash,
u've got marvelous coding skills.
Ur programming power is tremendous.
Heads off towards ur talent.
Can u help me to solve some programming problems.
If u r ready to help me than mail me at:
nehakothari492@yahoo.in
thanks

- neha kothari May 30, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

hello ,
i am using tc.
Whenever i compiles it, it gives me error.
Can u suggest me how could i compile the code.
I've not bitset, queue, list header files.
Can you send me the files.

- devendra June 23, 2012 | Flag


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More