Basically I need to sort arrays of structs by value from highest to lowest.
I must read from file into structure and then sort it.
Initial information:
6
m k 250
f k 280
m p 240
f p 290
m s 63
f s 45
My attempt: (sorting part might be incorrect)
using namespace std;
struct clothes
{
char gender;
char type;
int price;
};
int main()
{
ifstream file("duomenys.txt");
int amount;
int end;
file >> amount;
end = amount;
clothes robe[amount];
for(int x = 0; x<amount; x++)
{
file >> robe[x].gender >> robe[x].type >> robe[x].price;
}
for(int x = amount - 1; x>0; x--)
{
for(int i = 0; i < end; i++)
{
if(robe[i].price > robe[i+1].price)
{
???
}
}
end--;
}
return 0;
}
I'm pretty new in programming so please keep your answer as beginner-friendly as possible as I don't know much.
How do I swap information between struct robe[0] and robe[1] and sort them after checking if price is higher ?
#Beta
So I came up with something that worked, I declared additional struct which I used for holding values while swapping, and then swapped each value (gender, type, price) seperately into holder seperately.
robeH.genderH = robe[i].gender;
robe[i].gender = robe[i+1].gender;
robe[i+1].gender = robeH.genderH;
robeH.typeH = robe[i].type;
robe[i].type = robe[i+1].type;
robe[i+1].type = robeH.typeH;
robeH.priceH = robe[i].price;
robe[i].price = robe[i+1].price;
robe[i+1].price = robeH.priceH;
Thanks for help
P.S. Is it good practice to do it like I did or is there better way
Related
I'm creating a program, where you input n amount of mushroom pickers, they are in a shroom picking contest, they can find shroomA (worth 5 points), shroomB (worth 3 points) and shroomC (worth 15 points). I need to find the contest winner and print his/her name, but if two or more contestants have the same amount of points they are disqualified, meaning I need to find the highest non repeating result.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class ShroomPicker {
private:
string name;
long long int shroomA, shroomB, shroomC;
public:
void Input() {
char Name[100];
long long int shrooma, shroomb, shroomc;
cin >> Name >> shrooma >> shroomb >> shroomc;
name = Name;
shroomA = shrooma; shroomB = shroomb; shroomC = shroomc;
}
long long int calcPoints() {
return shroomA * 5 + shroomB * 3 + shroomC * 15;
}
string winnersName() {
return name;
}
};
int main() {
int n;
cin >> n;
vector<ShroomPicker> shr;
for (int i = 0; i < n; i++) {
ShroomPicker s;
s.Input();
shr.push_back(s);
}
long long int hiscore = 0;
int num = 0;
for (int i = 0; i < n; i++) {
long long int temp = 0;
temp = shr[i].calcPoints();
if (temp > hiscore) {
hiscore = temp;
num = i;
}
}
cout << shr[num].winnersName();
}
I made this program which finds the highest score even if repeats more than once, could someone suggest how I can find the highest non repeating score?
edit:
for (int i = 0; i < n; i++) {
long long int temp = 0;
temp = shr[i].calcPoints();
if (scoreMap.find(temp) == scoreMap.end()) {
scoreMap[temp] = Info{ i, false };
}
else {
scoreMap[temp] = Info{ i, true };
}
}
I would suggest sorting the list of participants in decreasing number of mushrooms picked (O[nlogn]) and then look through the list from start to finish (O[n] max). The first participant whose number of mushrooms picked is different than those of the adjacent participants (in the sorted list) is the winner.
The fastest (O(N)) way I can think of is to have:
struct Info
{
int picker_index;
bool disqualified;
}
// map from score to the Info object above
std::unordered_map<int, Info> scoreMap;
Iterate through pickers and update the map as follows:
-- If no item in the map, just add scoreMap[score] = Info {picker_index, false};
-- else, set disqualified = true on the existing item;
Once the map is constructed, find the max key in the map for which disqualified = false; similar to what you are doing now.
I am trying to write a simple nonogram solver, in a kind of bruteforce way, but I am stuck on a relatively easy task. Let's say I have a row with clues [2,3] that has a length of 10
so the solutions are:
$$-$$$----
$$--$$$---
$$---$$$--
$$----$$$-
$$-----$$$
-$$----$$$
--$$---$$$
---$$--$$$
----$$-$$$
-$$---$$$-
--$$-$$$--
I want to find all the possible solutions for a row
I know that I have to consider each block separately, and each block will have an availible space of n-(sum of remaining blocks length + number of remaining blocks) but I do not know how to progress from here
Well, this question already have a good answer, so think of this one more as an advertisement of python's prowess.
def place(blocks,total):
if not blocks: return ["-"*total]
if blocks[0]>total: return []
starts = total-blocks[0] #starts = 2 means possible starting indexes are [0,1,2]
if len(blocks)==1: #this is special case
return [("-"*i+"$"*blocks[0]+"-"*(starts-i)) for i in range(starts+1)]
ans = []
for i in range(total-blocks[0]): #append current solutions
for sol in place(blocks[1:],starts-i-1): #with all possible other solutiona
ans.append("-"*i+"$"*blocks[0]+"-"+sol)
return ans
To test it:
for i in place([2,3,2],12):
print(i)
Which produces output like:
$$-$$$-$$---
$$-$$$--$$--
$$-$$$---$$-
$$-$$$----$$
$$--$$$-$$--
$$--$$$--$$-
$$--$$$---$$
$$---$$$-$$-
$$---$$$--$$
$$----$$$-$$
-$$-$$$-$$--
-$$-$$$--$$-
-$$-$$$---$$
-$$--$$$-$$-
-$$--$$$--$$
-$$---$$$-$$
--$$-$$$-$$-
--$$-$$$--$$
--$$--$$$-$$
---$$-$$$-$$
This is what i got:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
typedef std::vector<bool> tRow;
void printRow(tRow row){
for (bool i : row){
std::cout << ((i) ? '$' : '-');
}
std::cout << std::endl;
}
int requiredCells(const std::vector<int> nums){
int sum = 0;
for (int i : nums){
sum += (i + 1); // The number + the at-least-one-cell gap at is right
}
return (sum == 0) ? 0 : sum - 1; // The right-most number don't need any gap
}
bool appendRow(tRow init, const std::vector<int> pendingNums, unsigned int rowSize, std::vector<tRow> &comb){
if (pendingNums.size() <= 0){
comb.push_back(init);
return false;
}
int cellsRequired = requiredCells(pendingNums);
if (cellsRequired > rowSize){
return false; // There are no combinations
}
tRow prefix;
int gapSize = 0;
std::vector<int> pNumsAux = pendingNums;
pNumsAux.erase(pNumsAux.begin());
unsigned int space = rowSize;
while ((gapSize + cellsRequired) <= rowSize){
space = rowSize;
space -= gapSize;
prefix.clear();
prefix = init;
for (int i = 0; i < gapSize; ++i){
prefix.push_back(false);
}
for (int i = 0; i < pendingNums[0]; ++i){
prefix.push_back(true);
space--;
}
if (space > 0){
prefix.push_back(false);
space--;
}
appendRow(prefix, pNumsAux, space, comb);
++gapSize;
}
return true;
}
std::vector<tRow> getCombinations(const std::vector<int> row, unsigned int rowSize) {
std::vector<tRow> comb;
tRow init;
appendRow(init, row, rowSize, comb);
return comb;
}
int main(){
std::vector<int> row = { 2, 3 };
auto ret = getCombinations(row, 10);
for (tRow r : ret){
while (r.size() < 10)
r.push_back(false);
printRow(r);
}
return 0;
}
And my output is:
$$-$$$----
$$--$$$---
$$---$$$--
$$----$$$--
$$-----$$$
-$$-$$$----
-$$--$$$--
-$$---$$$-
-$$----$$$-
--$$-$$$--
--$$--$$$-
--$$---$$$
---$$-$$$-
---$$--$$$
----$$-$$$
For sure, this must be absolutely improvable.
Note: i did't test it more than already written case
Hope it works for you
I am trying to solve this problem.
The goal is to determine the number of ways a morse string can be interpreted, given a dictionary of word.
What I did is that I first "translated" words from my dictionary into morse. Then, I used a naive algorithm, searching for all the ways it can be interpreted recursively.
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <iterator>
using namespace std;
string morse_string;
int morse_string_size;
map<char, string> morse_table;
unsigned int sol;
void matches(int i, int factor, vector<string> &dictionary) {
int suffix_length = morse_string_size-i;
if (suffix_length <= 0) {
sol += factor;
return;
}
map<int, int> c;
for (vector<string>::iterator it = dictionary.begin() ; it != dictionary.end() ; it++) {
if (((*it).size() <= suffix_length) && (morse_string.substr(i, (*it).size()) == *it)) {
if (c.find((*it).size()) == c.end())
c[(*it).size()] = 0;
else
c[(*it).size()]++;
}
}
for (map<int, int>::iterator it = c.begin() ; it != c.end() ; it++) {
matches(i+it->first, factor*(it->second), dictionary);
}
}
string encode_morse(string s) {
string ret = "";
for (unsigned int i = 0 ; i < s.length() ; ++i) {
ret += morse_table[s[i]];
}
return ret;
}
int main() {
morse_table['A'] = ".-"; morse_table['B'] = "-..."; morse_table['C'] = "-.-."; morse_table['D'] = "-.."; morse_table['E'] = "."; morse_table['F'] = "..-."; morse_table['G'] = "--."; morse_table['H'] = "...."; morse_table['I'] = ".."; morse_table['J'] = ".---"; morse_table['K'] = "-.-"; morse_table['L'] = ".-.."; morse_table['M'] = "--"; morse_table['N'] = "-."; morse_table['O'] = "---"; morse_table['P'] = ".--."; morse_table['Q'] = "--.-"; morse_table['R'] = ".-."; morse_table['S'] = "..."; morse_table['T'] = "-"; morse_table['U'] = "..-"; morse_table['V'] = "...-"; morse_table['W'] = ".--"; morse_table['X'] = "-..-"; morse_table['Y'] = "-.--"; morse_table['Z'] = "--..";
int T, N;
string tmp;
vector<string> dictionary;
cin >> T;
while (T--) {
morse_string = "";
cin >> morse_string;
morse_string_size = morse_string.size();
cin >> N;
for (int j = 0 ; j < N ; j++) {
cin >> tmp;
dictionary.push_back(encode_morse(tmp));
}
sol = 0;
matches(0, 1, dictionary);
cout << sol;
if (T)
cout << endl << endl;
}
return 0;
}
Now the thing is that I only have 3 seconds of execution time allowed, and my algorithm won't work under this limit of time.
Is this the good way to do this and if so, what am I missing ? Otherwise, can you give some hints about what is a good strategy ?
EDIT :
There can be at most 10 000 words in the dictionary and at most 1000 characters in the morse string.
A solution that combines dynamic programming with a rolling hash should work for this problem.
Let's start with a simple dynamic programming solution. We allocate an vector which we will use to store known counts for prefixes of morse_string. We then iterate through morse_string and at each position we iterate through all words and we look back to see if they can fit into morse_string. If they can fit then we use the dynamic programming vector to determine how many ways we could have build the prefix of morse_string up to i-dictionaryWord.size()
vector<long>dp;
dp.push_back(1);
for (int i=0;i<morse_string.size();i++) {
long count = 0;
for (int j=1;j<dictionary.size();j++) {
if (dictionary[j].size() > i) continue;
if (dictionary[j] == morse_string.substring(i-dictionary[j].size(),i)) {
count += dp[i-dictionary[j].size()];
}
}
dp.push_back(count);
}
result = dp[morse_code.size()]
The problem with this solution is that it is too slow. Let's say that N is the length of morse_string and M is the size of the dictionary and K is the size of the largest word in the dictionary. It will do O(N*M*K) operations. If we assume K=1000 this is about 10^10 operations which is too slow on most machines.
The K cost came from the line dictionary[j] == morse_string.substring(i-dictionary[j].size(),i)
If we could speed up this string matching to constant or log complexity we would be okay. This is where rolling hashing comes in. If you build a rolling hash array of morse_string then the idea is that you can compute the hash of any substring of morse_string in O(1). So you could then do hash(dictionary[j]) == hash(morse_string.substring(i-dictionary[j].size(),i))
This is good but in the presence of imperfect hashing you could have multiple words from the dictionary with the same hash. That would mean that after getting a hash match you would still need to match the strings as well as the hashes. In programming contests, people often assume perfect hashing and skip the string matching. This is often a safe bet especially on a small dictionary. In case it doesn't produce a perfect hashing (which you can check in code) you can always adjust your hash function slightly and maybe the adjusted hash function will produce a perfect hashing.
Here is my implementation
However, it is a bit slow when analyzing the textfile,
Anyone have a better idea or better data structure to implement Random writing?
Im not using the STL library so dun worry about the syntax.
instead of using push_back, vector here is using .add
randomInteger will generate randome integer between ranges
I would like to produce 2000 character if possible;
I think the slowest part is reading the file char by char?
void generateText(int order, string initSeed, string filename){
Map<string , Vector<char> > model;
char ch;
string key;
ifstream input(filename.c_str());
for(int i = 0; i < order; i++){
input.get(ch);
key+=ch;
}
while(input.get(ch)){
model[key].add(ch);
key = key.substr(1,key.length()-1) + ch;
}
string result;
string seed = initSeed;
for(int i = 0;i<2000;i++){
if (model[seed].size() >0) {
ch = model[seed][randomInteger(0, model[seed].size()-1)];
cout << ch;
seed = seed.substr(1,seed.length()-1) + ch;
}
else
return;
}
}
You need to determine that it is taking too long. (How is this code not running in less than a second on an average laptop?)
If it is, you need to profile.
For example, a likely candidate is the cost of generating random numbers...
You'll only disprove me by profiling ;)
I think it is a bit slow because it creates lots of temporary strings during the analysis phase.
for(int i = 0; i < order; i++){
input.get(ch);
key+=ch; // key = key + ch, at least one new string created
}
while(input.get(ch)){
model[key].add(ch); // key copied to hash table
key = key.substr(1,key.length()-1) + ch; // a couple of temp strings created
}
You could do instead like this:
char key[order + 1]; // pseudo code, won't work because order is not constant
key[order] = 0; /* NUL terminate */
for (int i = 0; i < order; i++) {
input.get(key[i]);
}
while (!(input.eof())) {
for (int j = 0; j < order - 1; k++) {
key[j] = key[j + 1];
}
input.get(key[order]);
model[key].add(ch);
}
Here the only string that is actually created is the string that ends up as a key in the hash table. The key is rotated in a simple character array, avoiding string temporaries.
hi i am using Random class for getting random numbers but my requirement is once it generate one no that should not be repeate again pls help me.
Keep a list of the generated numbers and check this list before returning the next random.
Since you have not specified a language, I'll use C#
List<int> generated = new List<int>;
public int Next()
{
int r;
do { r = Random.Next() } while generated.Contains(r);
generated.Add(r);
return r;
}
The following C# code shows how to obtain 7 random cards with no duplicates. It is the most efficient method to use when your random number range is between 1 and 64 and are integers:
ulong Card, SevenCardHand;
int CardLoop;
const int CardsInDeck = 52;
Random RandObj = new Random(Seed);
for (CardLoop = 0; CardLoop < 7; CardLoop++)
{
do
{
Card = (1UL << RandObj.Next(CardsInDeck));
} while ((SevenCardHand & Card) != 0);
SevenCardHand |= Card;
}
If the random number range is greater than 64, then the next most efficient way to get random numbers without any duplicates is as follows from this C# code:
const int MaxNums = 1000;
int[] OutBuf = new int[MaxNums];
int MaxInt = 250000; // Reps the largest random number that should be returned.
int Loop, Val;
// Init the OutBuf with random numbers between 1 and MaxInt, which is 250,000.
BitArray BA = new BitArray(MaxInt + 1);
for (Loop = 0; Loop < MaxNums; Loop++)
{
// Avoid duplicate numbers.
for (; ; )
{
Val = RandObj.Next(MaxInt + 1);
if (BA.Get(Val))
continue;
OutBuf[Loop] = Val;
BA.Set(Val, true);
break;
}
}
The drawback with this technique is that it tends to use more memory, but it should be significantly faster than other approaches since it does not have to look through a large container each time a random number is obtained.