Difference between the implementation? - algorithm

So recently I stumbled across a query i.e.
code 1:
for(long i = 1; i <= m; i++) {
long j = (fullsum - 2*(sum -i))/2;
if(j >= m+1 && j <=n) {
swaps++;
}
}
code 2:
for(long i = 1; i <= m; i++) {
for(long j = m+1; j <=n ; j++) {
if(sum - i + j == fullsum - sum -j + i) {
swaps++;
break;
}
}
}
Where fullsum = n*(n+1)/2, sum = m*(m+1)/2
1 <= N <= 10^9
1 <= M < N
Now my question here is that both the codes seem identical to me(logic wise) but Code 2 is giving correct output while code 1 is not.
Can anyone please tell me the difference between the codes, further why code2 is giving the correct output while code1 is not and what is the correct way of implementing code 1?

Rewriting if(sum - i + j == fullsum - sum -j + i), we get
if(2*j == fullsum - 2*(sum-i))
In the first code, the value you are assigning to j is
long j = (fullsum - 2*(sum -i))/2;
The issue is pretty clear: division truncation is causing the incorrect results. Let's say that fullsum - 2*(sum-i) = 45 for some case, and j=22. Now, the second condition will be false, since 2*j != fullsum - 2*(sum-i).
However, for the first condition, (fullsum - 2*(sum -i))/2 has a value of 45/2 = 22 (floor division), so the condition j = (fullsum - 2*(sum -i))/2 will be counted as a valid result when it shouldn't have been.

Related

Assuming that n is a positive even integer, what will be the value of x right after this segment of code is run?

x = 0;
for (i = 1; i <= n/2; i++) {
for (j = 1; j <=n; j++) {
if (j > i)
x++;
}
}
I'm trying to predict the value of x by capturing a summation but I'm kind of stuck because I know that for each iteration of the first for loop, the summation changes for the inner loop. For example if we assume x is 10, after the first completion of the inner loop, x would have 9, then after the 2nd completion, we add 8 to x, then 7, 6, etc. The final value of x would be 35. How would I represent this in a cohesive equation for any positive even integer n?
Skip to the end for a simple equation; here I show the steps you might take.
First, here's the original code:
x = 0;
for (i = 1; i <= n/2; i++) {
for (j = 1; j <=n; j++) {
if (j > i)
x++;
}
}
We can start j at i+1 to skip a lot of pointless loops
x = 0;
for (i = 1; i <= n/2; i++) {
for (j = i+1; j <=n; j++) {
if (j > i)
x++;
}
}
Then instead of adding 1 on each of n-i loops, we can just add n-i.
x = 0;
for (i = 1; i <= n/2; i++) {
x += (n-i)
}
That's the same as this (just writing out what we're adding in the loops):
x = (n-1) + (n-2) + ... + (n - n/2)
We can pull out the n's.
x = n * (n/2) - 1 - 2 - 3 - ... - n/2
The final simplification is for the summation of 1 through n/2.
x = n * (n/2) - ((n/2) * (n/2 + 1))/2

How to convert this recursive function to a dp based solution?

This is the recursive function
def integerPartition(m, n):
if(n==0):
return 0
if(m ==0):
return 1
if(m<0):
return 0
return integerPartition(m,n-1) + integerPartition(m-n,n)
and this is what i have done in c++
// n -> no. of persons
// m -> amount of money to be distributed
// dp table of order (n+1)*(m+1)
long long int dp[n+1][m+1] ;
//initializing values to 0
for(i = 0; i<=n ; i++)
for(j = 0; j<= m ; j++)
dp[i][j] = 0;
Print(n,m,dp);
cout << "\n";
//Case 1 - if there is no persons i.e n = 0 answer will be 0
//Case 2 - if there is no money i.e. m = 0 there is only 1 way answer will be 1
for ( i = 1; i<= n ; i++ )
dp[i][0] = 1;
dp[i][i] = 1;
Print(n,m,dp);
for ( i = 1; i<= n ; i++){
for ( j = 1; j<= m ; j++){
dp[i][j] = dp[i][j-1] ;
if(i>=j){
dp[i][j] += dp[i-j][j];
}
// else if(i==j){
// dp[i][j] += 1;
// }
}
}
but the answers i am getting are not matching with the recursive one i don't understand what am i missing if anyone can please help me to correct i will be thankful since i have just started with dynamic programming i really am not able to figure it out
Some issues:
You seem to use non-local variables for your for loops. This is bad practice and can lead to errors that are difficult to debug. Instead
do for (int i = 1; ...etc.
dp[i][i] = 1; is not part of the for loop. You would have detected this if you would have defined i only as a variable local to the for loop.
It is good practice to always use braces for the body of a for loop (also if, else, ...etc), even if you would only have one
statement in the body.
dp[i][i] = 1; is also a bad assignment: it just is not true that integerPartition(i, i) always returns 1. It happens to be true
for small values of i, but not when i is greater than 3. For instance, integerPartition(4, 4) should return 5.
Just remove this line.
In the final nested for loop you are mixing up the row/column in your dp array. Note that you had reserved the first dimension for n and the second dimension for m, so opposite to the parameter order.
That is fine, but you do not stick to that decision in this for loop. Instead of dp[i][j-1] you should have written dp[i-1][j], and instead of dp[i-j][j] you should have
written dp[i][j-i]. And so the if condition should be adapted accordingly.
There is no return statement in your version, but maybe you just forgot to include it in the question. It should be
return dp[n][m];
Here is the corrected code:
long long int dp[n+1][m+1];
for(int i = 0; i <=n; i++) {
for(int j = 0; j <= m; j++) {
dp[i][j] = 0;
}
}
for (int i = 1; i <= n; i++) {
dp[i][0] = 1;
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m ; j++) {
dp[i][j] = dp[i-1][j];
if (j >= i) {
dp[i][j] += dp[i][j-i];
}
}
}
return dp[n][m];
Not sure that this technically is DP, but if your goal is to get the benefits of DP, memorization might be a better approach.
The idea is made up of 2 parts:
At the start of each call to integerPartition, look up in a table (your dp will do nicely) to see if that computation has already been done, and if it has, just return the value stored in the table.
Just before any point where integerPartition is to return a value, store it in the table.
Note that this means you don't need to try to "pivot" the original code -- it proceeds as it did originally, so you are almost guaranteed to get the same results, but without as much unnecessary re-computation (at the code of extra storage).
so, basis of your code comment,
I am going to assume you only want 1 when n > 0 and m = 0 according to your recursive code, but in dp code, you interchanged them, that is i go to upto n, and j go upto m
so updating your code, try to find the mistake
// n -> no. of persons
// m -> amount of money to be distributed
// dp table of order (n+1)*(m+1)
long long int dp[n+1][m+1] ;
//initializing values to 0
for(i = 0; i<=n ; i++)
for(j = 0; j<= m ; j++)
dp[i][j] = 0;
Print(n,m,dp);
cout << "\n";
//Case 1 - if there is no persons i.e n = 0 answer will be 0
//Case 2 - if there is no money i.e. m = 0 there is only 1 way answer will be 1
for ( i = 1; i<= n; i++){
dp[i][0] = 0;
}
for(int j = 1; j <= m; j++){
dp[0][j] = 1;
}
Print(n,m,dp);
for ( i = 1; i<= n ; i++){
for ( j = 1; j<= m ; j++){
dp[i][j] = dp[i][j-1] ;
if(i>=j){
dp[i][j] += dp[i-j][j];
}
// else if(i==j){
// dp[i][j] += 1;
// }
}
}

What AI technique or something else should I use on this logic problem?

for didactic purposes I'm trying to complete this challenge:
A random 3 digit number is generated (1-9) the Char sequence is DESC, for exemple "123" is a invalid number generated cause 1 > 2 and 2 > 3;
"321" is valid.
when you try to guess the number it returns C for correct Char in exact placement and N for correct Char in wrong placement, eg:
randomly generated "961"
algorithm try "321" and XPTO returns C = 1 and N = 0
algorithm try "654" and XPTO returns C = 0 and N = 1
The objective is get C=3 efficiently with less tries as possible, don't even know what kind of AI technique I need to learn about, Any tip or recommendation?
After the hint of #juvian I built an js solution
First create a List:
function generateList(){
List = new Array();
for (i = 1; i <= 7; i++) {
for (j = i+1; j <= 8; j++) {
for (k = j+1; k <= 9; k++) {
List.push(""+k+j+i);}}}
WriteResult(List.length,List[0]);
}
Then make the tests and exclude from List the "not possible" combinations
for( var i = List.length-1; i >= 0; i--){
var C = Number(document.getElementById("C").value);
var N = Number(document.getElementById("N").value);
var Guess = ""+Number(document.getElementById("Guess").value);
var CountC = 0
var CountN = 0
for( var j = 0; j < 3; j++)
{
if (Guess.substr(j, 1) == List[i].substr(j, 1)) {CountC++;}
else if (List[i].split(Guess.substr(j, 1)).length > 1) {CountN++;}
}
console.log(List[i]+" C:"+CountC+" N:"+CountN);
if (CountC != C || CountN != N) {List.splice(i, 1); }
}
WriteResult(List.length,List[0]);
}

select k values at time and flip them, find minimum cost to make all array values same equal to 1

Given a array containing only 0 and 1 and a integer value k.
You should choose k digits at time and flip all of them. Find minimum cost for making all values same. If it is not possible then give -1.
This is a simple greedy problem. I am assuming you can't flip less than k digits any time.
Find minimum cost for making all values same.
To solve this, first we will try to make all values 1 and then we'll try to make all values 0. Between these, which will take minimum steps will be our answer.
Here is my pseudo-code. The pseudo-code is self-explanatory and that's why I am not adding explanation. I am giving code for making all values 1, hope you can do for both.
int cnt = 0;
for(int i = 0; i < arr.length() - k + 1; i++) {
if(arr[i] == '1') {
continue;
}
for(int j = 0; j < k; j++) {
arr[i + j] = (arr[i + j] == '0') ? '1' : '0';
}
cnt++;
}
bool flag = true;
for(int i = 0; i < arr.length(); i++) {
if(arr[i] == '0') {
flag = false;
break;
}
}
if(flag) {
print(cnt);
} else {
print("-1");
}

Nested loops, how many times run and complexity

I have these 2 codes, the question is to find how many times x=x+1 will run in each occasion as T1(n) stands for code 1 and T2(n) stands for code 2. Then I have to find the BIG O of each one, but I know how to do it, the thing is I get stuck in finding how many times ( as to n of course ) will x = x + 1 will run.
CODE 1:
for( i= 1; i <= n; i++)
{
for(j = 1; j <= sqrt(i); j++)
{
for( k = 1; k <= n - j + 1; k++)
{
x = x + 1;
}
}
}
CODE 2:
for(j = 1; j <= n; j++)
{
h = n;
while(h > 0)
{
for (i = 1; i <= sqrt(n); i++)
{
x = x+1;
}
h = h/2;
}
}
I am really stuck, and have read already a lot so I ask if someone can help me, please explain me analytically.
PS: I think in the code 2 , this for (i = 1; i <= sqrt(n); i++) will run n*log(n) times, right? Then what?
For code 1 you have that the number of calls of x=x+1 is:
Here we bounded 1+sqrt(2)+...+sqrt(n) with n sqrt(n) and used the fact that the first term is the leading term.
For code 2 the calculations are simpler:
The second loop actually goes from h=n to 0 by iterating h = h/2 but you can see that this is the same as going from 1 to log n. What we used is the fact the j, t, i are mutually independent (analogously just like we can write that sum from 1 to n of f(n) is just nf(n)).

Resources