Related
Question:
https://www.spoj.com/problems/BALNUM/
My Solution:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
string s;
vector<ll>v;
ll dp[20][2][3][3][3][3][3][3][3][3][3][3][2];
ll solve(ll i,ll less,ll start,ll m0,ll m1,ll m2,ll m3,ll m4,ll m5,ll m6,ll m7,ll m8,ll m9){
if(i == s.size()){
if((m1 == 2 or m1 == 0) and (m3 == 2 or m3 == 0) and (m5 == 2 or m5 == 0) and (m7 == 2 or m7 == 0) and (m9 == 2 or m9 == 0) and (m0 == 1 or m0 == 0) and (m2 == 1 or m2 == 0) and (m4 == 1 or m4 == 0) and (m6 == 1 or m6 == 0) and (m8 == 1 or m8 == 0)){
return 1;
}
return 0;
}
ll &ret = dp[i][less][m0][m1][m2][m3][m4][m5][m6][m7][m8][m9][start];
if(ret != -1) return ret;
ll k = less ? 9 : v[i];
ll ans = 0;
for(ll j = 1; j <= k; j++){
if(j == 1){
ans += solve(i+1,less | (j < v[i]),0,m0,((m1+1)%3 == 0) ? 1:(m1+1)%3,m2,m3,m4,m5,m6,m7,m8,m9);
}else if(j == 2){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,((m2+1)%3 == 0) ? 1:(m2+1)%3,m3,m4,m5,m6,m7,m8,m9);
}else if(j == 3){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,((m3+1)%3 == 0) ? 1:(m3+1)%3,m4,m5,m6,m7,m8,m9);
}else if(j == 4){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,((m4+1)%3 == 0) ? 1:(m4+1)%3,m5,m6,m7,m8,m9);
}else if(j == 5){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,m4,((m5+1)%3 == 0) ? 1:(m5+1)%3,m6,m7,m8,m9);
}else if(j == 6){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,m4,m5,((m6+1)%3 == 0) ? 1:(m6+1)%3,m7,m8,m9);
}else if(j == 7){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,m4,m5,m6,((m7+1)%3 == 0) ? 1:(m7+1)%3,m8,m9);
}else if(j == 8){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,m4,m5,m6,m7,((m8+1)%3 == 0) ? 1:(m8+1)%3,m9);
}else if(j == 9){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,m4,m5,m6,m7,m8,((m9+1)%3 == 0) ? 1:(m9+1)%3);
}
}
if(!start){
ans += solve(i+1,less | (0 < v[i]),0,((m0+1)%3 == 0) ? 1:(m0+1)%3,m1,m2,m3,m4,m5,m6,m7,m8,m9);
}
if(start){
ans += solve(i+1,1,1,0,0,0,0,0,0,0,0,0,0);
}
return ret = ans;
}
int main(){
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
ll t;
cin>>t;
while(t--){
ll x;
cin>>x;
--x;
s = to_string(x);
memset(dp,-1,sizeof(dp));
v.clear();
for(char c:s) v.push_back(c-'0');
ll a=solve(0,0,1,0,0,0,0,0,0,0,0,0,0);
cin>>s;
memset(dp,-1,sizeof(dp));
v.clear();
for(char c:s) v.push_back(c-'0');
ll b=solve(0,0,1,0,0,0,0,0,0,0,0,0,0);
cout<<b-a<<endl;
}
}
Here the array i use for memoization is dp[20][2][3][3][3][3][3][3][3][3][3][3][2] (20 is max length of integer A or B)
Is the time complexity O(n) with a very high constant (like 2*3*3*3*3*3*3*3*3*3*3*2) where n is max length of integer A or B?
Its T * ( N * (2^2 * 3^10 * 9) + C ), The constant factor is really huge, but overall i think you can say that the time complexity is T * N * (a huge constant factor).
So you could say its O(T*N).
I want to print the minimum sum of the matrix where you are allowed to move either right or down. I'm able to get cost but I'm not sure how can I print path with the minimum sum among all the possible paths.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
#define M 3
#define N 3
int findMinCost(int cost[M][N])
{
int T[M][N];
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
T[i][j] = cost[i][j];
if (i == 0 && j > 0)
T[0][j] += T[0][j - 1];
else if (j == 0 && i > 0)
T[i][0] += T[i - 1][0];
else if (i > 0 && j > 0)
T[i][j] += min(T[i - 1][j], T[i][j - 1]);
}
}
return T[M - 1][N - 1];
}
int main()
{
int cost[M][N] =
{
{ 9,-2,10 },
{ 15,23,-10 },
{ 40,16,2 },
};
cout << "The minimum cost is " << findMinCost(cost);
return 0;
}
You can use another 2-d array of std::pair to store the indexes of the path taken to reach the optimal solution.
Reconstructing the solution
For reconstructing the solution, declare path to store the last path taken to arrive at the optimal solution.
std::pair<int,int> path[M][N]
In your inner loop, everytime T[i][j] is computed, also compute path[i][j]
if (i == 0 && j > 0) {
T[0][j] += T[0][j - 1];
path[0][j] = std::make_pair(0, j - 1);
}
else if (j == 0 && i > 0) {
T[i][0] += T[i - 1][0];
path[i][0] = std::make_pair(i - 1, 0);
}
else if (i > 0 && j > 0) {
if (T[i - 1][j] < T[i][j - 1]) {
T[i][j] += T[i - 1][j];
path[i][j] = std::make_pair(i - 1, j);
} else {
T[i][j] += T[i][j - 1];
path[i][j] = std::make_pair(i, j - 1);
}
}
Finally, using the path array reconstruct the solution using a recursive function as follows (it can also be converted to an iterative solution)
void printPath(int i, int j, std::pair<int,int> path[M][N], int cost[M][N])
{
if (!i && !j) {
cout << cost[i][j] << ' ';
return;
}
printPath(path[i][j].first, path[i][j].second, path, cost);
cout << cost[i][j] << ' ';
}
Demo: here
I took some days to code 2048 game. And now I made most of the functions but one, testing whether the game is over. To code this game, my idea is to merge the same numbers first with the function up(down, left or right)_merge and make all the numbers go to the arrow direction that user presses with the function all_go_up(down, left or right). And then add a new number with the add_new_number function.
Here are some piece of those code I mentioned above:
void up_merge()
{
for(int i = 1; i < 4; i++) {
for(int j = 0; j < 4; j++) {
if(grid[i][j] > 0 && grid[i - 1][j] == grid[i][j]) {
while(grid[i - 1][j] == grid[i][j]) {
grid[i - 1][j] *= 2;
grid[i][j] = 0;
}
}
else if(grid[i][j] > 0 && grid[i - 1][j] == 0 && grid[i - 2][j] == grid[i][j]) {
while(grid[i - 2][j] == grid[i][j]) {
grid[i - 2][j] *= 2;
grid[i][j] = 0;
}
}
else if(grid[i][j] > 0 && grid[i - 1][j] == 0 && grid[i - 2][j] == 0 && grid[i - 3][j] == grid[i][j]) {
while(grid[i - 3][j] == grid[i][j]) {
grid[i - 3][j] *= 2;
grid[i][j] = 0;
}
}
}
}
}
void all_go_up()
{
for(int i = 3; i > 0; i--) {
for(int j = 0; j < 4; j++) {
if(grid[i][j] > 0 && grid[i - 1][j] == 0) {
grid[i - 1][j] = grid[i][j];
grid[i][j] = 0;
}
for(int k = 3; k > 0; k--) {
if(grid[k][j] > 0 && grid[k - 1][j] == 0) {
grid[k - 1][j] = grid[k][j];
grid[k][j] = 0;
}
}
}
}
}
bool add_new_number(int num)
{
int n = rand() % 2 + 1;
int newnumber = 1 << n;
int r, c;
switch(num) {
case 1: //up
r = rand() % 2 + 2;
c = rand() % 4;
break;
case 2: //down
r = rand() % 2;
c = rand() % 4;
break;
case 3: //left
r = rand() % 4;
c = rand() % 2 + 2;
break;
case 4: //right
r = rand() % 4;
c = rand() % 2;
break;
}
do {
if(check_empty() == 1) {
if(grid[r][c] == 0) {
grid[r][c] = newnumber;
return false;
}
if(grid[r][c] != 0) {
switch(num) {
case 1: //up
r = rand() % 2 + 2;
c = rand() % 4;
break;
case 2: //down
r = rand() % 2;
c = rand() % 4;
break;
case 3: //left
r = rand() % 4;
c = rand() % 2 + 2;
break;
case 4: //right
r = rand() % 4;
c = rand() % 2;
break;
}
}
}
else {
return false;
}
} while(true);
}
I have some other functions to check whether the grid is full and so on. I also tried use some while() and for() to do this, too. But I do not know where I get wrong to code the function to test whether the game is over.
I hope I express my problem well. Hoping to get some suggestions to code the test_fail function without changing too much of my code. Thanks.
With all the respect, your code looks totally unreadable. Consider functional approach where you compose few smaller function to break down more complex problem. I am going to demonstrate this in Typescript but it would be very similar in C++. In this way the code is I believe self-explanatory.
type Board = number[][]
function isGameOver(board: Board) {
if (hasEmptySpace(board)) return false
return checkHorizontalGameOver(board) && checkVerticalGameOver(board)
}
function hasEmptySpace(board: Board) {
for (let r = 0; r < NUM_ROWS; r++) {
for (let c = 0; c < NUM_COLS; c++) {
if (board[r][c] === 0) return true
}
}
return false
}
function checkHorizontalGameOver(board: Board) {
for (let i = 0; i < NUM_ROWS; i++) {
for (let j = 0; j < NUM_COLS - 1; j++) {
if (board[i][j] === board[i][j + 1]) return false
}
}
return true
}
function checkVerticalGameOver(board: Board) {
for (let i = 0; i < NUM_ROWS - 1; i++) {
for (let j = 0; j < NUM_COLS; j++) {
if (board[i][j] === board[i + 1][j]) return false
}
}
return true
}
I understand it's 5 years ago as I am reading now and your skills in programming are far far better, but still - I will post it here for people who might come across this so it can possibly help them.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Ok, so I have this code(declarations are global). It is basically a simple chess program and this part of the program tries to assess which fields are threatened by black pieces at a certain point in time. If a field is threatened, the c3[][] value of it goes from 0 to 1. The problem is that even after I made 100% sure the if conditions are met, the program would still refuse to set the c3[][] values to 1. And even worse, the if(c2[I][J]==9||c2[I][J]==10) partworks fine, which makes it even harder for me to identify the problem. I can provide the whole source code if necessary.
void atacalb()
{
int I,J;
for(I=1;I<=8;I++)
for(J=1;J<=8;J++)
{if(c2[I][J]==7){c3[I+1][J+1]=1,c3[I+1][J-1]=1;}
if(c2[I][J]==8){c3[I+2][J+1]=1,c3[I+2][J-1]=1,c3[I+1][J+2]=1,c3[I-1][J+2]=1,c3[I-2][J+1]=1,c3[I-2][J-1]=1,c3[I+1][J-2]=1,c3[I-1][J-2]=1;}
int z,x,ok;
for(I=1;I<=8;I++)
for(J=1;J<=8;J++)
if(c2[I][J]==9||c2[I][J]==10)
{
z=I,x=J,ok=1;
while((z<=8||x<=8)&&ok)
{z++,x++;
if(c2[z][x]==0)c3[z][x]=1;
else {c3[z][x]=1,ok=0;}
}
z=I,x=J,ok=1;
while((z<=8||x>=1)&&ok)
{i++,j--;
if(c2[z][x]==0)c3[z][x]=1;
else {c3[z][x]=1,ok=0;}
}
z=I,x=J,ok=1;
while((z>=1||x>=1)&&ok)
{z--,x--;
if(c2[z][x]==0)c3[z][x]=1;
else {c3[z][x]=1,ok=0;}
}
z=I,x=J,ok=1;
while((z>=1||x<=8)&&ok)
{z--,x++;
if(c2[z][x]==0)c3[z][x]=1;
else {c3[z][x]=1,ok=0;}
}
}
if(c2[I][J]==12||c2[I][J]==10)
{z=I,x=J,ok=1;
while(x<=8&&ok==1)
{x++;
if(c2[z][x]==0)c3[z][x]=1;
else {c3[z][x]=1,ok=0;}
}
z=I,x=J,ok=1;
while(z<=8&&ok==1)
{z++;
if(c2[z][x]==0)c3[z][x]=1;
else {c3[z][x]=1,ok=0;}
}
z=I,x=J,ok=1;
while(z>=1&&ok==1)
{z--;
if(c2[z][x]==0)c3[z][x]=1;
else {c3[z][x]=1,ok=0;}
}
z=I,x=J,ok=1;
while(x>=1&&ok==1)
{x--;
if(c2[z][x]==0)c3[z][x]=1;
else {c3[z][x]=1,ok=0;}
}
}
}
}
int main()
{//some code
atacalb();
//some more code
}
Using proper indention and bracket placement is key here! I stripped done all the code wich actually processes stuff and just left loops and if-statements in for readability. I then properly indented the code how the compiler gets to see it
int I, J;
for(I = 1; I <= 8; I++)
for(J = 1; J <= 8; J++) {
if(c2[I][J] == 7) {
}
if(c2[I][J] == 8) {
}
for(I = 1; I <= 8; I++)
for(J = 1; J <= 8; J++) /*!*/
if(c2[I][J] == 9 || c2[I][J] == 10) { ///< only this gets processed by the loop
while((z <= 8 || x <= 8) && ok){
if(c2[z][x] == 0) {
}
else {
}
}
while((z <= 8 || x >= 1) && ok) {
if(c2[z][x] == 0) {
}
else {
}
}
while((z >= 1 || x >= 1) && ok) {
if(c2[z][x] == 0) {
}
else {
}
}
while((z >= 1 || x <= 8) && ok) {
if(c2[z][x] == 0) {
}
else {
}
}
}
if(c2[I][J] == 12 || c2[I][J] == 10) { ///< not this
while(x <= 8 && ok == 1) {
if(c2[z][x] == 0) {
}
else {
}
}
while(z <= 8 && ok == 1) {
if(c2[z][x] == 0) {
}
else {
}
}
while(z >= 1 && ok == 1) {
if(c2[z][x] == 0) {
}
else {
}
}
while(x >= 1 && ok == 1) {
if(c2[z][x] == 0) {
}
else {
}
}
}
}
The problem is marked in the code above: the for loops (marked /*!*/) will not process the if-statement (if(c2[I][J] == 12 || c2[I][J] == 10)) only the first if statement after the marked loop. A way to fix this would be to either use a if-else-statement in this case or surround all your loops with curly braces as it should be done anyway. This is so that you can add and remove lines inside the brackets and can be sure that they will be processed as well. Also it makes the program flow more clear to the non-compiler-reader (i.e. the human being which tries to understand the code).
Also depending on the size of c2 which is probably an 8x8 array you should change the loop conditions. C++ uses 0-indexed arrays so an array with a size of 8 will be accessed by the indices from 0 - 7 not 1 - 8. So for example
for(I = 1; I <= 8; I++)
for(J = 1; J <= 8; J++) {
//...
should most likely be
for(I = 0; I < 8; I++) // smaller not smaller-equal
for(J = 0; J < 8; J++) {
// ...
You need to stop trying to play c++ golf if you want to debug basic problems in your code. Add white space where appropriate, including new lines.
Set a breakpoint on the line in question that sets your array location to 1, then step through the code with a watch on that variable, line by line. I can guarantee its not "refusing to set it." Its a branch in your code that you are not expecting to execute executing.
Question - A Little Elephant from the Zoo of Lviv likes lucky numbers very much. Everybody knows that the lucky numbers are positive integers whose decimal representation contains only the lucky digits 4 and 7. For example, numbers 47, 744, 4 are lucky and 5, 17, 467 are not.
Let F4(X) be the number of digits 4 in the decimal representation of X, and F7(X) be the number of digits 7 in the decimal representation of X. For example, F4(456) = 1, F4(444) = 3, F7(1) = 0, F7(747) = 2. The Little Elephant wants to know the largest product F4(X) ∙ F7(X), where L ≤ X ≤ R. In other words he wants to know the value
max{F4(X) ∙ F7(X) : L ≤ X ≤ R}.
1 <= L <= R <= 1018
Example:
1) For the range, 1 100 answer will be 1 {47,74}
2) 4199 6000 answer will be 4 {4747, 4477}
I feel my code is correct, but on submitting it's getting the verdict Wrong Answer. Can anybody help me find out exactly what is going wrong?
My algorithm cannot be wrong (it's very straightforward). I've double checked the implementation (it handles all possible cases). It's difficult to believe that it's going wrong for some input.
Here's the C++ code:
#include <cstdio>
#include <cstring>
using namespace std;
char buf1[20],buf2[20];
int *L, *R, *ans, len, ansn;
bool flagL, flagR;
inline int count(int n)
{
int a=0,c=0;
for(;a<len;a++) if(ans[a] == n) c++;
return c;
}
inline int max(int a, int b) { return a>b ? a:b; }
inline int min(int a, int b) { return a<b ? a:b; }
inline void f(int i, int n)
{
int a=0,n4=0,n7=0,t;
for(;a<=i;a++) if(ans[a] == 4) n4++; else if(ans[a] == 7) n7++;
while(n)
{
if(n4 == n7)
{
n4 += n/2;
n7 += (n-n/2);
break;
}
else if(n4 > n7)
{
t = min(n,n4-n7);
n -= t;
n7 += t;
}
else if(n7 > n4)
{
t = min(n,n7-n4);
n -= t;
n4 += t;
}
}
ansn = max(ansn,n4*n7);
}
void solve(int i, bool flagL, bool flagR)
{
while(i<len)
{
if(flagL && !flagR)
{
if(4 > L[i])
{
f(i-1,len-i);
return;
}
if(4 == L[i])
{
ans[i] = 4;
solve(i+1, 1, 0);
ans[i] = 7;
f(i,len-i-1);
return;
}
if(7 > L[i])
{
ans[i] = 7;
f(i,len-i-1);
return;
}
if(7 == L[i])
{
ans[i] = 8;
f(i,len-i-1);
ans[i] = 7;
i++;
continue;
}
// else
ans[i] = 9;
if(ans[i] > L[i])
{
f(i,len-i-1);
return;
}
else
{
i++;
continue;
}
}
if(!flagL && flagR)
{
if(7 < R[i])
{
f(i-1,len-i);
return;
}
if(7 == R[i])
{
ans[i] = 4;
f(i,len-i-1);
ans[i] = 7;
i++;
continue;
}
if(4 < R[i])
{
ans[i] = 4;
f(i,len-i-1);
return;
}
if(4 == R[i])
{
ans[i] = 3;
f(i,len-i-1);
ans[i] = 4;
i++;
continue;
}
// else
ans[i] = 0;
if(ans[i] < R[i])
{
f(i,len-i-1);
return;
}
else
{
i++;
continue;
}
}
if(flagL && flagR)
{
if(R[i] - L[i] == 1)
{
ans[i] = L[i];
solve(i+1,1,0);
ans[i]++;
solve(i+1,0,1);
return;
}
bool four = 4 > L[i] && 4 < R[i];
bool sev = 7 > L[i] && 7 < R[i];
if (four && sev)
{
f(i-1,len-i);
return;
}
else if (four && !sev)
{
ans[i] = 4;
f(i,len-i-1);
}
else if (!four && sev)
{
ans[i] = 7;
f(i,len-i-1);
}
if (L[i] == 4 || L[i] == 7 || R[i] == 4 || R[i] == 7)
{
if(L[i] == R[i]) { ans[i] = L[i]; i++; continue; }
if(L[i] == 4 && R[i] == 7)
{
ans[i] = 4;
solve(i+1,1,0);
ans[i] = 7;
solve(i+1,0,1);
ans[i] = 5;
f(i,len-i-1);
return;
}
if(R[i] - L[i] >= 2)
{
ans[i] = L[i]+1;
f(i,len-i-1);
if(L[i] == 4 || L[i] == 7)
{
ans[i] = L[i];
solve(i+1,1,0);
}
if(R[i] == 4 || R[i] == 7)
{
ans[i] = R[i];
solve(i+1,0,1);
}
return;
}
}
else
{
if (R[i] - L[i] >= 2)
{
ans[i] = L[i]+1;
f(i,len-i-1);
return;
}
ans[i] = L[i];
}
}
i++;
} // end of while
ansn = max(ansn, count(4)*count(7));
}
int main()
{
int a,t; scanf("%d\n",&t);
while(t--) // test cases
{
scanf("%s %s",&buf1,&buf2);
len = strlen(buf2);
L = new int[len];
R = new int[len];
ans = new int[len];
for(a=0;a<len;a++) R[a] = buf2[a]-48;
for(a=0;a<len-strlen(buf1);a++) L[a] = 0;
int b=a;
for(;a<len;a++) L[a] = buf1[a-b]-48;
flagL = flagR = 1; ansn = 0;
solve(0,1,1);
printf("%d\n",ansn);
}
return 0;
}
The algorithm:
Firstly, put the digits of L,R in arrays L[],R[] of length = no. of digits in R. And initialize an array ans[] for keeping track of the answer integer (integer for which F4(ans)*F7(ans) is maximum).
Pad L by 0 on the left, to make it equal to R in length. (so 1,100 becomes 001,100)
This is done in main() itself, before making a call to solve()
The real logic:
Run a loop, for i in range(0,len(R))
For each i, compare L[i] and R[i]
Variables flagL and flagR tell you whether or not, you need to check L and R respectively.
Supposing the L[], R[] is initially:
238 967
First we need to check both of them starting from 0th index (hence solve(0,1,1) or solve(0,true,true) ).
Now 4 and 7 both fall between L[0] and R[0]. So any permutation of {4,7} can be put in the 3 digits, without ans[] going out of range [L,R]. So answer will be 2.
If the range would have been:
238 and 545
Only 4 would fall in between 2 and 5, so we shall put 4 in ans[0], and any permutation of {4,7} can be put in the remaining places. So answer is again 2.
What if the range is:
238 and 410
Neither 4 nor 7 fall in between L[0] and R[0].
But note that R[0] is 4.
So we shall now have 2 choices to put, 4 and L[0]+1 (this is where recursion comes in)
Why L[0]+1 ? Because if we put L[0]+1 in ans[0], ans[0] would fall in between L[0] and R[0] (for this R[0] - L[0] >= 2) and whatever we put in the remaining digits, ans[] would never go out of range. But we also have to check with ans[0] being 4. In the last example, it won't help, but it would if R was >= 477.
So the answer would be 1. (2 if R was >= 477)
Let's discuss another example:
Range: 4500 5700
Because R[0] and L[0] differ by only 1, we will have to check for both, once for ans[i] = L[i], then ans[i] = R[i] (or ans[i]++ )
Now if we check for ans[i] = 4, we won't have to compare ans[i] and R[i] anymore, since ans[0] < R[0], hence ans will always be < R. So we call solve() recursively like this: solve(i+1, true, false)
Next time, when ans[0] = R[0], then we won't have to compare ans with L (since ans > L, whatever we put in the remaining 2 places). Then we call solve() like this: solve(i+1, false, true).
You get the idea of how it's working, and also, if you look at my code, no possible test case is being left out. I don't know why I'm getting a WA.
PS: Andrew pointed out the mistake. The order of conditions was wrong. The if block 4 == L[i] should have come before the if block 7 > L[i]. Now the code works correctly.
if(7 > L[i]) // 7 > 4 ?
{
ans[i] = 7;
f(i,len-i-1);
return;
}
if(4 == L[i]) // how is this ever reachable?
{
ans[i] = 4;
solve(i+1, 1, 0);
ans[i] = 7;
f(i,len-i-1);
return;
}
I think you mean:
- if(7 > L[i])
+ if(7 < L[i])