Is this Knapsack-like algorithm correct? - c++

I've implemented a simple algorithm for a Knapsack-like problem. I've searched other solutions in similar questions, but I cannot determine if my solution is complete for this specific problem.
The problem:
Write a function that takes a number a list of numbers. The function should return "true"
if number can be calculated using add and subtract operations or "false" otherwise.
Examples:
(9, [2,8,5,10]) -> true
(0, [4,3,2,1]) -> true
(0, []) -> true
(0, [1]) -> false
(1, [1]) -> true
(4, [1,2]-> false
From my understanding the algorithm must use all the numbers and should not stop in non-leaf nodes. So this is my code:
bool knapSack(int res, const std::vector<int>& v, int index, int cur_add)
{
bool ret = false;
if (index < v.size())
{
if (v.size() > 0)
{
ret = knapSack(res, v, index + 1, cur_add + v[index]);
if(!ret)
ret = knapSack(res, v, index + 1, cur_add - v[index]);
}
}
else if(res == cur_add)
ret = true;
return ret;
}
int main()
{
std::cout << "The result is: " << knapSack(9, { 5,8,10,2 }, 0, 0) << std::endl;
std::cout << "The result is: " << knapSack(0, { 4,3,2,1 }, 0, 0) << std::endl;
std::cout << "The result is: " << knapSack(0, { }, 0, 0) << std::endl;
std::cout << "The result is: " << knapSack(0, { 1 }, 0, 0) << std::endl;
std::cout << "The result is: " << knapSack(1, { 1 }, 0, 0) << std::endl;
std::cout << "The result is: " << knapSack(2, { 4,1 }, 0, 0) << std::endl;
return 0;
}
Is this algorithm complete and correct, or am I missing something?

Related

How to access the value from the json file using runtime key in c++

I'm new to json and trying to use nlohmann library and I'm quite stuck.
config.json file looks like this
{
"Version": 1.1,
"Size": 1024,
"integer": 600,
"Map": [{"0": "india"}, {"1": "usa"}, {"2": "china"}, {"2": "japan"}],
"name": "xxx",
}
I want to get the value of ["Map"]["1"] where "1" is a runtime entity. I have tried several ways but none of them is working.
std::string strRwFilePath = std::string(CONFIG_PATH) + "config.json";
std::ifstream RwFile(strRwFilePath);
if (RwFile.fail())
{
std::cout << "[ReadFileContents]RwFile doesnt exist" << std::endl;
}
else
{
// parsing input
RwFile >> conf_json;
if(!(conf_json.empty()))
{
//METHOD 1
for (auto it = conf_json["Map"].begin(); it != conf_json["Map"].end(); ++it)
{
std::cout << it.key() << " | " << it.value() << "\n";
std::string keyy = std::to_string(m_iRegionType);
std::string tempKey = it.key(); //ERROR- [json.exception.invalid_iterator.207] cannot use key() for non-object iterators
std::cout << "for loop: tempKey:" << tempKey << " \n";
if(!strcmp(tempKey.c_str(),(std::to_string(m_iRegionType)).c_str()))
{
std::cout << "SUCCESS 222" << std::endl;
break;
}
else
{
std::cout << "FAILURE 222" << std::endl;
}
}
//METHOD 2
for(auto& element : conf_json["Map"].items())
{
std::cout << element.key() << " | " << element.value() << "\n";
m_iRegionType = 2;
std::string keyy = std::to_string(m_iRegionType);
std::string tempKey = element.key(); //ERROR: [json.exception.type_error.302] type must be string, but is object
if(!strcmp(tempKey.c_str(),(std::to_string(m_iRegionType)).c_str()))
{
std::cout << "SUCCESS 333" << std::endl;
break;
}
else
{
std::cout << "FAILURE 333" << std::endl;
}
}
//METHOD 3
std::string strTempKey = std::to_string(m_iRegionType);
if(!conf_json["Map"][strTempKey.c_str()].is_null())
{
std::string strName = conf_json["Map"][strTempKey.c_str()]; //ERROR: [json.exception.type_error.305] cannot use operator[] with a string argument with array
std::cout << "key found. RegionName: " << strName << '\n';
}
else
{
std::cout << "key not found" << std::endl;
}
//METHOD 4
// create a JSON object
std::string strKey = "/Map/" + std::to_string(m_iRegionType);
// call find
auto it_two = conf_json.find(strKey.c_str());
if(true == (it_two != conf_json.end()))
{
std::cout << "Region key was found. RegionBucketName: " << *it_two << '\n';
std::string strRegionName = conf_json["Map"][m_iRegionType];
std::string strRegionName2 = *it_two;
std::cout << "strRegionName: " << strRegionName << '\n';
std::cout << "strRegionName2: " << strRegionName2 << '\n';
}
else
{
//getting this as OUTPUT even though key is available
std::cout << "invalid region type, key not available m_iRegionType: " << m_iRegionType << std::endl;
}
}
else
{
std::cout << "[ReadFileContents]Read Write Json object is empty" << std::endl;
}
}
I have also tried using the small json structure where I am not able to access the value using the runtime key.
json j =
{
{"integer", 1},
{"floating", 42.23},
{"string", "hello world"},
{"boolean", true},
{"object", {{"key1", 1}, {"key2", 2}}},
{"array", {1, 2, 3}}
};
int avail4 = j.value("/integer"_json_pointer, 444);
std::cout << "avail4 : " << avail4 << std::endl; //OUTPUT- avial4 : 1
int avail5 = j.value("/object/key2"_json_pointer, 555);
std::cout << "avail5 : " << avail5 << std::endl; //OUTPUT- avial5 : 2
auto strKey3 = "/object/key2";
int avail6 = j.value(strKey3, 666);
std::cout << "avail6 : " << avail6 << std::endl; //OUTPUT- avial6 : 666
Could any one help me.
You can't use ["Map"]["1"] to find the inner array objects. You need iterator through the array
A code example may like this:
#include <nlohmann/json.hpp>
#include <iostream>
// for convenience
using json = nlohmann::json;
int main() {
json j = R"(
{
"Version": 1.1,
"Size": 1024,
"integer": 600,
"Map": [{
"0": "india"
}, {
"1": "usa"
}, {
"2": "china"
}, {
"2": "japan"
}],
"name": "xxx"
}
)"_json;
for (const auto& ele : j["Map"]) {
if (ele.contains("1")) {
std::cout << ele["1"] << std::endl;
}
}
}
Output:
usa
Demo

How to traverse a map of the form pair<int,pair<int,int>> with a iterator

I defined map like
map <int,pair<int,int>> hmap;
If there is a pair(2,pair(3,4)) how to get 2 3 4 values, itr->first, itr->second not working
If there is a pair(2,pair(3,4)) how to get 2 3 4 values [from an iterator itr to map<int,pair<int, int>>]
I suppose
itr->first // 2
itr->second.first // 3
itr->second.second // 4
Here is a demonstrative program with using iterators and the range-based for statement.
#include <iostream>
#include <map>
int main()
{
std::map<int, std::pair<int, int>> hmap{ { 1, { 2, 3 } }, { 2, { 3, 4 } } };
for (auto it = hmap.begin(); it != hmap.end(); ++it)
{
std::cout << "{ " << it->first
<< ", { " << it->second.first
<< ", " << it->second.second
<< " } }\n";
}
std::cout << std::endl;
for (const auto &p : hmap)
{
std::cout << "{ " << p.first
<< ", { " << p.second.first
<< ", " << p.second.second
<< " } }\n";
}
std::cout << std::endl;
}
Its output is
{ 1, { 2, 3 } }
{ 2, { 3, 4 } }
{ 1, { 2, 3 } }
{ 2, { 3, 4 } }

Returns garbage value instead of 0 or 1 in c++

I am trying to return integer from the following method in c++:
int check_for_chef(string str1,string str2,int M,int N)
{
if ( N == -1 )
{
cout << "I am returning 1." <<endl;
return 1;
}
else if ( N > M )
{
cout << " I am returning 0." <<endl;
return 0;
}
else
{
if ( str1[M] == str2[N])
{
location[N] = M;
cout << "location is: "<<location[N]<<endl;
check_for_chef(str1,str2,M - 1, N - 1);
}
else
{
check_for_chef(str1,str2,M - 1, N);
}
}
}
But, what I am getting while returning is :
Returned value is: 35668224
Whole code is here:
#include <iostream>
#include <string>
using namespace std;
int location[4];
int check_for_chef(string str1,string str2,int M,int N)
{
if ( N == -1 )
{
cout << "I am returning 1." <<endl;
return 1;
}
else if ( N > M )
{
cout << " I am returning 0." <<endl;
return 0;
}
else
{
if ( str1[M] == str2[N])
{
location[N] = M;
cout << "location is: "<<location[N]<<endl;
check_for_chef(str1,str2,M - 1, N - 1);
}
else
{
check_for_chef(str1,str2,M - 1, N);
}
}
}
int main()
{
int count = 0;
string original_string;
cin >> original_string;
string chef = "CHEF";
int M = original_string.size();
int N = 4;
while ( 1 )
{
cout << "Returned value is: " << check_for_chef(original_string,chef,M - 1, N - 1);
cout << " i am in while."<<endl;
count++;
original_string.erase(location[3],1);
cout << "the original_string : " << original_string <<endl;
original_string.erase(location[2],1);
cout << "the original_string : " << original_string <<endl;
original_string.erase(location[1],1);
cout << "the original_string : " << original_string <<endl;
original_string.erase(location[0],1);
cout << "the original_string : " << original_string <<endl;
cout << "the original_string : " << original_string <<endl;
M = original_string.size();
cout << "size is :" << M <<endl;
if ( M < N )
break;
}
cout << count <<endl;
}
Please help me to solve this problem.
I don't see two more return in the code
I have added in the commented lines below:
int check_for_chef(string str1,string str2,int M,int N)
{
if ( N == -1 )
{
cout << "I am returning 1." <<endl;
return 1;
}
else if ( N > M )
{
cout << " I am returning 0." <<endl;
return 0;
}
else
{
if ( str1[M] == str2[N])
{
location[N] = M;
cout << "location is: "<<location[N]<<endl;
return check_for_chef(str1,str2,M - 1, N - 1); // here 1st RETURN
}
else
{
return check_for_chef(str1,str2,M - 1, N); // here 2nd RETURN
}
}
}
Your code does not return anything expicitly in the else branch.
Values in x84 usually are returned via EAX register, so if you do not return anything - it behaves like an uninitialized variable.

Binary search on strings instead of numbers

I am reading up on binary search on an array of numbers and I believe I know how it works and how to implement it. Now I need to know how to do binary search on an array of strings ? I know binary search requires the array to be sorted already. suppose I have an array of strings already sorted how do I implement binary search on it ? I know if it was an array of numbers I would go to the middle index of the array and determin if the required search no is on the left or the right and do that recursively. How would i do that for strings?
As long as the concept of "it is equal to" and "it is less than" are defined for the type you are working on, you can implement the algorithm. It does not matter if the values are numbers, letters, or custom objects. The following example demonstrates this concept:
template<typename Iterator>
Iterator search(Iterator initial, Iterator final, const typename Iterator::value_type& value) {
if(value < *initial) {
// bail out immediately
return final;
}
while(initial != final) {
auto mid = std::next(initial, std::distance(initial, final) / 2);
if(*mid == value) {
return mid;
} else if(*mid < value) {
initial = std::next(mid);
} else {
final = std::prev(mid);
}
}
return final;
}
As long as the operations *mid == value and *mid < value are defined, I can search in a container of any type (another requirement is that I must be able to randomly access my iterator).
This is by no means a full answer, and there are many more details involved, but hopefully you get the idea.
Full sample program:
#include <vector>
#include <list>
#include <iostream>
template<typename Iterator>
Iterator search(Iterator initial, Iterator final, const typename Iterator::value_type& value) {
if(value < *initial) {
// bail out immediately
return final;
}
while(initial != final) {
auto mid = std::next(initial, std::distance(initial, final) / 2);
if(*mid == value) {
return mid;
} else if(*mid < value) {
initial = std::next(mid);
} else {
final = std::prev(mid);
}
}
return final;
}
int main() {
{
std::vector<int> v {1, 2, 3, 4, 5};
auto it = search(v.begin(), v.end(), 3);
if(it == v.end()) {
std::cout << "Not Found!" << std::endl;
} else {
std::cout << "Found in position: " << std::distance(v.begin(), it)
<< " (value is : " << *it << ")" << std::endl;
}
}
{
std::vector<char> v {'a', 'b', 'c', 'd', 'e'};
auto it = search(v.begin(), v.end(), 'd');
if(it == v.end()) {
std::cout << "Not Found!" << std::endl;
} else {
std::cout << "Found in position: " << std::distance(v.begin(), it)
<< " (value is : " << *it << ")" << std::endl;
}
}
{
std::list<float> v {-1, 0, 1, 2, 3, 4};
auto it = search(v.begin(), v.end(), 0);
if(it == v.end()) {
std::cout << "Not Found!" << std::endl;
} else {
std::cout << "Found in position: " << std::distance(v.begin(), it)
<< " (value is : " << *it << ")" << std::endl;
}
}
{
std::vector<char> v {'a', 'b', 'c', 'd', 'e'};
auto it = search(v.begin(), v.end(), 'f');
if(it == v.end()) {
std::cout << "Not Found!" << std::endl;
} else {
std::cout << "Found in position: " << std::distance(v.begin(), it)
<< " (value is : " << *it << ")" << std::endl;
}
}
}
Sample Run:
Found in position: 2 (value is : 3)
Found in position: 3 (value is : d)
Found in position: 1 (value is : 0)
Not Found!
A naive approach would be to assign a unique value to each letter (if you're doing English, that's easy; only 26 values), and compare the values of the first letter of each string. If the letters are the same, then you compare the second letter, and so on.
If you use array of std::string, it just the same since you have all compare operators.
so you just need to replace the type of the array and you can do the search as is for numbers.
Exact same way. If you use std::string, it already has operator== and operator < which are all you need for binary search. If you just have character pointers, you can use strcmp, where a negative value is less than and 0 is equal.

Initialize a map with map-values

I want to initialize a map with map-values in the following way:
std::map<int, std::map<int, int>> map =
{
{ 1, { { 1, 0 }, { 2, 1 } } },
{ 2, { { 1, 1 }, { 2, 0 } } },
};
While this compiles without any error or warning, it raises an exception stating "map/set iterators incompatible". If I remove the second pair, i.e. { 2, { { 1, 1 }, { 2, 0 } } }, no exception is raised and map contains one pair with key 1 and a map containing the pairs (1, 0) and (2, 1) as its value.
I'm sure there is a quite good reason for this (at first glance) somehow strange behavior.
Solution
Nope, there's no good reason. It turned out to be one of the beautiful bugs in Visual Studio 2013.
did you tried with c++11 option?
#include <iostream>
#include <map>
int main()
{
std::map<int, std::map<int, int>> map =
{
{ 1, { { 1, 0 }, { 2, 1 } } },
{ 2, { { 1, 1 }, { 2, 0 } } },
};
auto t = map[1];
std::cout << t[1] << std::endl;
std::cout << t[2] << std::endl;
auto t2 = map[2];
std::cout << t2[1] << std::endl;
std::cout << t2[2] << std::endl;
std::cout << "--------------" << std::endl;
std::cout << map[1][1] << std::endl;
std::cout << map[1][2] << std::endl;
std::cout << map[2][1] << std::endl;
std::cout << map[2][2] << std::endl;
}