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'
Related
Problem is to return any one combination from given array that sums up to the target. I'm new to C++. How can I complete the function howSum() below? I can't return null here since the return type is vector. Also I'm having trouble passing the vectors.
JavaScript:
const howSum = (targetSum, numbers) => {
if (targetSum === 0) return [];
if (targetSum < 0) return null;
for (let num of numbers) {
const remainder = targetSum - num;
const remainderResult = howSum(remainder, numbers);
if (remainderResult !== null)
{
return [...remainderResult, num];
}
}
return null;
};
C++:
vector<int> howSum(int targetSum, vector<int> numbers)
{
if(targetSum == 0) return {};
if(targetSum < 0) return; //can't return null here in C++
for (int i = 0; i < numbers.size(); i++)
{
int remainder = targetSum - numbers[i];
vector<int> remainderResult = howSum(remainder, numbers);
if(pass)
{
pass
}
}
}
You can use C++17 std::optional and return std::nullopt when it does not contain value.
#include <optional>
#include <vector>
std::optional<std::vector<int>>
howSum(int targetSum, const std::vector<int>& numbers) {
if (targetSum == 0)
return std::vector<int>{};
if (targetSum < 0)
return std::nullopt;
for (auto numer : numbers) {
const auto remainder = targetSum - numer;
auto remainderResult = howSum(remainder, numbers);
if (remainderResult) {
remainderResult->push_back(targetSum);
return remainderResult;
}
}
return std::nullopt;
}
Let your function return a bool to indicate if the vector result (returned as an out param) is valid or not. It's likely going to be more efficient to pass the array (vector) as an out param reference than as a return value anyway. (Although modern compilers can do some amazing optimizations these days.)
bool howSum(int targetSum, const std::vector<int>& numbers, std::vector<int>& result)
{
result.clear();
if (targetSum == 0) {
return true;
}
if (targetSum < 0) {
return false;
}
for (int num : numbers) {
const int remainder = targetSum - num;
bool recursion_result = howSum(remainder, numbers, result);
if (recursion_result) {
result.push_back(num);
return true;
}
}
return false;
}
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?
I will be given string. I can remove only 1 element from it. After removing it if the new string becomes palindrome I have to print "Yes" otherwise "No".
For example, I am given a string "abdbca". Here I can remove 5th index 'c' and make it palindrome and i have to print "Yes". On the other hand if the string is something like "abcd" I can not make it palindrome by removing only one character. Hence I have to print "No".
I tried to do it but my code is not efficient enough. Can anybody please suggest me a efficient way to do it? I have to check strings of 10^5 length in less than 2.5 seconds.
the way I tried to do it is shown bellow :
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#define REP(i,n) for(int i=0;i<n;i++)
#define MAX 100010
using namespace std;
bool isPalindrome(char abc[]){
int len = strlen(abc), lem = len/2;
for(int i=0,n=len-1;i<=lem;i++,n--) if(abc[i]!=abc[n]) return false;
return true;
}
int main()
{
int tc;
char str[MAX];
scanf("%d",&tc);
while(tc--){
scanf("%s", str);
int length = strlen(str), len = length - 1, z = length % 2, res = 0, ans = 0, b=0,lem = length / 2;
for(int i = 0;i<length;i++){
int n=0, m=1;
for(int x = 0, y = len;x<i && y!=i;x++,y--){
n++;
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
if(i>lem) for(int x=n,y=len-n-1;x<y;x++,y--){
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
else for(int x=n+1,y=len-n;x<y;x++,y--){
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
if(m==1) {printf("YES\n");b++;break;}
}
//if(length <= res) printf("NO\n");
if(b==0) printf("NO\n");
}
return 0;
}
Since you you only need to remove one character, you can do so in linear time by modifying palindrome checking. The idea is that you compare characters from the beginning to characters from the end and stop at the first mismatch. If you remove one character from the mismatching pair and get a palindrome, then return true, otherwise return false. I implemented the idea in C++ below.
#include<iostream>
#include<string>
using namespace std;
bool palindromeExists(string s)
{
int i = 0;
int j = s.length()-1;
while(i < j)
{
if(s[i] != s[j]) //first mismatch
break;
i++;
j--;
}
int tempj = j-1; //remove s[j]
int tempi = i;
while(tempi < tempj)
{
if(s[tempi] != s[tempj])
break;
tempi++;
tempj--;
}
if(tempi >= tempj) //palindrome found?
return true;
tempi = i+1; //remove s[i]
tempj = j;
while(tempi < tempj)
{
if(s[tempi] != s[tempj])
return false;
tempi++;
tempj--;
}
return true;
}
int main()
{
string s = "abca";
if(palindromeExists(s))
cout << "YES" << endl;
else
cout << "NO" << endl;
return 0;
}
This should return true if the string is already a palindrome, or if it can be a palindrome after the removal of one character. I hope I didn't miss any corner cases.
You can refer complete program in c++ here. Input the string to get the index of character to be removed. String reversal is performed in palim() function. It returns -1 if string is already palindrome.
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
bool palim(string s)
{
string s2;
s2=string(s.rbegin(),s.rend());
if(s2==s)
{
return true;
}
else
{
return false;
}
}
int check(string s)
{
int x;
if(s.length()%2==0)
{
for(int i=0,j=s.length()-1;i<s.length()/2,j>=s.length()/2;i++,j--)
{
if(s[i]!=s[j])
{
string s1=s;
s1.erase(j,1);
if(palim(s1))
{
x=j;
break;
}
else
{
string s1=s;
s1.erase(i,1);
if(palim(s1))
{
x=i;
break;
}
}
}
}
}
else
{
for(int i=0,j=s.length()-1;i<s.length()/2,j>s.length()/2;i++,j--)
{
if(s[i]!=s[j])
{
string s1=s;
s1.erase(j,1);
if(palim(s1))
{
x=j;
break;
}
else
{
string s1=s;
s1.erase(i,1);
if(palim(s1))
{
x=i;
break;
}
}
}
}
}
return x;
}
int main()
{
string s;
cin>>s;
if(palim(s))
{
cout<<"-1"<<endl;
}
else
{
cout<<check(s)<<endl;
}
return 0;
}
Similar to turingcomplete, but with sub functions:
bool isPalindrome(std::string::const_iterator& start, std::string::const_iterator& end)
{
while (start < end) {
--end;
if (*start != *end) {
return false;
}
++start;
}
return true;
}
bool test(const std::string& s)
{
auto start = s.begin();
auto end = s.end();
if (isPalindrome(start, end)) {
// If we remove the middle character of a palindrome,
// We still have a palindrome.
return true;
}
// Now test if there is a palindrome
// if we skip the mismatch char from the start or from the end.
auto start2 = start;
auto end2 = end;
++start2;
--end;
return isPalindrome(start, end) || isPalindrome(start2, end2);
}
Live example
I am trying to run this program but it just runs for a very long time when it is supposed to only take a couple seconds. I would appreciate it if I could get help on what is wrong with my code and what i need to fix.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include "sudoku_solver.hpp"
int main()
{
std::vector< std::vector<int> > board(9,std::vector<int>(9));
int i =0,j=0;
for(std::string line;std::getline(std::cin,line);)
{
if(i==9)
{
i=0;
break;
}
std::stringstream line_stream(line);
for(std::string token;std::getline(line_stream,token,' ');)
{
if(j==9)
{
j=0;
}
board[i][j] = std::stoi(token);
j++;
}
i++;
}
if(sudoku_backtracker(board)==1)
{
for(int i = 0;i<9;i++)
{
for(int j = 0;j<9;j++)
{
std::cout<<board[i][j];
}
std::cout<<endl;
}
}
return 0;
}
sudoku_solver.hpp:
#ifndef __SUDOKU_SOLVER_HPP__
#define __SUDOKU_SOLVER_HPP__
#include <vector>
int sudoku_backtracker(std::vector< std::vector<int> > &board);
std::pair<int, int> find_empty_spot(std::vector< std::vector<int> > board);
bool checks_num_is_valid(std::vector< std::vector<int> > board,int row,int column,int number);
#endif //__SUDOKU_SOLVER_HPP__
sudoku_solver.cpp:
#include "sudoku_solver.hpp"
#include <iostream>
#include <string>
int sudoku_backtracker(std::vector< std::vector<int> > &board)
{
int test_num = 1;
std::pair<int,int> empty_spot = find_empty_spot(board);
if(empty_spot.first == -1)
{
return 1;
}
while(test_num != 10)
{
if(checks_num_is_valid(board,empty_spot.first,empty_spot.second,test_num))
{
board[empty_spot.first][empty_spot.second] = test_num;
int recursive_sudoku = sudoku_backtracker(board);
if(recursive_sudoku==1)
{
return 1;
}
board[empty_spot.first][empty_spot.second] = 0;
}
test_num++;
}
return 0;
}
std::pair<int, int> find_empty_spot(std::vector< std::vector<int> > board)
{
for(int row=0;row<9;row++)
{
for(int column=0;column<9;column++)
{
if(board[row][column] == 0){return std::make_pair(row,column);}
}
}
return std::make_pair(-1,-1);
}
bool checks_num_is_valid(std::vector< std::vector<int> > board, int row,int column, int number)
{
bool num_not_in_column = true;
bool num_not_in_row = true;
bool num_not_in_box = true;
//box_start_row as bsr and box_start_column as bsc
//this is the starting point to check the numbers inside the box and make
//sure the test number is valid
int bsr = 0,bsc = 0;
//checks the numbers in the same column but different rows
for(int i =0;i<9;i++)
{
if(i==row){continue;}
if(board[i][column] == number){num_not_in_column = false;break;}
}
//checks numbers in the same row but different columns
for(int i = 0;i<9;i++)
{
if(i==column){continue;}
if(board[row][i] == number){num_not_in_row = false;break;}
}
//checks wether the numer is int the same box
if(row<=2){bsr =0;}
if(row>=3 && row<=5){bsr = 3;}
if(row>=6 && row<=8){bsr = 6;}
if(column <=2){bsc =0;}
if(column>=3 && column<=5){bsc=3;}
if(column>=6 && column<=8){bsc=6;}
//double for loop to check all the values inside the box
for(bsr;bsr<bsr+3;bsr++)
{
for(bsc;bsc<bsc+3;bsc++)
{
if(bsr==row && bsc==column)
{continue;}
else
{
if(board[bsr][bsc] == number)
{
num_not_in_box = false;
}
}
}
}
bool result = num_not_in_row && num_not_in_column && num_not_in_box;
return result;
}
You have two nested infinite loops. bsr<bsr+3 is always true, regardless of bsr value. Except when it overflows, but that's undefined behaviour and the compiler is allowed to optimize that to true.
for(bsr;bsr<bsr+3;bsr++)
{
for(bsc;bsc<bsc+3;bsc++)
I cannot figure out why this code isn't working. It doesn't even seem to be going through my for loops and nested loops. I'm very new to programing. I have been trying to answer Euler questions for practice. Sorry if my code is awful.
#include <iostream>
#include <string>
using namespace std;
bool isPalindrome(int x) {
string str = to_string(x);
for(string::reverse_iterator rit=str.rbegin(); rit!=str.rend(); ++rit) {
string pal = to_string(*rit);
if(pal == str) {
return true;
}else {
return false;
}
}
}
int main() {
int max[] = {0, 0};
for(int i=999; i>99; i--) {
for( int j =999; j>99; j--) {
int pal = i*j;
if(isPalindrome(pal) == true) {
max[1] = pal;
if(max[1] > max[0]){
max[0] = pal;
}
}
}
}
cout << max[0];
}
I think you need to return true in isPalindrome after comparing complete string. ie return true; should be outside for loop
And for checking largest 3 digit palindrome why are you passing int pal = i*j; ie for first iteration 999*999. Check this
bool isPalindrome(int x) {
string str = to_string(x);
string pal = str;
std::reverse(pal.begin(),pal.end());
if(pal == str) {
return true;
}else {
return false;
}
}