So I wanted to write code which solves this problem: "Collecting Beepers"
And I did:
int rec(int current, int beers)
{
if(beers == (1 << (numOfBeers + 1)) - 1) return cost(beerX[0], beerY[0], beerX[current], beerY[current]);
int optimal = 100000;
for(int i = 1; i <= numOfBeers; ++i)
{
if(((1 << i) & beers) == 0)
{
int newBeersSet = (1 << i) | beers;
int c = cost(beerX[current], beerY[current], beerX[i], beerY[i]);
int current = c + rec(i, newBeersSet);
optimal = min(optimal, current);
}
}
return optimal;
}
The strange thing is, that when I replace the part
int c = cost(beerX[current], beerY[current], beerX[i], beerY[i]);
int current = c + rec(i, newBeersSet);
with
int current = cost(beerX[current], beerY[current], beerX[i], beerY[i]) + rec(i, newBeersSet);
the logic is absolutely the same and yet my program crashes on the same (the one given in the problem desciption) input and the online judge gives wrong answer as a result from the program execution while with the original code it gives Accepted. Any ideas what could possibly be wrong?
That is propably because your variable "current" is overriden. Try:
int current2 = cost(beerX[current], beerY[current], beerX[i], beerY[i]) + rec(i, newBeersSet);
optimal = min(optimal, current2);
In this line you are using an uninitialized variable:
int current = cost(beerX[current], // ...
This declares a new variable current and then, before the variable has had a value assigned, uses it as index to beerX.
You probably meant:
int new_current = cost(beerX[current], // ...
which uses the existing current variable which was declared in the parameter list for the rec function.
Related
I am a C++ newbie.
Context: I found this third-party snippet of code that seems to work, but based on my (very limited) knowledge of C++ I suspect it will cause problems. The snippet is as follows:
int aVariable;
int anInt = 1;
int anotherInt = 2;
int lastInt = 3;
aVariable = CHAIN(anInt, anotherInt, lastInt);
Where CHAIN is defined as follows (this is part of a library):
int CHAIN(){ Map(&CHAIN, MakeProcInstance(&_CHAIN), MAP_IPTR_VPN); }
int _CHAIN(int i, int np, int p){ return ASMAlloc(np, p, &chainproc); }
int keyalloc[16384], kpos, alloc_locked, tmp[4];
int ASMAlloc(int np, int p, alias proc)
{
int v, x;
// if(alloc_locked) return 0 & printf("WARNING: you can declare compound key statements (SEQ, CHAIN, EXEC, TEMPO, AXIS) only inside main() call, and not during an event.\xa");
v = elements(&keyalloc) - kpos - 4;
if(v < np | !np) return 0; // not enough allocation space or no parameters
Map(&v, p); Dim(&v, np); // v = params array
keyalloc[kpos] = np + 4; // size
keyalloc[kpos+1] = &proc; // function
keyalloc[kpos+2] = kpos + 2 + np; // parameters index
while(x < np)
{
keyalloc[kpos+3+x] = v[x];
x = x+1;
}
keyalloc[kpos+3+np] = kpos + 3 | JUMP;
x = ASMFind(kpos);
if(x == kpos) kpos = kpos + np + 4;
return x + 1 | PROC; // skip block size
}
int ASMFind(int x)
{
int i, j, k; while(i < x)
{
k = i + keyalloc[i]; // next
if(keyalloc[i] == keyalloc[x]) // size
if(keyalloc[i+1] == keyalloc[x+1]) // proc
{
j = x-i;
i = i+3;
while(keyalloc[i] == keyalloc[j+i]) i = i+1; // param
if((keyalloc[i] & 0xffff0000) == JUMP) return x-j;
}
i = k;
}
return x;
}
EDIT:
The weird thing is that running
CHAIN(aVariable);
effectively executes
CHAIN(anInt, anotherInt, lastInt);
Somehow. This is what led me to believe that aVariable is, in fact, a pointer.
QUESTION:
Is it correct to store a parametrized function call into an integer variable like so? Does "aVariable" work just as a pointer, or is this likely to corrupt random memory areas?
You're calling a function (through an obfuscated interface), and storing the result in an integer. It might or might not cause problems, depending on how you use the value / what you expect it to mean.
Your example contains too many undefined symbols for the reader to provide any better answer.
Also, I think this is C, not C++ code.
I'm kind of inexperienced with C++, and I'm converting a program that I wrote in C to C++. I have a RollDice function that takes numbers that I read in from a text file and uses them to generate the number. This is the function in C:
void rollDice(Move *move, GameState *game_state) {
int diceNum1 = 0;
int diceNum2 = 0;
int randomNumber1 = 0;
int randomNumber2 = 0;
randomNumber1 = game_state->randomNums[game_state->current_roll]; //gets the random number from the array randomNum (which holds the numbers from the text file), at index "current_roll"
game_state->current_roll++; //increments so the next random number will be the next number in the array
diceNum1 = 1 + (randomNumber1 % (1 + 6 - 1));
randomNumber2 = game_state->randomNums[game_state->current_roll];
game_state->current_roll++;
diceNum2 = 1 + (randomNumber2 % (1 + 6 - 1));
move->dice_sum = diceNum1 + diceNum2;
printf("You rolled a %d!\n", move->dice_sum);
}
This works just how I want it to when I run it. Now, when converting my program to C++ I had to change things around. My parameters are now pass by reference and I made a vector to store the list of random numbers from the text file:
void rollDice(Move& move, GameState& game_state) {
std:: vector<int> randomNums = game_state.getRandomNums();
int current_roll = game_state.getCurrentRoll();
int diceNum1 = 0;
int diceNum2 = 0;
int randomNumber1 = 0;
int randomNumber2 = 0;
randomNumber1 = randomNums.at(current_roll);
current_roll++;
diceNum1 = 1 + (randomNumber1 % (1 + 6 - 1));
randomNumber2 = randomNums.at(current_roll);
current_roll++; //this line is grayed out and says "this value is never used"
diceNum2 = 1 + (randomNumber2 % (1 + 6 - 1));
move.dice_sum = diceNum1 + diceNum2;
std:: cout << "You rolled a " << move.dice_sum << "!\n";
}
My code is telling me that the second time I increment current_roll it is unused. This didn't happen for my C code, so why is it happening here and how can I fix it? I'm completely lost.
It's never used because you write to the variable, but never read from it. Having a variable that you never read is effectively meaningless.
Presumably your game_state.getCurrentRoll function returns an integer, when you store this, you store the value (rather than a reference to the value), thus incrementing it doesn't increment the current roll inside the game_state, instead you should add a function to your game_state called makeRoll for example which increments the game_states internal current_roll value.
This is different from your C code which increments the current_roll value directly using game_state->current_roll++ (alternatively you could make game_state.current_roll public and increment it the same way as in your C code).
From your comment I assume you have some class:
class GameState {
private:
int current_roll;
...
public:
int getCurrentRoll() {
return current_roll;
}
...
}
All you'd need to do is add another function to your class to increment the current_roll:
class GameState {
private:
int current_roll;
...
public:
int getCurrentRoll() {
return current_roll;
}
void makeRoll() {
current_roll++;
}
...
}
Then you can call it as normal.
Regarding your new issue in the comments regarding the error:
parameter type mismatch: Using 'unsigned long' for signed values of type 'int'.
This is because the signature of at is std::vector::at( size_type pos ); That is, it expects a value of type size_type which is an unsigned integer type, rather than int as you're using which is signed. This post may be helpful.
I'm pretty new to C++ and I have the following simple program:
int main()
{
int a = 5,b = 10;
int sum = a + b;
b = 6;
cout << sum; // outputs 15
return 0;
}
I receive always the output 15, although I've changed the value of b to 6.
Thanks in advance for your answers!
Execution of your code is linear from top to bottom.
You modify b after you initialize sum. This modification doesn't automatically alter previously executed code.
int sum = a + b; writes the result of adding a and b into the new variable sum. It doesn't make sum an expression that always equals the result of the addition.
There are already answers, but I feel that something is missing...
When you make an assignment like
sum = a + b;
then the values of a and b are used to calculate the sum. This is the reason why a later change of one of the values does not change the sum.
However, since C++11 there actually is a way to make your code behave the way you expect:
#include <iostream>
int main() {
int a = 5,b = 10;
auto sum = [&](){return a + b;};
b = 6;
std::cout << sum();
return 0;
}
This will print :
11
This line
auto sum = [&](){return a + b;};
declares a lambda. I cannot give a selfcontained explanation of lambdas here, but only some handwavy hints. After this line, when you write sum() then a and b are used to calculate the sum. Because a and b are captured by reference (thats the meaning of the &), sum() uses the current values of a and b and not the ones they had when you declared the lambda. So the code above is more or less equivalent to
int sum(int a, int b){ return a+b;}
int main() {
int a = 5,b = 10;
b = 6;
std::cout << sum(a,b);
return 0;
}
You updated the b value but not assigned to sum variable.
int main()
{
int a = 5,b = 10;
int sum = a + b;
b = 6;
sum = a + b;
cout << sum; // outputs 11
return 0;
}
example code:
const char* list[] = {"Elem_E", "Elem_T", "Elem_R", "Turtle", "Rabbit"};
const char ** patterns=0;
.
.
.
bool sec_run = false;
patterns = list;
process_data(patterns, sec_run);
process_data function:
process_data(const char **& pattern, bool sec_run){
.
.
some_variable=0;
for(int i; i < num_patterns;++i){
if(!sec_run){
some_variable = *pattern[i];
}
else{
if(/* list element contains "_" */)continue;
some_variable= /*letter after "_" */
}
if(some_variable == 'E') multiplier = 0;
else if(some_variable == 'T') multiplier = 1;
else if(some_variable == 'R') multiplier = 2;
}
}
So there is the base of what I'm trying to do. I cannot change signature for process_data. To start i do not get how some_variable = *pattern[i]; returns E,T, or R, and I cannot figure out how to iteratively access the full elements in the list. ie "Elem_E" to check for underscore and parse off the E.
I have little background in C++, but have used C numerous times. I am having a difficult time finding visual representation for char **& to help with based understanding of what is going on here, if you can point in the direction of a good tutorial with visual that will also suffice.
Sorry for confusion, forgot quotes in the list.
In C++, reading a parameter passed by reference (with the &) works the same as reading a parameter passed by value (without the &). The difference happens when you assign to the parameter. If the parameter was passed by value then the assignment is only visible inside the function but if it was passed by reference the assignment will be visible outside.
int mynumber = 0;
void foo(int &x)
{
printf("%d\n", x); //prints 0;
x = 10;
}
int main()
{
foo(mynumber);
printf("%d\n", mynumber); // prints 10
}
The equivalent to this in plain C would be to make the x parameter into a pointer and add the required *s and &s:
int mynumber = 0;
void foo(int *x)
{
printf("%d\n", *x);
*x = 10;
}
int main()
{
foo(&mynumber);
printf("%d\n", mynumber); // prints 10
}
Coming back to your code, I don't really know how to solve all your problems (what does the constant Elem_E mean? Is your list NULL terminated or is there a length stored somewhere?) but what I can say is that as long as you don't want to change the patterns global variable from inside process_data, using a char **& will be the same as using a char **.
I don't know how some_variable and multiplier will be used, but I made these changes to calculate them for each string in the list. The variable sec_run is not required in this approach. If no match is found, some_variable and multiplier are set to default values of '\0' and -1.
Output:
item=Elem_E some_variable=E multiplier=0
item=Elem_T some_variable=T multiplier=1
item=Elem_R some_variable=R multiplier=2
item=Turtle some_variable= multiplier=-1
item=Rabbit some_variable= multiplier=-1
Code:
void process_data(const char **& pattern, int num_patterns)
{
const char * item;
for (int i = 0; i < num_patterns; ++i)
{
item = pattern[i];
if ( item == NULL ) continue;
char some_variable = '\0'; // set to default for no match
int multiplier = -1; // set to default for no match
int len = strlen(item);
for (int j = 0; j < len; ++j)
{
if (item[j] == '_' && j + 1 < len)
some_variable = item[j + 1]; /*letter after "_" */
}
if (some_variable == 'E') multiplier = 0;
else if (some_variable == 'T') multiplier = 1;
else if (some_variable == 'R') multiplier = 2;
cout << "item=" << item << " some_variable=" << some_variable << " multiplier=" << multiplier << endl;
}
}
void pattern_test()
{
const char* list[] = { "Elem_E", "Elem_T", "Elem_R", "Turtle", "Rabbit" };
const char ** patterns = list;
// trick to calculate array length
// length of entire array divided by length of one element
int num_length = sizeof(list) / sizeof(list[0]);
process_data(patterns, num_length);
}
I have a dynamic programming algorithm for Knapsack in C++. When it was implemented as a function and accessing variables passed into it, it was taking 22 seconds to run on a particular instance. When I made it the member function of my class KnapsackInstance and had it use variables that were data members of that class, it started taking 37 seconds to run. As far as I know, only accessing member functions goes through the vtable so I'm at a loss to explain what might be happening.
Here's the code of the function
int KnapsackInstance::dpSolve() {
int i; // Current item number
int d; // Current weight
int * tbl; // Array of size weightLeft
int toret;
tbl = new int[weightLeft+1];
if (!tbl) return -1;
memset(tbl, 0, (weightLeft+1)*sizeof(int));
for (i = 1; i <= numItems; ++i) {
for (d = weightLeft; d >= 0; --d) {
if (profitsWeights.at(i-1).second <= d) {
/* Either add this item or don't */
int v1 = profitsWeights.at(i-1).first + tbl[d-profitsWeights.at(i-1).second];
int v2 = tbl[d];
tbl[d] = (v1 < v2 ? v2 : v1);
}
}
}
toret = tbl[weightLeft];
delete[] tbl;
return toret;
}
tbl is one column of the DP table. We start from the first column and go on until the last column. The profitsWeights variable is a vector of pairs, the first element of which is the profit and the second the weight. toret is the value to return.
Here is the code of the original function :-
int dpSolve(vector<pair<int, int> > profitsWeights, int weightLeft, int numItems) {
int i; // Current item number
int d; // Current weight
int * tbl; // Array of size weightLeft
int toret;
tbl = new int[weightLeft+1];
if (!tbl) return -1;
memset(tbl, 0, (weightLeft+1)*sizeof(int));
for (i = 1; i <= numItems; ++i) {
for (d = weightLeft; d >= 0; --d) {
if (profitsWeights.at(i-1).second <= d) {
/* Either add this item or don't */
int v1 = profitsWeights.at(i-1).first + tbl[d-profitsWeights.at(i-1).second];
int v2 = tbl[d];
tbl[d] = (v1 < v2 ? v2 : v1);
}
}
}
toret = tbl[weightLeft];
delete[] tbl;
return toret;
}
This was run on Debian Lenny with g++-4.3.2 and -O3 -DNDEBUG turned on
Thanks
In a typical implementation, a member function receives a pointer to the instance data as a hidden parameter (this). As such, access to member data is normally via a pointer, which may account for the slow-down you're seeing.
On the other hand, it's hard to do more than guess with only one version of the code to look at.
After looking at both pieces of code, I think I'd write the member function more like this:
int KnapsackInstance::dpSolve() {
std::vector<int> tbl(weightLeft+1, 0);
std::vector<pair<int, int> > weights(profitWeights);
int v1;
for (int i = 0; i <numItems; ++i)
for (int d = weightLeft; d >= 0; --d)
if ((weights[i+1].second <= d) &&
((v1 = weights[i].first + tbl[d-weights[i-1].second])>tbl[d]))
tbl[d] = v1;
return tbl[weightLeft];
}