We use cookies to ensure you have the best browsing experience on our website. Please read our cookie policy for more information about how we use cookies.
Although the problem states "We can call an attribute by referencing the tag, followed by a tilde, '~' and the name of the attribute", there are queries without tilde (~) (test case #4, #5). So be careful when parsing your queries. I think the author should describe the problem more clear.
First you should have enough hackos to buy test cases (5 hackos/ testcase). Too see how many hackos you have currently, click on your login ID on the top right corner.You can click on 'Hackos' hyperlink to learn more about how to earn and use these hackos.
Now suppose that you have submit your solution and got some test cases which are failed. Move your mouse over a failed test case, you should see a popup message. Click the 'Download' hyperlink and you will see 'Purchase TestCase' window. Click yes to buy it. Then you will see 'Download TestCase' window. Click 'Input' or 'Output' to download the content of Input or Expected Output data respectively. Hope this helps.
Hi! So what is the correct behavior for queries without tilde? I guess there are some more inaccuracies in the descreption as I have the following custom input which works great, but any test case other than default fails:
Some of the Test Cases contain queries that have a . instead of the ~
These still expected to produce "Not Found!". For your example input, try the queries:
tag1.valuetag1.tag2.name
Also make sure you can handle attribute names with underscores in them and attribute values containing characters like $,.!
Very poor that the question didn't specify all this. It took me hours to figure out what was wrong.
If attributes are encoded as tag1[.tagN]~attr , searching for tag1[.tagN].attr would fail because there would never be a match. Surely you meant the opposite -- basic_string<char>.rfind(".") and converting that to ~
int n,q;
cin >> n >> q;
cin.ignore();
map <string,string> attributeDB; // to store attribute-value pairs
string inputstr,tag_preamble="";
// get each HRML line
for (int i=0;i<n;i++) {
getline(cin,inputstr);
// for each HRML line, break it up into token words
stringstream ss(inputstr);
string word, attribute, value;
size_t pos;
while (getline(ss, word, ' ')) { // for each token word
// tag detected -> adjust tag_preamble by +/- tag
if (word[0]=='<') {
string tag;
if (word[1]=='/') { // it's tag closing
tag=word.substr(2);
tag=tag.substr(0,tag.length()-1); // rid of ">"
pos=tag_preamble.find("."+tag);
if (pos==string::npos) tag_preamble="";
else tag_preamble=tag_preamble.substr(0,pos);
}
else { // it's tag opening
tag=word.substr(1);
if (tag.find(">")!=string::npos)
tag=tag.substr(0,tag.length()-1); // rid of ">"
if (tag_preamble=="") tag_preamble=tag;
else tag_preamble=tag_preamble+"."+tag;
}
}
// value detected
else if (word[0]=='"') {
pos=word.find_last_of('"');
value=word.substr(1,pos-1);
attributeDB[attribute]=value; // insert into DB
}
// attribute name detected
else if (word[0]!='=') {
attribute=tag_preamble + "~" + word;
}
}
}
// now we process the queries
for (int i=0;i<q;i++) {
getline(cin,inputstr);
if (attributeDB.find(inputstr)==attributeDB.end())
cout << "Not Found!" << endl;
else
cout << attributeDB[inputstr] << endl;
}
It clears the value of the string 'tag_preamble' :p
Are you curious to know, what is the function of 'tag_preamble'? Try to figure out what are the keys in the map 'attributeDB'. You can analyse, how this map is built, or you can first take a look, how it's used:
So, if it doesn't find the opening part of the tag in the format of "something.tag" (meaning it is a sub-tag) in the first line (so pos==string::npos), that means this is the primary tag, so it resests it to nothing (tag_preamble="").
If it does find the tag in that format ("something.tag"), that means this is a sub-tag, so it erases the ".tag" part (leaving only the "something", which will be retained through future line iterations, as it is declared outside of the main for-loop), removing it from the pathway hierarchy for future elements when they are added to the map.
The elements are added to the map based on the string generated from tag_preamble. This is how they are pulled for printing later. So any final values would have the correct, full, corresponding index "pathway" via the [string] (tab_preamble) used to access the map.
When you call string::find and when it doesn't match anything, it returns string::npos which equal to literally -1. The type of npos here is comparable to size_t.
You can use a deque to keep track of the token stack and use a deque to string mapping function to resolve it to an attributeDB entry:
stringd_to_string(constdeque<string>&d){strings;for(constauto&t:d){if(t[0]=='<'){if(s.size())s+='.';s+=t.substr(1);}elses+='~'+t;}returns;}[...]cin.ignore();deque<string>tags;[...]if(word[0]=='<'){// tag::end -> popif(word[1]=='/'){tags.pop_back();// tag::begin -> push}else{// the "- (word[word.size()-1] == '>')" trick is needed to pass half the cases// this is due to no-attr tags of the form "<tag>" and "<tag>" being in the deque// instead of "<tag"tags.push_back(word.substr(0,word.size()-(word[word.size()-1]=='>')));}// attr::val}elseif(word[0]=='"'){size_tpos=word.find_last_of('"');attr_db.insert({d_to_string(tags)],word.substr(1,pos-1)});tags.pop_back();// attr::name}elseif(word[0]!='='){tags.push_back(word);}[...]
On second thought, a vector would probably be better here because the head to tail to traversal would have better locality. However, this would come with the downside that push_back would be only amoritized O(1) instead of strict O(1) unless capacity can be guessed from the maximum nesting level of tags (+1 for the attribute)
Attribute Parser
You are viewing a single comment's thread. Return to all comments →
Although the problem states "We can call an attribute by referencing the tag, followed by a tilde, '~' and the name of the attribute", there are queries without tilde (~) (test case #4, #5). So be careful when parsing your queries. I think the author should describe the problem more clear.
Hi, How did you know the content of the test cases? And without the tilde how did the test cases specify the attribute name after a tag?
It's simple. Use your hackos to buy the test cases. One test case costs you 5 hackos.
How? Could you point out how to do this? Many thanks.
First you should have enough hackos to buy test cases (5 hackos/ testcase). Too see how many hackos you have currently, click on your login ID on the top right corner.You can click on 'Hackos' hyperlink to learn more about how to earn and use these hackos.
Now suppose that you have submit your solution and got some test cases which are failed. Move your mouse over a failed test case, you should see a popup message. Click the 'Download' hyperlink and you will see 'Purchase TestCase' window. Click yes to buy it. Then you will see 'Download TestCase' window. Click 'Input' or 'Output' to download the content of Input or Expected Output data respectively. Hope this helps.
Oh crud... I thought you earned 5 hackos by running your submitted code against a special "hidden" test case. Gees... I wonder how much I've wasted.
Thanks!
here is solution of problem Attribute Parser in c++ programming https://solution.programmingoneonone.com/2020/06/hackerrank-attribute-parser-solution-c-plus-plus.html
Don't paste links of the answer .
the attribute without ~ should not be printed right???
Hi! So what is the correct behavior for queries without tilde? I guess there are some more inaccuracies in the descreption as I have the following custom input which works great, but any test case other than default fails:
As you see it has multilevel nesting, multiple attributes support, no attributes support (tabs are added for better visibility). Confused...
Some of the Test Cases contain queries that have a . instead of the ~
These still expected to produce "Not Found!". For your example input, try the queries:
Also make sure you can handle attribute names with underscores in them and attribute values containing characters like $,.!
Very poor that the question didn't specify all this. It took me hours to figure out what was wrong.
Thanks a lot for the clarification!
if
'~'
is replaced with'.'
in query string, we can modify processing of query like this:If attributes are encoded as
tag1[.tagN]~attr
, searching fortag1[.tagN].attr
would fail because there would never be a match. Surely you meant the opposite --basic_string<char>.rfind(".")
and converting that to~
it should be like this?
Test data and problem statement is modified now.
Using MAP STL:
your code is simple and light
Wow! Thank you!
what does your 'tag_preamble=""' do in the code? Could you explain a bit?
It clears the value of the string 'tag_preamble' :p Are you curious to know, what is the function of 'tag_preamble'? Try to figure out what are the keys in the map 'attributeDB'. You can analyse, how this map is built, or you can first take a look, how it's used:
pos=tag_preamble.find("."+tag); if (pos==string::npos) tag_preamble=""; else tag_preamble=tag_preamble.substr(0,pos);
can anyone explains what this piece of code do actually im new to c++
what if two tags are not nested example
is this case is included in the hackerank testcases?
Yes, it still works. Because it resets "tag_preamble" when the closed tag is encountered:
So, if it doesn't find the opening part of the tag in the format of "something.tag" (meaning it is a sub-tag) in the first line (so pos==string::npos), that means this is the primary tag, so it resests it to nothing (tag_preamble="").
If it does find the tag in that format ("something.tag"), that means this is a sub-tag, so it erases the ".tag" part (leaving only the "something", which will be retained through future line iterations, as it is declared outside of the main for-loop), removing it from the pathway hierarchy for future elements when they are added to the map.
The elements are added to the map based on the string generated from tag_preamble. This is how they are pulled for printing later. So any final values would have the correct, full, corresponding index "pathway" via the [string] (tab_preamble) used to access the map.
i am new to the concept of map. Can you please recommend me some tutorial or video to get started with?
Here
Why are we using size_t data type?
When you call string::find and when it doesn't match anything, it returns string::npos which equal to literally -1. The type of npos here is comparable to size_t.
You may get a performance increase if you use unordered_map as you are processing queries in order so the storage order doesn't matter.
I am new to these map concepts and couldn't figure out the use of "size_t pos", please can you elaborate.
Thank you for sharing!
the code works fine however anyone using this, must also make sure to use two additional header files: 1. map.h 2. bits/stdc++.h
otherwise the compiler will show errors
how could distinguish a.b~value and b~value ?
I love the way you see the problem ,very clever and easy thinking
You can use a deque to keep track of the token stack and use a deque to string mapping function to resolve it to an attributeDB entry:
On second thought, a vector would probably be better here because the head to tail to traversal would have better locality. However, this would come with the downside that push_back would be only amoritized O(1) instead of strict O(1) unless capacity can be guessed from the maximum nesting level of tags (+1 for the attribute)
pos=tag_preamble.find("."+tag); if (pos==string::npos) tag_preamble=""; else tag_preamble=tag_preamble.substr(0,pos);
really helpful, thanks!
My code outputs Not Found! in case the query doesn't contain a ~. Is that what is expected out of #4 and #5 as these are the ones failing for my code.