| | |
Problem with contest program
Please support our C++ advertiser: Programming Forums - DaniWeb Sister Site
Thread Solved |
I'm writing a program for a contest (it's a demo, not the actual thing - so I'm not cheating by asking for help - and my question isn't directly related to the algorithm they want anyway). To submit a program, you send them the .cpp file, and they execute it on their server (automatically) for a number of test trials (around 10), and show you the results. This problem has 11 trials. For the first five trials, the program runs fine. However, the sixth run of the program fails, and it throws std::bad_alloc (I'm guessing its caused by vector::push_back - the only other things I'm using from std are file streams and strings). Then, trial 7 works fine. Trials 8 and 9 failed, same reason. Trial 10's runtime was too long (it was stopped at around 1.5 secs, shouldn't go over 1 second), and trial 11 had the bad_alloc again.
I wanted to see exactly where the bad_alloc was occurring, so I copied the test input data for trial 6 into the test input file on my machine, and ran the program. I didn't get bad_alloc, but the program didn't end (for the time I ran it, maybe 10 seconds - I'm going to try leaving it for longer while outputting debug info).
Anyway - this is my assumption of what's going on, tell me if I'm right:
On the virtual machine on the competition's servers, the program is only given the amount of memory that they think it needs to execute. So, my program is memory inefficient, and on their machine, it runs out of memory. However, on my machine, the memory isn't limited, so it keeps using it up, and so instead of getting bad_alloc, the program just runs for a long time. Is this a correct assumption?
I wanted to see exactly where the bad_alloc was occurring, so I copied the test input data for trial 6 into the test input file on my machine, and ran the program. I didn't get bad_alloc, but the program didn't end (for the time I ran it, maybe 10 seconds - I'm going to try leaving it for longer while outputting debug info).
Anyway - this is my assumption of what's going on, tell me if I'm right:
On the virtual machine on the competition's servers, the program is only given the amount of memory that they think it needs to execute. So, my program is memory inefficient, and on their machine, it runs out of memory. However, on my machine, the memory isn't limited, so it keeps using it up, and so instead of getting bad_alloc, the program just runs for a long time. Is this a correct assumption?
I'm a student. If my statements seem too absolute, feel free to coat them with "In my opinion..." or "I believe...".
•
•
Join Date: Jan 2008
Posts: 3,844
Reputation:
Solved Threads: 503
•
•
•
•
I'm writing a program for a contest (it's a demo, not the actual thing - so I'm not cheating by asking for help - and my question isn't directly related to the algorithm they want anyway). To submit a program, you send them the .cpp file, and they execute it on their server (automatically) for a number of test trials (around 10), and show you the results. This problem has 11 trials. For the first five trials, the program runs fine. However, the sixth run of the program fails, and it throws std::bad_alloc (I'm guessing its caused by vector::push_back - the only other things I'm using from std are file streams and strings). Then, trial 7 works fine. Trials 8 and 9 failed, same reason. Trial 10's runtime was too long (it was stopped at around 1.5 secs, shouldn't go over 1 second), and trial 11 had the bad_alloc again.
I wanted to see exactly where the bad_alloc was occurring, so I copied the test input data for trial 6 into the test input file on my machine, and ran the program. I didn't get bad_alloc, but the program didn't end (for the time I ran it, maybe 10 seconds - I'm going to try leaving it for longer while outputting debug info).
Anyway - this is my assumption of what's going on, tell me if I'm right:
On the virtual machine on the competition's servers, the program is only given the amount of memory that they think it needs to execute. So, my program is memory inefficient, and on their machine, it runs out of memory. However, on my machine, the memory isn't limited, so it keeps using it up, and so instead of getting bad_alloc, the program just runs for a long time. Is this a correct assumption?
Sounds like a reasonable assumption. You could easily have a program that ran out of memory in one environment with limited memory resources, but not run out in an environment with more resources. push_back is going to result in a bad_alloc error when you run out of memory. I got about 134,000,000 allocations in the program below before hitting the bad_alloc exception, but it could easily vary with different systems.
C++ Syntax (Toggle Plain Text)
#include <vector> #include <string> #include <iostream> using namespace std; int main () { vector <int> v; cout << "Absolute maximum allocations = " << v.max_size() << endl; int counter = 0; bool done = false; while(!done) { try { v.push_back(counter); counter++; } catch (std::bad_alloc) { done = true; cout << "Number of allocations = " << counter << endl; cout << "Bad allocation" << endl; } } cout << "Done with program" << endl; return 0; }
•
•
•
•
I would surmise you're using a brute force solution when perhaps a dynamic solution exists.
This is quite common on online contests such as topcoder etc.
The problem:
You're given x number of lowercase characters and a password length. You need to find all the valid passwords you can construct from the given letters.
valid passwords:
- have at least one vowel
- have at least two consonants
- have characters in alphabetical order, ie: abc is ok, bac, or cab, is not
You need to then alphabetize the results you get and print up to 25000 of them. Here's how I go about it (I'm away from home so I don't have the code with me).
Find all the possible combos given the letters.
Weed out the incorrect ones
Alphabetize what's left.
Output up to 25000
Is this a brute force method? If so, what would be a possible dynamic method (if you can sort of hint at the answer or put me on the right track without giving me the answer, that'd be nice).
I'm a student. If my statements seem too absolute, feel free to coat them with "In my opinion..." or "I believe...".
•
•
Join Date: Jan 2008
Posts: 3,844
Reputation:
Solved Threads: 503
•
•
•
•
My solution may be a brute force - I'm not entirety sure. I would have preferred to think of the algorithm on my own - but this is the basic structure of the problem/program, is it a brute force?
The problem:
You're given x number of lowercase characters and a password length. You need to find all the valid passwords you can construct from the given letters.
valid passwords:
- have at least one vowel
- have at least two consonants
- have characters in alphabetical order, ie: abc is ok, bac, or cab, is not
You need to then alphabetize the results you get and print up to 25000 of them. Here's how I go about it (I'm away from home so I don't have the code with me).
Find all the possible combos given the letters.
Weed out the incorrect ones
Alphabetize what's left.
Output up to 25000
Is this a brute force method? If so, what would be a possible dynamic method (if you can sort of hint at the answer or put me on the right track without giving me the answer, that'd be nice).
A good algorithm, I think, will actually work in such a way that the solutions are actually added to the vector already in alphabetical order, so there is no need to sort. I would also NOT generate all possible combinations (let alone permutations). Some you know right away are illegal (i.e. all consonants), so don't even generate them. Start with a vowel and two consonants, and THEN generate all combinations of the remaining letters. Those will all be legal combinations (you'll need to sort the letter into alphabetical order before adding it to the vector, but it'll be a legal combination of letters).
I got home recently, and I'll try to make the program more memory efficient, but I just let the program run for 40 mins with one of the failed sets of test data, and it didn't get past the portion where it finds all the possible combinations you can have, so I'm thinking there may be some other issue, but I'll try to make it less of a brute-force and see what happens.
Here's the code, if anyone cares to read it:
Here's the code, if anyone cares to read it:
C++ Syntax (Toggle Plain Text)
#include <fstream> #include <iostream> #include <string> #include <vector> using namespace std; int password_length; int num_chars; vector<string> possible_combos; char* chars; void FindAll(string current,vector<int> char_ids_used) { if(current.length() == password_length) { possible_combos.push_back(current); return; } for(int i = 0; i < num_chars;i++) { bool used = false; for(int j = 0;j < char_ids_used.size();j++) { if(i == char_ids_used[j]) used = true; } if(!used) { vector<int> my_used = char_ids_used; my_used.push_back(i); FindAll(current + chars[i],my_used); } } } bool IsVowel(char c) { switch(c) { case 97: case 101: case 105: case 111: case 117: return true; } return false; } bool HasVowel(string str) { int length = str.length(); for(int i = 0;i < length;i++) { if(IsVowel(str[i])) return true; } return false; } bool HasTwoConsonants(string str) { int numConsonants = 0; int length = str.length(); for(int i = 0;i < length;i++) { if(!IsVowel(str[i])) numConsonants++; } if(numConsonants >= 2) return true; return false; } bool InAlphaOrder(string str) { for(int i = 1;i < str.length();i++) { char prev = str[i-1]; char current = str[i]; if(int(prev) > int(current)) return false; } return true; } bool InAlphaOrder(string first,string second) { int length = first.length(); for(int i = 0;i < length;i++) { if(int(first[i]) < int(second[i])) return true; else if(int(first[i]) > int(second[i])) return false; } return true;//strings are the same } int main() { ofstream debug("passwd.debug"); debug << "Program start\n"; cout << "Program start\n"; debug << "Reading data from passwd.in\n"; cout << "Reading data from passwd.in\n"; ifstream fin("passwd.in"); fin >> password_length >> num_chars; chars = new char[num_chars]; for(int i = 0;i < num_chars;i++) fin >> chars[i]; fin.close(); debug << "Done reading\n"; cout << "Done reading\n"; debug << "Finding possible combos\n"; cout << "Finding possible combos\n"; for(int i = 0;i < num_chars;i++) { vector<int> used_chars; used_chars.push_back(i); string current; current = chars[i]; FindAll(current,used_chars); } debug << "Done finding\n"; cout << "Done finding\n"; debug << "Validating results\n"; cout << "Validating results\n"; int num_combos = possible_combos.size(); vector<string> valid_combos; for(int i = 0;i < num_combos;i++)//added i < 25001 { if(!InAlphaOrder(possible_combos[i])) continue; if(!HasVowel(possible_combos[i])) continue; if(!HasTwoConsonants(possible_combos[i])) continue; valid_combos.push_back(possible_combos[i]); } debug << "Done validating\n"; cout << "Done validating\n"; possible_combos.clear();//all valid results have been copied to the valid_combos vector debug << "Alphabetizing results\n"; cout << "Alphabetizing results\n"; for(int i = 1;i < valid_combos.size() && i <= 25000;i++) { if(!InAlphaOrder(valid_combos[i-1],valid_combos[i])) { string temp = valid_combos[i]; valid_combos[i] = valid_combos[i-1]; valid_combos[i-1] = temp; for(int j = i-1;j > 0;j--) { valid_combos[j-1]; valid_combos[j]; if(InAlphaOrder(valid_combos[j-1],valid_combos[j])) break; else { temp = valid_combos[j]; valid_combos[j] = valid_combos[j-1]; valid_combos[j-1] = temp; } } } } debug << "Done alphabetizing\n"; cout << "Done alphabetizing\n"; debug << "Outputting results\n"; cout << "Outputting results\n"; ofstream fout("passwd.out"); int size = valid_combos.size(); if(size > 25000) size = 25000; for(int i = 0;i < size;i++) { fout << valid_combos[i] << "\n"; } debug << "Done outputting\n"; cout << "Done outputting\n"; debug << "Program end\n"; cout << "Program end\n"; fout.close(); return 0; }
I'm a student. If my statements seem too absolute, feel free to coat them with "In my opinion..." or "I believe...".
Alright, I added the validations before I store the combo in a vector, and that did get rid of the bad_alloc. However, now I'm having issues with runtime. All of the tests that failed before still all fail, it's just that now they fail due their runtime passing one second. I'll try to make the program more efficient as far as runtime, but I still think that there's something up with the brute-force logic I have in place. I can't imagine that one of the tests would take 40+ mins. while others would take fractions of seconds. Though perhaps that 's because I'm not used to these types of problems. I'll look into both improving my logic and seeing if there are issues with it as it is currently implemented.
I'm a student. If my statements seem too absolute, feel free to coat them with "In my opinion..." or "I believe...".
•
•
•
•
Question: Can you have more than one of the same character or must all characters be unique? If you can have multiple characters (i.e. aaert), that's a harder program, I would imagine. Or must all characters be unique (i.e. aert)?
Right after you get the input chars, alphabetize them. Then, go to the first char, and cycle through all the possible combos, but stop if you find that any of the chars you are adding to the string make the string not be in alphabetical order. That will make each output be in alphabetical order, and the outputs themselves will be organized alphabetically.
That logic might be slightly flawed, I just spurred it out. As I'm implementing it I might see any flaws in it, but I think I'm on the right track.
Was this what you were thinking of?
I'm a student. If my statements seem too absolute, feel free to coat them with "In my opinion..." or "I believe...".
![]() |
Similar Threads
- We only give homework help to those who show effort (Computer Science)
- ACMICPC Contest Scoring (Java)
- Uncompress (C)
- C++ Program Contest (C++)
- Programming Contest - Play a game (C)
Other Threads in the C++ Forum
- Previous Thread: Code Speed Question
- Next Thread: Trying to solve a past thread from another user.
Views: 1111 | Replies: 10
| Thread Tools | Search this Thread |
Tag cloud for C++
6 api application array arrays based beginner binary c++ c/c++ calculator char char* class classes code coding compile compiler console conversion convert count data database delete developer display dll dynamiccharacterarray email encryption error file format forms fstream function functions game generator givemetehcodez graph iamthwee ifstream image input int java lib list loop looping loops map math matrix memory multiple newbie news number numbertoword output pointer problem program programming project python random read recursion recursive reference return rpg search simple sort sorting spoonfeeding string strings struct template templates text tree url variable vector video visual visualstudio win32 windows winsock wordfrequency wxwidgets






