I'm trying to solve a problem from hacker rank over here.
The question is:
So to solve this, I tried with a simple maths equation:
4x + 7y = lucky_number
For example, to check 15 is a lucky_number or not, I could do start with x, y values 0 and substituting in the above equation until its equal or greater than (if so stop and say its not lucky number)
The above logic works fine. But the problem is with big number, imagine to check number 966888032206353 lucky or not, starting with x,y to 0 wont be an efficient idea.
Any guidance to it?
All numbers from 7*4=28 up (in fact even all mumbers from 18 up) are lucky, for the rest just precompute a smalll table.
Another way to think of it: All you need to do is plot the line
7y = -4x + 966888032206353
and identify any points where both x and y are integers.
So, you don't need a nested loop. Instead:
Iterate y as an integer. for y=0; y<966888032206353 / 7; y++
For each iteration, solve for x, using floating point math.
If x is an integer, the number is lucky.
This will require about 138T iterations.
Here's my code that I submitted to Hackerrank.
#include <bits/stdc++.h>
using namespace std;
int q; long long n; bool dp[1009];
int main() {
cin >> q;
dp[0] = true;
for(int i = 1; i <= 1000; i++) {
if(i >= 4 && dp[i - 4]) dp[i] = true;
if(i >= 7 && dp[i - 7]) dp[i] = true;
}
while(q--) {
cin >> n;
if(n >= 1000 || dp[n]) cout << "Yes" << endl;
else cout << "No" << endl;
}
}
This is dynamic programming, but if n >= 28 it is always ok.
One of your problems is that your problem description is very incomplete. You can infact represent any integer number as 4x + 7y, if you only allowed negative x and y. For example, 1 = 4*2 + (-1)*7 and you can get a solution for any number by multiplying with that factor.
I guess the best solution from an algorithmics point of view is to use dynamic programming. You can simply start checking numbers whether they are lucky in your sense or not. As soon as you find 4 consequtive lucky numbers, you can stop, because any number afterwards will be lucky by just adding 4 an appropriate number of times. I guess you will find a sequence of 4 consequtive lucky numbers very early.
Related
So, I'm trying to create a random vector (think geometry, not an expandable array), and every time I call my random vector function I get the same x value, though y and z are different.
int main () {
srand ( (unsigned)time(NULL));
Vector<double> a;
a.randvec();
cout << a << endl;
return 0;
}
using the function
//random Vector
template <class T>
void Vector<T>::randvec()
{
const int min=-10, max=10;
int randx, randy, randz;
const int bucket_size = RAND_MAX/(max-min);
do randx = (rand()/bucket_size)+min;
while (randx <= min && randx >= max);
x = randx;
do randy = (rand()/bucket_size)+min;
while (randy <= min && randy >= max);
y = randy;
do randz = (rand()/bucket_size)+min;
while (randz <= min && randz >= max);
z = randz;
}
For some reason, randx will consistently return 8, whereas the other numbers seem to be following the (pseudo) randomness perfectly. However, if I put the call to define, say, randy before randx, randy will always return 8.
Why is my first random number always 8? Am I seeding incorrectly?
The issue is that the random number generator is being seeded with a values that are very close together - each run of the program only changes the return value of time() by a small amount - maybe 1 second, maybe even none! The rather poor standard random number generator then uses these similar seed values to generate apparently identical initial random numbers. Basically, you need a better initial seed generator than time() and a better random number generator than rand().
The actual looping algorithm used is I think lifted from Accelerated C++ and is intended to produce a better spread of numbers over the required range than say using the mod operator would. But it can't compensate for always being (effectively) given the same seed.
I don't see any problem with your srand(), and when I tried running extremely similar code, I did not repeatedly get the same number with the first rand(). However, I did notice another possible issue.
do randx = (rand()/bucket_size)+min;
while (randx <= min && randx >= max);
This line probably does not do what you intended. As long as min < max (and it always should be), it's impossible for randx to be both less than or equal to min and greater than or equal to max. Plus, you don't need to loop at all. Instead, you can get a value in between min and max using:
randx = rand() % (max - min) + min;
I had the same problem exactly. I fixed it by moving the srand() call so it was only called once in my program (previously I had been seeding it at the top of a function call).
Don't really understand the technicalities - but it was problem solved.
Also to mention, you can even get rid of that strange bucket_size variable and use the following method to generate numbers from a to b inclusively:
srand ((unsigned)time(NULL));
const int a = -1;
const int b = 1;
int x = rand() % ((b - a) + 1) + a;
int y = rand() % ((b - a) + 1) + a;
int z = rand() % ((b - a) + 1) + a;
A simple quickfix is to call rand a few times after seeding.
int main ()
{
srand ( (unsigned)time(NULL));
rand(); rand(); rand();
Vector<double> a;
a.randvec();
cout << a << endl;
return 0;
}
Just to explain better, the first call to rand() in four sequential runs of a test program gave the following output:
27592
27595
27598
27602
Notice how similar they are? For example, if you divide rand() by 100, you will get the same number 3 times in a row. Now take a look at the second result of rand() in four sequential runs:
11520
22268
248
10997
This looks much better, doesn't it? I really don't see any reason for the downvotes.
Your implementation, through integer division, ignores the smallest 4-5 bit of the random number. Since your RNG is seeded with the system time, the first value you get out of it will change only (on average) every 20 seconds.
This should work:
randx = (min) + (int) ((max - min) * rand() / (RAND_MAX + 1.0));
where
rand() / (RAND_MAX + 1.0)
is a random double value in [0, 1) and the rest is just shifting it around.
Not directly related to the code in this question, but I had same issue with using
srand ((unsigned)time(NULL)) and still having same sequence of values being returned from following calls to rand().
It turned out that srand needs to called on each thread you are using it on separately. I had a loading thread that was generating random content (that wasn't random cuz of the seed issue). I had just using srand in the main thread and not the loading thread. So added another srand ((unsigned)time(NULL)) to start of loading thread fixed this issue.
I am solving this problem on CSES.
Given n planets, with exactly 1 teleporter on each planet which teleports us to some other planet (possibly the same), we have to solve q queries. Each query is associated with a start planet, x and a number of teleporters to traverse, k. For each query, we need to tell where we would reach after going through k teleporters.
I have attempted this problem using the binary lifting concept.
For each planet, I first saved the planets we would reach by going through 20, 21, 22,... teleporters.
Now, as per the constraints (esp. for k) provided in the question, we need only store the values till 231.
Then, for each query, starting from the start planet, I traverse through the teleporters using the data in the above created array (in 1) to mimic the binary expansion of k, the number of teleporters to traverse.
For example, if k = 5, i.e. (101)2, and the initial planet is x, I first go (001)2 = 1 planet ahead, using the array, let's say to planet y, and then (100)2 = 4 planets ahead. The planet now reached is the required result to the query.
Unfortunately, I am receiving TLE (time limit exceeded) error in the last test case (test 12).
Here's my code for reference:
#define inp(x) ll x; scanf("%lld", &x)
void solve()
{
// Inputting the values of n, number of planets and q, number of queries.
inp(n);
inp(q);
// Inputting the location of next planet the teleporter on each planet points to, with correction for 0 - based indexing
vector<int> adj(n);
for(int i = 0; i < n; i++)
{
scanf("%d", &(adj[i]));
adj[i]--;
}
// maxN stores the maximum value till which we need to locate the next reachable plane, based on constraints.
// A value of 32 means that we'll only ever need to go at max 2^31 places away from the planet in query.
int maxN = 32;
// This array consists of the next planet we can reach from any planet.
// Specifically, par[i][j] is the planet we get to, on passing through 2^j teleporters starting from planet i.
vector<vector<int>> par(n, vector<int>(maxN, -1));
for(int i = 0; i < n; i++)
{
par[i][0] = adj[i];
}
for(int i = 1; i < maxN; i++)
{
for(int j = 0; j < n; j++)
{
ll p1 = par[j][i-1];
par[j][i] = par[p1][i-1];
}
}
// This task is done for each query.
for(int i = 0; i < q; i++)
{
// x is the initial planet, corrected for 0 - based indexing.
inp(x);
x--;
// k is the number of teleporters to traverse.
inp(k);
// cur is the planet we currently are at.
int cur = x;
// For every i'th bit in k that is 1, the current planet is moved to the planet we reach to by moving through 2^i teleporters from cur.
for(int i = 0; (1 << i) <= k ; i++)
{
if(k & (1 << i))
{
cur = par[cur][i];
}
}
// Once the full binary expansion of k is used up, we are at cur, so (cur + 1) is the result because of the judge's 1 - based indexing.
cout<<(cur + 1)<<endl;
}
}
The code gives the correct output in every test case, but undergoes TLE in the final one (the result in the final one is correct too, just a TLE occurs). According to my observation the complexity of the code is O(32 * q + n), which doesn't seem to exceed the 106 bound for linear time code in 1 second.
Are there any hidden costs in the algorithm I may have missed, or some possible optimization?
Any help appreciated!
It looks to me like your code works (after fixing the scanf), but your par map could have 6.4M entries in it, and precalculating all of those might just get you over the 1s time limit.
Here are a few things to try, in order of complexity:
replace par with a single vector<int> and index it like par[i*32+j]. This will remove a lot of double indirections.
Buffer the output in a std::string and write it in one step at the end, in case there's some buffer flushing going on that you don't know about. I don't think so, but it's easy to try.
Starting at each planet, you enter a cycle in <= n steps. In O(n) time, you can precalculate the distance to the terminal cycle and the size of the terminal cycle for all planets. Using this information you can reduce each k to at most 20000, and that means you only need j <= 16.
I should resolve 16-Queens Problem in 1 second.
I used backtracking algorithm like below.
This code is enough to resolve N-Queens Problem in 1 second when the N is smaller than 13.
But it takes long time if N is bigger than 13.
How can I improve it?
#include <stdio.h>
#include <stdlib.h>
int n;
int arr[100]={0,};
int solution_count = 0;
int check(int i)
{
int k=1, ret=1;
while (k < i && ret == 1) {
if (arr[i] == arr[k] ||
abs(arr[i]-arr[k]) == abs(i-k))
ret = 0;
k++;
}
return ret;
}
void backtrack(int i)
{
if(check(i)) {
if(i == n) {
solution_count++;
} else {
for(int j=1; j<=n; j++) {
arr[i+1] = j;
backtrack(i+1);
}
}
}
}
int main()
{
scanf("%d", &n);
backtrack(0);
printf("%d", solution_count);
}
Your algorithm is almost fine. A small change will probably give you enough time improvement to produce a solution much faster. In addition, there is a data structure change that should let you reduce the time even further.
First, tweak the algorithm a little: rather than waiting for the check all the way till you place all N queens, check early: every time you are about to place a new queen, check if another queen is occupying the same column or the same diagonal before making the arr[i+1] = j; assignment. This will save you a lot of CPU cycles.
Now you need to speed up checking of the next queen. In order to do that you have to change your data structure so that you could do all your checks without any loops. Here is how to do it:
You have N rows
You have N columns
You have 2N-1 ascending diagonals
You have 2N-1 descending diagonals
Since no two queens can take the same spot in any of the four "dimensions" above, you need an array of boolean values for the last three things; the rows are guaranteed to be different, because the i parameter of backtrack, which represents the row, is guaranteed to be different.
With N up to 16, 2N-1 goes up to 31, so you can use uint32_t for your bit arrays. Now you can check if a column c is taken by applying bitwise and & to the columns bit mask and 1 << c. Same goes for the diagonal bit masks.
Note: Doing a 16 Queen problem in under a second would be rather tricky. A very highly optimized program does it in 23 seconds on an 800 MHz PC. A 3.2 GHz should give you a speed-up of about 4 times, but it would be about 8 seconds to get a solution.
I would change while (k < i && ret == 1) { to while (k < i) {
and instead of ret = 0; do return 0;.
(this will save a check every iteration. It might be that your compiler does this anyway, or some other performance trick, but this might help a bit).
My problem is as follows:
Given a number of 2n points, I can calculate the distance between all points
and get a symmetrical matrix.
Can you create n pairs of points, so that the sum of the distance of all pairs is
minimal?
EDIT: Every point has to be in one of the pairs. Which means that
every point is only allowed to be in one pair.
I have naively tried to use the Hungarian algorithm and hoped that it may give me an assignment, so that the assignments are symmetrical. But that obviously did not work, as I do not have a bipartite graph.
After a search, I found the Stable roommates problem, which seems to be similar to my problem, but the difference is, that it just tries to find a matching, but not to try to minimize some kind of distance.
Does anyone know a similar problem or even a solution? Did I miss something? The problem does actually not seem that difficult, but I just could not come up with an optimal solution.
There's a primal-dual algorithm due to Edmonds (the Blossom algorithm), which you really don't want to implement yourself if possible. Vladimir Kolmogorov has an implementation that may be suitable for your purposes.
Try network-flow. The max flow is the number of the pairs you want to create. And calculate the min cost of it.
now this isn't a guarantee but just a hunch.
you can find the shortest pair, match them, and remove it from the set.
and recurse until you have no pairs left.
It is clearly sub-optimal. but I have a hunch that the ratio of just how sub-optimal this is to the absolutely optimal solution can be bounded. The hope is to use some sub-modularity argument and bound it to something like (1 - 1 / e) fraction of the global optimal, but I wasn't able to do it. Maybe someone could take a stab at it.
There is a C++ memoization implementation in Competitive Programming 3 as follows (note maximum of N was 8):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
int N, target;
double dist[20][20], memo[1<<16];
double matching(int bitmask)
{
if (memo[bitmask] > -0.5) // Already computed? Then return the result if yes
return memo[bitmask];
if (bitmask == target) // If all students are already matched then cost is zero
return memo[bitmask] = 0;
double ans = 2000000000.0; // Infinity could also work
int p1, p2;
for (p1 = 0; p1 < 2*N; ++p1) // Find first non-matched point
if (!(bitmask & (1 << p1)))
break;
for (p2 = p1 + 1; p2 < 2*N; ++p2) // and pair it with another non-matched point
if (!(bitmask & (1 << p2)))
ans = min(ans, dist[p1][p2]+matching(bitmask| (1 << p1) | (1 << p2)));
return memo[bitmask] = ans;
}
and then the main method (driving code)
int main()
{
int i,j, caseNo = 1, x[20], y[20];
while(scanf("%d", &N), N){
for (i = 0; i < 2 * N; ++i)
scanf("%d %d", &x[i], &y[i]);
for (i = 0; i < 2*N - 1; ++i)
for (j = i + 1; j < 2*N; ++j)
dist[i][j] = dist[j][i] = hypot(x[i]-x[j], y[i]-y[j]);
// use DP to solve min weighted perfect matching on small general graph
for (i = 0; i < (1 << 16); ++i) memo[i] = -1;
target = (1 << (2 * N)) - 1;
printf("Case %d: %.2lf", caseNo++, matching(0));
}
return 0;
}
I need serious help dividing the positive numbers and the negative numbers.
I am to accumulate the total of the negative values and separately accumulate the total of the positive values. After the loop, you are then to display the sum of the negative values and the sum of the positive values.
The data is suppose to look like this:
-2.3 -1.9 -1.5 -1.1 -0.7 -0.3 0.1 0.5 0.9 1.3 1.7 2.1 2.5 2.9
Sum of negative values: -7.8 Sum of positive
values: 12
So far I have this:
int main () {
int num, num2, num3, num4, num5, sum, count, sum1;
int tempVariable = 0;
int numCount = 100;
int newlineCount = 0, newlineCount1 = 0;
float numCount1 = -2.3;
while (numCount <= 150)
{
cout << numCount << " ";
numCount += 2;
newlineCount ++;
if(newlineCount == 6)
{
cout<< " " << endl;
newlineCount = 0;
}
}
**cout << "" << endl;
while (numCount1 <=2.9 )
{
cout << numCount1 << " ";
numCount1 += 0.4;
newlineCount1 ++;
} while ( newlineCount1 <= 0 && newlineCount >= -2.3 );
cout << "The sum is " << newlineCount1 << endl;**
return 0;
}
I do not know C/C++ but here is a general idea of the loop assuming the values are coming from an array. (since I am unaware of how they are coming in, i.e. user input, etc.)
Logic:
Use a for loop structure opposed to a while, to loop over each element of the array.
Initialize two variables to keep count, positiveSum and negativeSum.
At each iteration of the element, check to see if it's greater than 0. That's how you can divide the positive and negative numbers accordingly.
If greater than zero, add the element onto the running positiveSum, else add it to the running sum of negativeSum.
When the loop finishes, positiveSum and negativeSum should have the calculated sum.
If this is homework, (I don't remember if the homework tag was there prior to the question, or was added on later) this pseudo code should point you in the right direction without explicitly doing the entire work for you.
Pseudo Java Code (not tested or compiled)
// as a good convention, I always initialize variables,
// for numbers I always use zero's.
double positiveSum, negativeSum = 0.0;
// assuming array holds the array of values.
for (i=0; i < array.length; i++) {
// if positive, add it to the count
if (array[i] > 0) positiveSum = positiveSum + array[i];
// else negative
else negativeSum = negativeSum + array[i];
}
Once it's completed, both positiveSum and negativeSum should hold the correct calculated sum.
If you have any questions along the way, I can edit my answer to help you achieve the correct answer, I wish I could give it away but that's what your responsibilities are for homework.
I would loop through each number individually, let's call it currentValue
if the number is negative, negativeNumberTotal += currentValue
else if positive, positiveNumberTotal += currentValue
You will get your individual totals that way. Very simple.
You are clearly overcomplicating the problem. First of all you don't need two separate loops for the numbers, as there is a constant 0.4 difference between them, even between -0.3 and 0.1. You only have to check if it's negative or not to know how to sum them up.
Loops are simpler if you use an integer as counter. As you want 14 numbers you can simply count from 0 to 13, and from that you can easily calculate the corresponding floating point value.
Example C# code:
double negSum = 0.0, posSum = 0.0;
for (int i = 0; i < 14; i++) {
double number = -2.3 + (double)i * 0.4;
if (number < 0) {
negSum += number;
} else {
posSum += number;
}
}
You can of course use a floating point number in the loop, but then you need to take into account the inexact nature of floating point numbers. You should make sure to use an ending interval that is something like halfway between the last number that you want and the next.
double negSum = 0.0, posSum = 0.0;
for (double number = -2.3; number < 3.1; number += 0.4) {
if (number < 0) {
negSum += number;
} else {
posSum += number;
}
}
Also, when repeatedly accumulating floating point numbers (like adding 0.4 over and over again), you also accumulate rounding errors. Most numbers can't be represented exactly as floating point numbers, so it's likely that you are actually adding something like 0.3999999999999994225 instead of 0.4 each iteration. It's not likely to add up to something that is enough to show up in this small example, but you should be aware of this effect so that you can anticipate it in situations with more numbers.
You have several magic numbers, whose purpose I'm not sure of, e.g numcount1 = -2.3 In general you want to avoid magic numbers.
You might want to give your variables more descriptive names than num1, num2, etc.
Could you explain more precisely what the parameters are for your assignment?
EDIT:
I've noticed that you are using very weird conditions to control your loop. You are continuing until numcount1 is = 2.9, which is a very fragile sort of setup. The first thing I would do in your shoes is to rewrite your program so that the loop terminates when there are no more numbers to add. (Alternatively, you could just make it stop after, say 12 values.)
EDIT AGAIN:
OK, how about this
int sumOfPos = 0, sumOfNeg = 0, currentValue = -2.3, terminationValue = 2.9;
while (currentValue <= terminationValue) {
if ( /* there is a missing condition here */ ) {
// need a statement here to increment your negative counter
} else {
// need a statement here to increment your positive counter
}
}
// put some statements here to do output
This is easily solvable with pure math:
lowerBound = -2.3
upperBound = 2.9
incAmount = 0.4
signChange = lowerBound % incAmount
numBelowChange = -(lowerBound-signChange)/incAmount
avgNegValue = -(numBelowChange+1)/2.0*incAmount + signChange
sumOfNegative = numBelowChange*avgNegValue
numAboveChange = (upperBound-signChange)/incAmount
avgPosValue = (numAboveChange+1)/2.0*incAmount + signChange
sumOfPositive = numAboveChange*avgPosValue + signChange
It's more accurate, and more efficient than looping and adding.
With the constants you provided,
signChange = 0.1
numBelowChange = 6.0
avgNegValue = -1.3
sumOfNegative = -7.8
numAboveChange = 7.0
avgPosValue = 1.7
sumOfPositive = 12.0
If you're unfamiliar with the % operator, x%y means "divide x by y and return the remainder". So 5%2=1
http://en.wikipedia.org/wiki/Modulo_operator
I'm not a programmer, but I thought it was best to keep the inside of a loop as lean as possible. This version works without any if statements inside the loop, just simple addition. It's late at night, and I've had a couple of whiskies, but I think this algorithm would work (it worked when I tried implementing it in python). It's psuedo code, so you'll have to write it up in yr language of choice:
neg_total =0
abs_total=0
loop with i in all_your_numbers
total += i
abs_total += abs(i)
end
neg_total=(total-abs_total)/2
pos_total=abs_Total+neg_Total
print "sum of negative values =", neg_total
print "sum of positive values =", pos_total
I'm not sure if this is good programming practice, I'm just chuffed that it worked. Points if you can explain how.