Reputation: 3891
I saw this code in a HackerRank challenge solution, and I'm wondering whether there's a way to make it more efficient and/or aesthetically appealing. It's counting all the permutations of a bunch of digits, where there are x 4's
, y 5's
, and z 6's
. For this reason, the code gets quite repetitive:
int cnt[101][101][101];
int solve1(int x,int y,int z){
if(x <= 0 && y <= 0 && z <= 0)
return 1 ;
int &ret = cnt[x][y][z] ;
if(ret != -1) return ret ;
ret = 0 ;
if(x)
ret += solve1(x-1,y,z) ;
if(ret >= mod) ret -= mod ;
if(y)
ret += solve1(x,y-1,z) ;
if(ret >= mod) ret -= mod ;
if(z)
ret += solve1(x,y,z-1) ;
if(ret >= mod) ret -= mod ;
return ret ;
}
Do STL
containers or algorithms offer a way to make this less repetitive and/or more efficient?
Considered and rejected:
Pass a vector
to solve()
rather than many integers and then use accumulate
to collect ret
while modifying each vector element (x, y, z as vector elements) and recalling solve
on modified copy of original vector input.
But this just creates a whole bunch of vectors
without any clear
counterbalancing improvement. Also, I haven't thought out the accumulate
application so presumably that part is way off/not possible.
Thanks for any suggestions.
Upvotes: 0
Views: 147
Reputation: 275385
Sort the x y z, and the memoization is far more effective:
int cnt[101][101][101]={0};
int solve1(std::array<int,3> idx){
std::sort(idx.begin(),idx.end());
int x=idx[0],y=idx[1],z=idx[2];
if(x <= 0 && y <= 0 && z <= 0) return 1;
int &ret = cnt[x][y][z];
if(ret != -1) return ret;
ret = 0;
auto f=[&](int x,int y,int z){
ret += solve1({{x-1,y,z}});
if(ret >= mod) ret -= mod;
};
if(x)f(x-1,y,z);
if(y)f(x,y-1,z);
if(z)f(x,y,z-1);
return ret;
}
int solve1(int x,int y,int z){
return solve1({{x,y,z}});
}
Upvotes: 0
Reputation: 182763
With c++11, you can replace:
if(x)
ret += solve1(x-1,y,z) ;
if(ret >= mod) ret -= mod ;
if(y)
ret += solve1(x,y-1,z) ;
if(ret >= mod) ret -= mod ;
if(z)
ret += solve1(x,y,z-1) ;
if(ret >= mod) ret -= mod ;
With:
auto func = [](int&ret, int x, int y, int z)
{
ret += solve1(x, y, z);
if (ret >= mod) ret -= mod;
return ret;
};
if (x) func (ret, x-1, y, z);
if (y) func (ret, x, y-1, z);
if (z) func (ret, x, y, z-1);
You could also just use a function.
Upvotes: 2