Given a list of n non repeating integer numbers L:=(x1,...,xn) develop an algorithm that decides if there are xi1, xi2, xi3 in L such that i1 is lower than i2, i2 is lower than i_3, xi1 is lower than xi3 and xi3 is lower than xi2. Only a yes-no answer is required.
The statement also suggest to use the "divide & conquer" strategy.
My try was the following:
I read the vector left to right
If the list changes from increasing to decreasing, then it is clear that the last read number is lower than the maximum of the currently read list. So if it is greater than the minimum of the current list we can stop.
If the list changes from decreasing to increasing, then I look for the first number m in the list which is a local minimum and it is lower than the last read number c. And then I look for a local maximum appearing after m which is greater than c.
If the list keeps increasing we do the same as in the previous step.
If the list keeps decreasing do nothing.
So the complexity is nlogn. I think the strategy is good, but an online judge rejected it. I don't know if it is due to a silly bug or because the strategy is indeed wrong.
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
bool solveCase();
bool increasingCase(map<int, int> & mins, map<int, int> & maxs,
pair<map<int, int>::iterator, bool> & lastMaxInserted,
const int & current);
void ignoreStuff();
int main() {
while (solveCase())
;
return 0;
}
bool solveCase() {
/*---Reading the number of children---*/
int N;
if (scanf("%d", &N) == EOF) {
return false;
}
/*---Used variables---*/
int globalMax;
int globalMin;
map<int, int> maxs;
map<int, int> mins;
int localMin;
int localMinPos;
bool increasing;
pair<map<int, int>::iterator, bool> lastMaxInserted;
int old;
int current;
/*-----Reading the first two children-----*/
/*--Reading the first children--*/
scanf("%d", &old);
globalMax = old;
globalMin = old;
/*--Reading the second children--*/
scanf("%d", ¤t);
if (current > old) { /*The sequence starts increasing*/
increasing = true;
globalMax = current;
localMin = old;
localMinPos = 0;
} else { /*The sequence starts decreasing*/
increasing = false;
globalMin = current;
lastMaxInserted = maxs.insert(pair<int, int>(old, 0));
}
old = current;
/*-----Reading the rest-----*/
for (int i = 2; i < N; i++) {
scanf("%d", ¤t); /*Reading a child*/
if (!increasing) { /*--The sequence was decreasing--*/
if (current < old) { /*The sequence keeps decreasing*/
globalMin = min(current, globalMin);
} else { /*The monotony changes*/
localMin = old;
localMinPos = i - 1;
if (increasingCase(mins, maxs, lastMaxInserted, current)) {
printf("ELEGIR OTRA\n");
ignoreStuff(); /*Ignoring the rest*/
return true;
}
increasing = true;
}
} else { /*--The sequence was increasing--*/
if (current > old) { /*The sequence keeps increasing*/
globalMax = max(current, globalMax);
if (increasingCase(mins, maxs, lastMaxInserted, current)) {
printf("ELEGIR OTRA\n");
ignoreStuff(); /*Ignoring the rest*/
return true;
}
} else { /*The monotony changes*/
if (current > globalMin) { /*Check if we can end*/
printf("ELEGIR OTRA\n");
ignoreStuff(); /*Ignoring the rest*/
return true;
} else {
globalMin = current;
/*Inserting the local minimum (saved somewhere)*/
map<int, int>::iterator minIter;
minIter = mins.lower_bound(localMin);
if (!mins.empty() && minIter != mins.begin()) {
/*The value is the minimum position of the local
* minimums lower than the current local minimum*/
minIter--;
mins.insert(pair<int, int>(localMin, minIter->second));
} else {
mins.insert(pair<int, int>(localMin, localMinPos));
}
/*Inserting the local maximum (old)*/
/*The value is the maximum position of the local
* maximums greater or equal than than the current
* local maximum (i.e. the position of the local
* maximum). The local maximums lower than the
* current maximum have incoherent values, but it
* doesn't matter...*/
lastMaxInserted = maxs.insert(pair<int, int>(old, i - 1));
increasing = false;
}
}
}
old = current;
}
printf("SIEMPRE PREMIO\n");
return true;
}
bool increasingCase(map<int, int> & mins, map<int, int> & maxs,
pair<map<int, int>::iterator, bool> & lastMaxInserted,
const int & current) {
if (!mins.empty()) {
/*--Getting the position of the first local minimum lower than current--*/
map<int, int>::iterator minIter;
minIter = mins.lower_bound(current);
if (minIter != mins.begin()) {
minIter--;
} else {
return false;
}
int minPos = minIter->second;
/*--Trying to get a good local maximum coming after the minimum--*/
if (!maxs.empty()) {
map<int, int>::iterator maxIter;
maxIter = maxs.upper_bound(current);
if (maxIter != maxs.end()) {
if (maxIter->first < lastMaxInserted.first->first) {
if (minPos > lastMaxInserted.first->second) {
return false;
}
} else {
if (minPos > maxIter->second) {
return false;
}
}
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
return true;
}
void ignoreStuff() {
char trash = getchar();
while (trash != '\n') {
trash = getchar();
}
}
Any idea?
Related
So I was doing a question on LeetCode...
Question:
Write an efficient algorithm that searches for a target value in an m x n integer matrix. The matrix has the following properties:
Integers in each row are sorted in ascending from left to right.
Integers in each column are sorted in ascending from top to bottom.
Example 1:
Input: matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
Output: true
Example 2:
Input: matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
Output: false
So first I attempted this question by regular brute force method:
Answer-1:
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int t) {
int i=0,j,I=matrix.size(),J,mj;
for(;i<I;i++)
{
j=0;J=matrix[i].size()-1;
mj=(j+J)/2;
while(j<=J)
{
if(matrix[i][mj]==t)
return true;
else if(matrix[i][mj]<t)
j=mj+1;
else
J=mj-1;
mj=(j+J)/2;
}
}
return false;
}
};
Then I decided to do it by idk Divide and Conquer ig...
Answer-2:
class Solution {
public:
bool VFinder(vector<vector<int>>& matrix, int hstart, int hend, int vstart, int vend, int ele)
{
if(vstart > vend || hstart > hend)
return false;
int mid = vstart;
int start = vstart;
int end = vend;
while(start<=end)
{
mid = (int)((start + end) / 2);
if (start == end)
{
if (matrix[mid][hstart] == ele)
{
return true;
}
else
{
return HFinder(matrix, hstart + 1, hend, vstart, mid, ele);
}
}
else
{if(matrix[mid][hstart] <ele && matrix[mid+1][hstart] > ele)
return HFinder(matrix, hstart+1, hend, vstart, mid,ele);
else if(matrix[mid][hstart] <ele)
start = mid+1;
else if(matrix[mid][hstart] >ele)
end = mid-1;
else if(matrix[mid][hstart] == ele)
return true;}
}
return false;
}
bool HFinder(vector<vector<int>>& matrix, int hstart, int hend, int vstart, int vend, int ele)
{
if(hstart > hend || vstart > vend)
return false;
int mid = hstart;
int start = hstart;
int end = hend;
while(start<=end)
{
mid = (int)((start + end) / 2);
if (start == end)
{
if (matrix[vstart][mid] == ele)
{
return true;
}
else
{
return VFinder(matrix, hstart, mid, vstart + 1, vend, ele);
}
}
else
{if(matrix[vstart][mid] <ele && matrix[vstart][mid+1] > ele)
return VFinder(matrix, hstart, mid, vstart+1, vend, ele);
else if(matrix[vstart][mid] <ele)
start = mid+1;
else if(matrix[vstart][mid] >ele)
end = mid-1;
else if(matrix[vstart][mid] == ele)
return true;}
}
return false;
}
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int horizontal = matrix[0].size();
int vertical = matrix.size();
return HFinder(matrix, 0, horizontal-1, 0, vertical-1, target);
}
};
So the first code after submission took about : 328 ms
And the second one took about : 488 ms
But in second one, I am after each step reducing the search space, so it should have taken less time as compared to the first code, but it is not happening so.
Can someone please tell me why is it so?
And also what is the time complexity of the second code?
The objective is to return true if the sum can be made by adding up elements from a given vector. The vector elements maybe used and reused in any order.
Example:
sum = 7, list = [4,5]
return false because you can't use these list elements to make 7
sum = 9 or 5 or 20 or 8, list = [4,5]
return true because 9 = 4+5, 5 is in list already, 20 = 5+5+5+5, 8 = 4 + 4
I do not know why canSum is not returning anything. When targetSum reaches 0, canSum should return true, and then in memo we emplace (remainder, true). However, the program is not returning anything. Why is that?
#include <iostream>
#include <vector>
#include <map>
using namespace std;
bool canSum(int targetSum, vector<int> &vec, map<int, bool> &memo) {
int remainder;
if (memo[targetSum] == true)
return true;
else if (targetSum == 0)
return true;
else if (targetSum < 0)
return false;
else
for (auto i : vec) {
remainder = targetSum - i;
if (canSum(remainder, vec, memo)) {
memo.emplace(remainder, true);
return true;
}
}
memo.emplace(remainder, false);
return false;
}
int main() {
vector<int> vector1{7, 14};
int sum = 300;
map<int, bool> memo;
if (canSum(sum, vector1, memo))
cout << "true";
else
cout << "false";
}
The problem in your code is the way you handle the storing of sates in your memo table. You store only when the result is desired in the for loop and same problem is while returning using the memo table. So, the states which result in false are not stored in your memo until the complete recursive call ends and you are out of the loop. So, your recursion keeps on calculating the same states again and again. Your logic is correct but dynamic programming integration in recursive code is not proper. Your code will give an output, you just need to wait for a long time even for a small input. Below I have explained the above mentioned problems in detail.
You return from memo only if the result is true i.e. the if condition:
...
if(memo[remainder] == true)
return true;
...
is the problem. We use dynamic programming to save the result of a state that has been calculated so that if we come across the same problem in future, we don't have to recalculate it and we can return its result from saved memo table to avoid going into recursion again. We return the result from memo table irrespective of the result. But here you are returning only if the result was true. You should instead use this:
...
if (memo.find(targetSum)!=memo.end())
return memo[targetSum];
...
This is also the problem while you are storing the results in the memo table in the for loop. The if condition in the for loop:
for (auto i : vec) {
remainder = targetSum - i;
if (canSum(remainder, vec, memo)) {
memo.emplace(remainder, true);
return true;
}
}
is the problem. We store the result in the memo table irrespective of our desired result.
Here is the complete code with both problems fixed.
#include <iostream>
#include <vector>
#include <map>
using namespace std;
bool canSum(int targetSum, vector<int> &vec, map<int, bool> &memo) {
int remainder;
if (memo.find(targetSum)!=memo.end())
return memo[targetSum];
else if (targetSum == 0)
return true;
else if (targetSum < 0)
return false;
else{
bool ans = false;
for (auto i : vec) {
remainder = targetSum - i;
ans = ans || canSum(remainder, vec, memo);
if (ans) {
memo.emplace(targetSum, true);
return true;
}
}
memo.emplace(targetSum, false);
}
return false;
}
int main() {
vector<int> vector1{7, 14};
int sum = 300;
map<int, bool> memo;
if (canSum(sum, vector1, memo))
cout << "true";
else
cout << "false";
}
This is the answer to your question "I do not know why canSum is not returning anything."
Now, in general one should not use recursive DP as it is too much time consuming and iterative DP is best suited for competitive programming problems.
I think this code is from the freecodecamp video. I have solved the same question like below. Here, 0 means false and 1 means true. I hope you'll understand:
#include<bits/stdc++.h>
using namespace std;
vector<int>memo(1000,10);
bool canSum(int n, vector<int>v){
if(n==0){
return true;
}
if(n<0) return false;
if(memo[n]==1) return true;
if(memo[n]==0) return false;
for(int i = 0; i<v.size(); i++){
int rmndr = n-v[i];
bool x = canSum(rmndr,v);
if(x){
memo[n] = 1;
return true;
}
else{
memo[n] = 0;
}
}
return false;
}
int main() {
int n,x;
cin>>x;
vector<int>v(x);
for(int i = 0; i<v.size(); i++){
cin>>v[i];
}
cin>>n;
if(canSum(n,v)) cout<<"true"<<endl;
else cout<<"false"<<endl;
return 0;
}
This is what you are looking for
#include <vector>
#include <unordered_map>
using namespace std;
bool canSum(int target, vector<int> arr,unordered_map<int,bool> &mp){
if(target == 0)
return true;
if(target < 0)
return false;
if(mp.find(target)!=mp.end())
return mp[target];
for(auto x:arr){
int rem = target - x;
if(canSum(rem,arr,mp) == true){
mp[target] = true;
return true;
}
}
mp[target] = false;
return false;
}
int main(){
int target = 300;
unordered_map<int,bool> mp;
vector <int> arr = {7,14};
cout<<canSum(target,arr,mp);
return 0;
}```
// memoization for the canSum problem
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
bool canSum(int targetSum, vector <int> &numbers, unordered_map <int,int> &memo) {
int key = targetSum;
if(targetSum == 0) return true;
if(targetSum < 0) return false;
if(memo.find(key) != memo.end()) return memo[key]; // to avoid duplicate subtree calculations
else {
for(auto x:numbers) {
int rem = targetSum - x;
if( canSum(rem, numbers, memo) == true) {
memo[key] = true;
return true;
}
}
memo[key] = false;
return false;
}
}
int main() {
unordered_map <int,int> mp1;
unordered_map <int,int> mp2;
unordered_map <int,int> mp3;
unordered_map <int,int> mp4;
unordered_map <int,int> mp5;
vector <int> nums{2,3};
vector <int> nums1{7,14};
vector <int> nums2{5,3,4,7};
vector <int> nums3{2,4};
vector <int> nums4{2,3,5};
cout<<canSum(7,nums,mp1)<<"\n";
cout<<canSum(7,nums2,mp2)<<"\n";
cout<<canSum(7,nums3,mp3)<<"\n";
cout<<canSum(8,nums4,mp4)<<"\n";
cout<<canSum(300,nums1,mp5)<<"\n";
return 0;
}
Output of the code: 1 stands for 'true' and 0 stands for 'false'
I am working on a discrete event simulation program in C++. My output is completely incorrect but all the output values are pretty close to the correct output. I have tried debugging my algorithm but I couldn't find any errors. Below is my main algorithm for the simulation.
I implemented the event priority queue using a min heap and array. I am not allowed to use any STL libraries. The FIFO queue used in the code is a linked list. When I print the event time at the top of the priority queue, the events are not always getting passed in ascending order (which I think is how event priority queues are supposed to work) and I do not understand why. The ascending order is breached mostly around event completion times. Please help!
#include <iostream>
#include <fstream>
#include "PQueue.h"
#include "SPqueue.h"
#include "LinkedList.h"
using namespace std;
int serverCount; //number of servers
Spqueue spq; //priority queue for servers
Pqueue pq; //priority queue for events
LinkedList list; //FIFO queue to put arriving events in
double totalTime; //variables for statistics calculation
double timeNow;
double totalWait;
int ql;
int qlength = 0;
double totalQlength;
int time = 0;
bool available(); //checks availability of servers
int main() {
ifstream fin;
fin.open("Sample2.txt");
if (!fin.good())
cerr << "Couldn't find file/corrupted file" << endl;
fin >> serverCount; //reads number of servers and efficiency
//from file
for (int i = 0; i < serverCount; i++) {
server s;
fin >> s.effi;
s.status = true;
s.count = 0;
spq.insert(s);
}
//reads first event from file
event e;
fin >> e.eventTime;
fin >> e.serviceTime;
e.eventType = -1;
pq.insert(e);
int i = 1;
//while priority queue is not empty
while (!pq.isEmpty()) {
timeNow = pq.getArrivalTime(1);
while (time < pq.getArrivalTime(1)) {
totalQlength = totalQlength + list.getLength();
time++;
}
//get event from priority queue
if (pq.getServer(1) == -1) { //if arrival event, add to FIFO queue
list.AddTail(pq.getArrivalTime(1), pq.getServiceTime());
if (list.getLength() > qlength) {
qlength = list.getLength();
}
//read next arrival event from file
if (!fin.eof()) {
event e;
fin >> e.eventTime;
fin >> e.serviceTime;
e.eventType = -1;
pq.insert(e);
i++;
}
}
else //must be customer complete event
{
spq.setIdle(pq.getServer(1)); //set the server to idle
}
pq.deleteMin(); //remove the evnt from priority queue
//if FIFO queue is not empty and servers are available
//process event
if ((list.isEmpty() == false) && (available() == true)) {
list.getHead();
int s = spq.getMin();
spq.setBusy(s); //set server to busy
spq.incrementCustNumber(s); //increment number of customers
//served
double waitTime = timeNow - list.getHead().arrivalTime;
totalWait = totalWait + waitTime;
double serviceT = spq.getEffi(s) * list.getHead().serviceTime;
double eventT = list.getHead().arrivalTime +serviceT;
event e2;
e2.eventTime = eventT;
e2.serviceTime = list.getHead().serviceTime;
e2.eventType = s;
pq.insert(e2); //add customer complete event to the priority
//queue
list.RemoveHead(); //remove head from FIFO
}
totalTime = pq.getArrivalTime(1);
}
fin.close();
return 0;
}
bool available() {
bool ava = false;
for (int i = 1; i <= serverCount; i++) {
if (spq.getStatus(i) == true) {
ava = true;
break;
}
}
return ava;
}
Below is the priority queue implementation:
#include <iostream>
#include <fstream>
#include "PQueue.h"
using namespace std;
Pqueue::Pqueue() {
inde = 0; //length of heap
}
void Pqueue::insert(event i) { //inserts new element into the heap array and maintains min heap property
inde++;
pqueue[inde] = i;
siftup(inde);
}
int Pqueue::getServer(int i) {
return pqueue[i].eventType;
}
void Pqueue::siftup(int i) { //shifts element up to the correct position in the heap
if (i == 1)
return;
int p = i / 2;
if (pqueue[p].eventTime > pqueue[i].eventTime)
{
swap(pqueue[i], pqueue[p]);
siftup(p);
}
}
void Pqueue::deleteMin() { //removes element at the root of the heap
swap(pqueue[inde], pqueue[1]);
inde--;
siftdown(1);
}
void Pqueue::siftdown(int i) { //shifts element to its position in the min heap
int c = i * 2;
int c2 = (i * 2) + 1;
if (c > inde) return;
int in = i;
if (pqueue[i].eventTime > pqueue[c].eventTime)
{
in = c;
}
if ((c2 < inde) && (pqueue[i].eventTime > pqueue[c2].eventTime))
{
in = c2;
}
if (pqueue[c].eventTime < pqueue[c2].eventTime) {
in = c;
}
if (in != i) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}
}
void Pqueue::swap(event& i, event& j) {
event temp;
temp = i;
i = j;
j = temp;
}
bool Pqueue::isEmpty() { //checks if the priority queue is empty
if (inde == 0) return true;
else
return false;
}
double Pqueue::getArrivalTime(int i) {
return pqueue[i].eventTime;
}
double Pqueue::getServiceTime() {
return pqueue[1].serviceTime;
}
There are five servers with varying efficiency. The most efficient idle server is to be used. For this, I sorted the array of servers efficiency wise in the beginning.
#include <iostream>
#include <fstream>
#include "SPqueue.h"
using namespace std;
Spqueue::Spqueue() {
inde = 0;
}
void Spqueue::insert(server i) { //inserts new element into the array
inde++;
spqueue[inde] = i;
}
void Spqueue::heapify(int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2 * i; // left = 2*i + 1
int r = 2 * i +1; // right = 2*i + 2
// If left child is larger than root
if (l < n && spqueue[l].effi > spqueue[largest].effi)
largest = l;
// If right child is larger than largest so far
if (r < n && spqueue[r].effi > spqueue[largest].effi)
largest = r;
// If largest is not root
if (largest != i)
{
swap(spqueue[i], spqueue[largest]);
// Recursively heapify the affected sub-tree
heapify(n, largest);
}
}
void Spqueue::heapSort()
{
// Build heap (rearrange array)
for (int i = inde / 2 - 1; i > 0; i--)
heapify(inde, i);
// One by one extract an element from heap
for (int i = inde - 1; i > 0; i--)
{
// Move current root to end
swap(spqueue[1], spqueue[i]);
// call max heapify on the reduced heap
heapify(i, 1);
}
}
void Spqueue::swap(server& i, server& j) {
server temp;
temp = i;
i = j;
j = temp;
}
int Spqueue::getMin() { //iterates to the next available server in the sorted list of servers
int i = 0;
while (i <=20){
if (spqueue[i].status == true)
{
return i;
}
else
{
i++;
}
}
}
bool Spqueue::getStatus(int i) {
return spqueue[i].status;
}
void Spqueue::setBusy(int i) {
spqueue[i].status = false;
}
void Spqueue::addServiceTime(int i,double s) {
spqueue[i].busyTime = spqueue[i].busyTime + s;
}
double Spqueue::getTotalServiceTime(int i) {
return spqueue[i].busyTime;
}
void Spqueue::setIdle(int i) {
spqueue[i].status = true;
}
double Spqueue::getEffi(int i) {
return spqueue[i].effi;
}
void Spqueue::incrementCustNumber(int i) {
spqueue[i].count++;
}
int Spqueue::getCount(int i) {
return spqueue[i].count;
}
And the following function is supposed to return the most efficient server.
int Spqueue::getMin() { //iterates to the next available server in
the already sorted array
int i = 0;
while (i <=20){
if (spqueue[i].status == true)
{
return i;
}
else
{
i++;
}
}
}
Your priority queue implementation of siftdown has some problems.
void Pqueue::siftdown(int i) { //shifts element to its position in the min heap
int c = i * 2;
int c2 = (i * 2) + 1;
// *** Possible bug
// *** I think that if c == inde, then c is indexing beyond the current queue
if (c > inde) return;
int in = i;
if (pqueue[i].eventTime > pqueue[c].eventTime)
{
in = c;
}
if ((c2 < inde) && (pqueue[i].eventTime > pqueue[c2].eventTime))
{
in = c2;
}
// ***************
// ** Bug here
if (pqueue[c].eventTime < pqueue[c2].eventTime) {
in = c;
}
if (in != i) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}
}
First, I think you want to test c1 >= inde. Also, when you're checking to see if pqueue[c].eventTime < pqueue[c2].eventTime, you do so without making sure that c2 is within bounds.
I find the following to be a more clear and succinct way to do things:
// find the smallest child
int in = c;
if (c2 < inde && pqueue[c2] < pqueue[c])
{
in = c2;
}
if (pqueue[in] < pqueue[i]) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}
I've been trying to understand what havn't I initialized in this code and I completely(?) understand what is uninitialized but I don't know how to initialize it.
I am getting the error:
==11931== Conditional jump or move depends on uninitialised value(s)
==11931== at 0x804ABA6: Hashtable<int>::put(int, int) (hash_table.h:169)
==11931== by 0x8048F80: test_put() (hash_table_test.cpp:27)
==11931== by 0x804A551: main (hash_table_test.cpp:52)
==11931== Uninitialised value was created by a heap allocation
==11931== at 0x402ADFC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==11931== by 0x804A9AE: Hashtable<int>::Hashtable() (hash_table.h:64)
==11931== by 0x8048F62: test_put() (hash_table_test.cpp:26)
==11931== by 0x804A551: main (hash_table_test.cpp:52)
from the valgrind so apparantly I havn't been initializing correctly the c'tor for Hashtable class:
Hashtable() :
ht_keys(2), ht_size(0), dynamicArray(NULL) {
dynamicArray = new Node[ht_keys];
for (int i = 0; i < ht_keys; i++) {
dynamicArray[i].delete_val = false;
dynamicArray[i].key=0;
dynamicArray[i].default_node = false;
}
}
the dynamic array is of type Node* which it's private fields are:
bool delete_val;
T element;
int key;
bool default_node;
the class Node is inside the class Hashtable.
how can I initialize dynamicArray?
here's the full code:
#include <string>
#include <iostream>
#include "library2.h"
#include <iterator>
using namespace std;
#ifndef HASH_TABLE_HPP_
#define HASH_TABLE_HPP_
#define DIV 2
//type T must have c'tor, operator !=
template<class T>
class Hashtable {
public:
class Node {
public:
Node(const T t) :
delete_val(false), element(t), key(0), default_node(true) {
}
Node(bool v, const Node& n) :
delete_val(v), element(n.element), key(0), default_node(
n.default_node) {
}
Node(const Node& n) :
delete_val(false), element(n.element), key(n.key), default_node(
n.default_node) {
}
Node() :
delete_val(false), key(0), default_node(true) {
}
bool operator==(const Node* n) {
if (n) {
if (element != n->element || default_node != n->default_node) {
return false;
}
return true;
}
return false;
}
bool operator!=(const Node n) {
if (!(*this == n)) {
return false;
}
return true;
}
bool delete_val;
T element;
int key;
bool default_node;
};
Hashtable() :
ht_keys(2), ht_size(0), dynamicArray(NULL) {
dynamicArray = new Node[ht_keys];
for (int i = 0; i < ht_keys; i++) {
dynamicArray[i].delete_val = false;
dynamicArray[i].key=0;
dynamicArray[i].default_node = false;
}
}
//seriously damaged programming...
Hashtable(Node* array, int HT_keys, int HT_size) :
ht_keys(HT_keys), ht_size(HT_size) {
dynamicArray = new Node[ht_keys];
if (array != NULL) {
for (int i = 0; i < ht_keys; i++) {
dynamicArray[i] = array[i];
}
}
}
Hashtable(const Hashtable& ht) {
if (&ht == this) {
return;
}
ht_keys = ht.ht_keys;
ht_size = ht.ht_size;
dynamicArray = new Node[ht_keys];
for (int i = 0; i < ht.ht_keys; i++) {
this->dynamicArray[i] = ht.dynamicArray[i];
}
}
~Hashtable() {
delete[] this->dynamicArray;
}
Hashtable operator=(const Hashtable& ht) {
Hashtable<T> newHT = ht;
return newHT;
}
//Returns true if some value equal to value exists within the hash table.
bool contains(Node n, int i) {
if (i < 0 || i > ht_keys || !n) {
return false;
}
if (i == ht_keys) {
return false;
}
//make sure that n.delete_val is not set as true.
if (dynamicArray[i]->element == n.element
&& !dynamicArray[i]->delete_val) {
return true;
}
if (dynamicArray[i]->delete_val) {
return contains(n, i + 1);
}
return false;
return true;
}
//Returns true if some key equal to key exists within the hash table.
bool containsKey(int i) {
if (i < 0 || i > ht_keys) {
return false;
}
if (dynamicArray[i]->element && !dynamicArray[i]->delete_val) {
return true;
}
return false;
}
//Returns true if some value equal to value exists within the hash table.
bool containsValue(T e) {
return true;
}
//Returns an enumeration of the values contained in the hash table.
int enumeration() {
return ht_size;
}
//Returns the object that contains the value associated with key.
//If key is not in the hash table, a null object is returned.
Node get(int i) {
if (i >= 0) {
return dynamicArray[i % ht_keys];
}
Node n;
return n;
}
//Returns true if the hash table is empty;
//returns false if it contains at least one key.
bool isEmpty() {
if (ht_size) {
return false;
}
return true;
}
//Returns an enumeration of the keys contained in the hash table.
int keys();
//Inserts a key and a value into the hash table.
//Returns false if key isn't already in the hash table;
//returns true if key is already in the hash table.
bool put(T e, int i) {
if (e && i > 0) {
Node n;
n.default_node = false;
n.delete_val = false;
n.key = i;
n.element = e;
//line 168
for (int j = (i % ht_keys); j < ht_keys; j = ((j + 1) % ht_keys)) { //line 169
if (!dynamicArray[j % ht_keys].element
|| dynamicArray[j % ht_keys].delete_val) {
dynamicArray[j % ht_keys] = n;
ht_size++;
return true;
}else if (i == (j + 1) % ht_keys) {
rehash();
return put(e, i);
}
}
return false;
}
return false;
}
bool put_aux(Node n, int i, Node* Array, int HT_keys) {
for (int j = (i % HT_keys); j < HT_keys; j = ((j + 1) % HT_keys)) {
if (!Array[j % HT_keys].element || Array[j % HT_keys].delete_val) {
Array[j % HT_keys] = n;
return true;
} else if (Array[j % HT_keys].element == n.element) {
return true;
}
}
return false;
}
//Increases the size of the hash table and rehashes all of its keys.
void rehash() {
int old_ht_keys = ht_keys;
ht_keys = DIV * ht_keys;
Node* newArray = new Node[ht_keys];
if (ht_keys > DIV) {
for (int j = 0; j < old_ht_keys; j++) {
put_aux(dynamicArray[j],dynamicArray[j].key,newArray,ht_keys);
}
}
delete[] dynamicArray;
dynamicArray = newArray;
}
//Removes key and its value.
//Returns the value associated with key.
//If key is not in the hash table, a null objecht_sizet is returned.
T remove(int i) {
if (i >= 0 && i < ht_keys) {
Node deleted_node(true, dynamicArray[i % ht_keys]);
dynamicArray[i % ht_keys] = deleted_node;
ht_size--;
return deleted_node.element;
}
return NULL;
}
//Returns the number of entries in the hash table.
int size() {
return this->ht_size;
}
private:
int ht_keys;
int ht_size;
Node* dynamicArray;
};
#endif /* HASH_TABLE_HPP_ */
It seems to be complaining about the line !dynamicArray[j % ht_keys].element (on line 163 of the code you posted; this would be a lot easier if the code you posted matched the code valgrind was using; right now the code you posted is several lines shorter than the code valgrind is using).
You never initialize the element member when you allocate the memory in the constructor. You then attempt to use it here in a conditional statement. valgrind correctly warns you of the problem.
I have a container (array or vector) and millions of words. I need to sort them in following order s.
The primary sort order should be the number of characters in the word. The secondary sort order should
be lexicographical. I can not use any library such as sort. I want to create the algorithms from scratch. I appreciate if anyone can hit me up with any reference.
So sorting the words:
This is a list of unsorted words
should give:
a is of This list words unsorted
Edit:
I am not allowed to use any STL such as sort
//Following is my final program
//It wi be run with following: args: <inputfile> <outputfile> <timesfile> <ntests>
//timesfile is for storing times and ntests is for number of test
/*
Bernard Grey
10 Wednesday 10 Sep 2014
*/
#include <iostream>
#include <ctime>
#include <algorithm>
#include <fstream>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <vector>
using namespace std;
//This node contain two type of information both in the vector
//First is vector for hash function. it contains number of repetition of the word
//Second node contain a word for values in my vector and the other field is for future implementation ;)
struct node
{
string val;
int count;
};
//Definition of inner and outer vectors as cintainer of words and hash table
typedef std::vector<node> StringVector;
typedef std::vector<StringVector> StringVector2D;
//Cited at http://stackoverflow.com/questions/8317508/hash-function-for-a-string :In the comment
int HashTable (string word)
{
int seed = 378551;
unsigned long hash = 0;
for(int i = 0; i < word.length(); i++)
{
hash = (hash * seed) + word[i];
}
return hash % 1000000;//Later assign it to number of words
}
//Cite at: http://stackoverflow.com/questions/25726530/how-to-find-an-struct-element-in-a-two-dimention-vector
struct find_word
{
string val;
find_word(string val) : val(val) {}
bool operator () ( const node& m ) const
{
return m.val == val;
}
};
//I could use swap function in vector instead of implementing this function
void swap(StringVector& vec, int i, int j)
{
node tmp = vec[i];
vec[i] = vec[j];
vec[j] = tmp;
}
//To compare string alphabetically order
bool comp(node& i,node& p)
{
int cmp;
if(i.val.compare(p.val)<0)
{
return true;
}
return false;
}
void quickSort(StringVector& aVec, int left, int right);
int partition(StringVector& aVec, int left, int right);
void swap(StringVector& aVec, int left, int right);
void quickSort(StringVector& aVec, int left, int right)
{
if(right>0){
int index = partition(aVec,left,right);
if (left<index-1) {
quickSort(aVec, left, index-1);
}
if (index<right) {
quickSort(aVec, index,right);
}
}
}
int partition(StringVector& aVec, int left, int right)
{
string pivotNode;
pivotNode = aVec[(left+right)/2].val;
while (left<=right) {
while (aVec[left].val.compare(pivotNode)<0) {left++; }
while (aVec[right].val.compare(pivotNode)>0) {right--; }
if (left<=right) {
swap(aVec,left,right);
left++;
right--;
}
}
return left;
}
//Welcome to Maaaain
int main(int argc, char* argv[])
{
/*file reading and preprocessing*/
if(argc != 5)
{
cerr << "usage: " << argv[0] << " infile outfile timesfile ntests" << endl;
}
ifstream fin(argv[1]);
if(fin.fail())
{
cerr << "Error: failed to open file " << argv[1] << " for input" << endl;
exit(EXIT_FAILURE);
}
int ntests = atoi(argv[4]);
//Len of string and max num word
int stringlen, numwords;
get_max_words(fin, stringlen, numwords);
//initial string
string init[numwords];
//Read the file and add it to first array
for(int i=0; i<numwords; i++)
{
string tmp;
fin >> tmp;
int len = tmp.length();
//There is one single ' in the example output file. so I do not want to delete that one :-)
bool pp = true;
//Remove punct from leading and tail
if(len==1)
{
pp=false;
}
//Remove punc
if( ispunct(tmp[0]) && pp)
{
tmp.erase(0,1);
}
//Remove punc
if( ispunct(tmp[len-1]) && pp)
{
tmp.erase(len-1,1);
}
init[i] =tmp;
}
/*
At this point, everything should be in the initial array
The temporary array should be declared but not filled
*/
clockid_t cpu;
timespec start, end;
long time[ntests];
//2 Dimension vector this will called outer vector
StringVector2D twoD;
if(clock_getcpuclockid(0, &cpu) != 0)
{
cerr << "Error: could not get cpu clock" << endl;
exit(EXIT_FAILURE);
}
int rep = 0;
node tmp;
tmp.count = 0;
tmp.val = "";
//Later I need to assign it to number of words * M ... Good for encryption... It is not a security subject
vector<node> first(1000000,tmp);
//This is called inner vector
vector<string> templateVec;
//Last search?
bool last = false;
//Initialize inner map as needed and put it inside the outer vector with no data
for(int f=0;f<(stringlen);f++)
{
StringVector myVec;
twoD.push_back(myVec);
}
for(int i=0; i<ntests; i++)
{
if(clock_gettime(cpu, &start) == -1)
{
cerr << "Error: could not get start time" << endl;
exit(EXIT_FAILURE);
}
//Check if it is last iteration so do not delete data for printing purposeses
if(i == ntests-1)
{
last = true;
}
/*copy from initial array to temporary array*/
//Initialize inner vector with the values. In this point outer vector is filled with inner vector
//&&& inner vector is empty myvec.empty() = true;
//vector at index 0 is for words with one char... vector 1 is for words with two chars and so on...
for(int j=0; j<numwords; j++)
{
int len = init[j].length()-1;
if(len<0)continue;
//Initilize a node to fill up the vector
node currNode;
currNode.val = init[j];
//currNode.count = 0;
int hash = HashTable(init[j]);
//Node already existed
if(first[hash].count != 0){
//Add to its value in hash table
first[hash].count++;
}
else
{
//Activate word first time!
first[hash].count =1;
//I can even not use this because of the hash table but it may help in future improvment!!!
first[hash].val = init[j];
//Add the word to appropriate level in outer string! 1char == [0] --- 2char== [1] so on
twoD[len].push_back(currNode);
}
}
//Sort Alphabetically order
for(int f=0;f<(stringlen);f++)
{
//Eficcient sorting algorithm with no chance of segmentation dump ;)
quickSort(twoD[f],0,twoD[f].size()-1);
}
//Time finished
if(clock_gettime(cpu, &end) == -1)
{
cerr << "Error: could not get end time" << endl;
exit(EXIT_FAILURE);
}
//Delete items from vector if it is not last iteration --- This is not part of sorting algorithm so it is after clock
if(!last)
{
for(int f=0;f<stringlen;f++)
{
twoD[f].clear();
}
twoD.clear();
for(StringVector::iterator it3 = first.begin();it3!=first.end();it3++)
{
it3->val="";
it3->count=0;
}
//Initialize inner map as needed and put it inside the outer vector
for(int f=0;f<(stringlen);f++)
{
StringVector myVec;
twoD.push_back(myVec);
}
}
/*time per trial in nanoseconds*/
time[i] = (end.tv_sec - start.tv_sec)*1000000000 + end.tv_nsec - start.tv_nsec;
}
/*output sorted temporary array*/
int k=0;
int y =0;
int num=0;
ofstream fout(argv[2]);
//Pointer for inner vector
StringVector::iterator it2;
for (StringVector2D::iterator outer = twoD.begin(); outer != twoD.end(); ++outer){
y++;
k=0;
for (it2= outer->begin(); it2!=outer->end(); ++it2){
//Get back data from hash table
int hash = HashTable(it2->val);
//Number of word in other field of the node
int repWord = first[hash].count;
//Print according to that
for(int g=0; g < repWord ;g++){
num++;
//10 char in one line
if(num%10 == 0)
{
fout << it2->val;
fout<<endl;
k++;
}
else
{
fout<< it2->val << " ";
}
}
}
}
//Sort times with STL for god sake....
sort(time,time+ntests);
//print times to the file///
ofstream ftimes(argv[3]);
for(int i=0; i<ntests; i++)
ftimes << time[i] << endl;
}
//Helper function .. nice job
void get_max_words(ifstream& fin, int& wordlen, int& numwords)
{
char c;
int count=0;
wordlen = numwords = 0;
while(fin.good() && fin.get(c) && isspace(c)){;} //skip leading space
while(fin.good())
{
++numwords;
while(fin.good() && !isspace(c))
{
++count;
fin.get(c);
}
if(count > wordlen)
wordlen = count;
count = 0;
while(fin.good() && fin.get(c) && isspace(c)){;} //skip space
}
if(count > wordlen)
wordlen = count;
fin.clear();
fin.seekg(0, ios::beg);
}
You'll primarily need a comparator for your sort routine to sort on:
bool lessThan(const std::string a, const std::string b) {
if (a.length() != b.length())
return a.length() < b.length();
return a < b;
}
There's actually an easy way to implement this in stl. There's a sort method that takes a comparator:
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
So you can do this:
bool comparator(const string& a, const string& b) {
if (a.length() < b.length())
return true;
if (a.length() == b.length())
return a < b;
return false;
}
sort(words.begin(), words.end(), comparator);
It's about sorting based on multiple keys. I suggest you study some efficient sorting algorithm, say Quick Sort, then change the comparator to adapt the multiple keys.
For any sorting algorithm that is based on comparing, the easiest way to adapt multiple key sorting is to change the comparing criteria, from a single value to multiple values.
If you are not even allowed to use STL, i.e. you are not allowed to use sort in , here is a post you can start with: Sorting an array using multiple sort criteria (QuickSort)
If you are allowed, just write a comparing function which supports the multiple key comparison and plug it in the sort function. You can check this C++ reference for more details.
An illustration (it's just an illustration to point out how you can plug in the compare function):
bool comparator(const string& a, const string& b) {
if (a.length() < b.length())
return true;
if (a.length() > b.length())
return false;
return a < b;
}
void Qsort(string a[],int low,int high)
{
if(low >= high)
{
return;
}
int left = low;
int right = high;
string key = a[(low + high) >> 1];
while(left < right)
{
while(left < right && comparator(a[left], key)) left++;
while(left < right && !comparator(a[right], key)) right--;
if (left < right)
{
swap(a[left], a[right]);
left++; right--;
}
}
if (left == right) left ++;
if (low < right) Qsort(a, low, left - 1);
if (high > left) Qsort(a, right + 1, high);
}
The answer wants a design, so I'll focus on the design of your sorting library, than an implementation
Your sort algorithm can use your custom comparator objects with a member operator() implemented for comparison between two elements.
Your comparator can be a Linked List of comparators and can call the next comparator if the current one gives a tie. You'll have to ensure that there is always a true and false return though. Or implement something that can create a stable_sort if nothing else.
So the first comparator is number of characters and the second comparator is lexicographical..
This idea is then general enough so that if your requirement changes tomorrow. This can then be reused.
This is on the lines of Chain of Responsibility Pattern. You can templat-ize the comparator after you've got the gist.
Ex:
class Chain_Comparator
{
Chain_Comparator* next;
public:
bool operator()( void* a, void* b )
{
if( a_is_less_b(a, b) )
return true;
else if( b_is_less_a(a,b) )
return false;
else if( next )
return next( a, b )
}
virtual bool a_is_less( void* a, void* b) = 0;
virtual bool b_is_less( void* a, void* b) = 0;
};
class Num_Comparator : public Chain_Comparator
{
// Implements a_is_less etc.
};
class Lex_Comparator : public Chain_Comparator
{
// Implement lex comparisons.
};
void your_custom_sorting_method( vector<int > a, Chain_Comparator& c)
{
// Implementation goes here.
// call the operator() for c with simply : c( a[i], a[j] )
}