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.
hy bro , can you tell me how it,s like doing cs study and job (coding)?\
I am new but still i know most of the basics like thus code ,just wanted to know how everything is like.
Hey Singh,
Firstly, i do not belong to CS backgroud :D My major was in Electronics and Telecom so i won't be the right person to answer your question. But if you are in college right now, i would suggest you to try imbibing 2 habits:
1. Meet/talk with people who code (hackerrank, hackerearth, leetcode, codechef, stackoverflow etc.)
2. Write code everyday. Can be a small program or a part from a big program and keep pushing it in Git.
It would prepare you to face any coding challenges in job world :)
Thanks a lot bro. How you actually came across this thread!? last comment here was 2 months ago .Using it as brain teaser? I mean you are not in cs field.Thanks again for the help!
Why we are trying to cram the code in 2-3 lines. Is this what pythonic is?
If you are writing a code more than 50 lines and there is bug you will have hell of headache in debugging it.
One great personaility said once:
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
I also agree with you and here is reason for code should be clear and simple to read.
Think someone (may be you) after few months/years may need to change/debug it, then you might have forget the cleaverness done in past :/
Be practicle and try to write clear (might not be in fewer lines or cleaverest) but working and easy read (by someone else) and in future easy to maintaine.
name,score=[],[]
for _ in range(int(input())):
name.append(input())
score.append(float(input()))
print("\n".join(sorted([name[i] for i in range(len(name)) if score[i]==sorted(list(set(score)))[1]])))
I don't disagree with the principle but in this specific case there's absolutely nothing wrong with using a list comprehension instead of a for loop. The comprehension is doing a simple job elegantly.
If this were production code, I'd use a generator rather than a comprehension, to avoid loading the entire data set into memory unnecessarily, but that's not a problem with the tiny data set here.
Java dev here learning python. I don't think pythonic means cram code in as fewest lines. In fact pythonic just means to use python features to your advantages and create CLEAR, CONCISE, MAINTANABLE CODE. And also follow the "standard" ways of doing something in the python community.
The key word here is MAINTANABLE. I've seen many python challenges were people strive for less lines and even one liners and in some occassions they even fail to do the assignment for the sake of a one liner.
Once you get the hang of comprehensions you will use nothing else. They are very easy to read/understand/debug. It's no different than when you learned how to use a loop for the first time.
marksheet=[]
scorelist=[]
if __name__ == '__main__':
for _ in range(int(input())):
name = input()
score = float(input())
marksheet+=[[name,score]]
scorelist+=[score]
b=sorted(list(set(scorelist)))[1]
for a,c in sorted(marksheet):
if c==b:
print(a)
just tweak this code a little bit.
add this : scorelist = list(dict.fromkeys(scorelist))
before taking b.
if name == 'main':
marksheet=[]
scorelist=[]
for _ in range(int(input())):
name = input()
score = float(input())
marksheet+=[[name,score]]
scorelist+=[score]
scorelist = list(dict.fromkeys(scorelist))
b=sorted(scorelist)[1]
for a,c in sorted(marksheet):
if c==b:
print(a)
1.Create a dictionary, using the List items as keys. This will automatically remove any duplicates because dictionaries cannot have duplicate keys.
2.Then, convert the dictionary back into a list
3.Now we have a List without any duplicates, and it has the same order as the original List
becasuse score represents the input value only .it is not a list, so we create a another list as name contain scorelist . all set and sorted operations done only on lists. i hope this is helpfull to you
last=min(score)#score is a list with n elements
second=max(score)
for i in range (len(score)):#if this gives float try abs(len(score))
if score(i)>last and score(i)
Traceback (most recent call last):
File "Solution.py", line 9, in
second_lowest_mark = sorted(list(dict.fromkeys(score_list)))[1]
IndexError: list index out of range
marks_sheet=[]
score_list =[]
for _ in range(int(raw_input())):
name = raw_input()
score = float(raw_input())
marks_sheet.append([name,score])
score_list.append(score)
for _ in range(int(input())):
new=[]
scorelist=[]
name = input()
score = float(input())
scorelist.append(score)
new+=[name, score]
upda= sorted(set(scorelist))[1]
for i,k in sorted(new):
if k==upda:
print(i)
Traceback (most recent call last):
File "/tmp/submission/20220125/09/42/hackerrank-726008e796df9b7633215ac4e1573e85/code/Solution.py", line 9, in
b = sorted(list(dict.fromkeys(score_list)))[1]
IndexError: list index out of range
i am getting these errors.can someone please tell me how to resolve them.
bro can u say in which order the nest is sorted?
because in marksheet=[name,score]
when u used the sorted syntax . would the name of marksheet get sorted or marks get sorted ?
The "TypeError: unhashable type: 'list'" error message in Python occurs when you try to use a mutable object (such as a list) as a key in a dictionary. Since dictionaries use keys to index values, keys must be hashable objects, meaning they must be immutable (i.e. their value cannot be changed). Lists are mutable, so they cannot be used as dictionary keys. To fix the error, use an immutable object like a tuple, string, or number as the dictionary key instead.
To resolve the TypeError: unhashable type: 'list' error, you need to use an immutable object as a key in a dictionary instead of a mutable one like a list. For example, you can use tuples, strings, or numbers as keys, which are all hashable objects.
d = {[1, 2, 3]: "list_key"} //Using a list as a key in a dictionary
//This will raise the TypeError: unhashable type: 'list' error
d = {(1, 2, 3): "tuple_key"} //Using a tuple as a key in a dictionary
Hi, thanks for your elegent code.
Could explain why you change the format of scorelist into list in b=sorted(list(set(scorelist)))[1]? I think scorelist initially set as list.
i think that when you assigned marksheet+=[ [name,score] ] this line and so in the for loop for a,c in sorted(marksheet):.here 'a' is for name and 'c' is for score.So you are comparing if the score matches then you print the name
@HAMZA_SHAKEEL First two lists are created as marksheet and scorelist. marksheet is used to store the values of all the inputs more like a dictionary while the scorelist recores only the scores.
input is put into the range() to make sure there are enough inputs taken for all the inputs gievn and also because we camt be so sure about th amount of inputs.
Then the scores, marks are stored by
marksheet+=[[name,score]]
scorelist+=[score]
b=sorted(list(set(scorelist)))[1] The second lowest score is taken out to the element b by the index[1].
Then for a,c (a and c are used for the loop process. Nothing special with the functionality of the programme) in the range, all the names which bears the score b is printed.
And a special note must be made, this may look like its forgetting that the test cases might have more than one lowest score. That issue has been addressed by the use of set(). A set does not have duplicate items. Therefore the check is valid and accurate.
From your 5th point, the position [1] is taken to the second value. I assume the list is sorted by the marks from lowest to highest. So giving[1] will take the second lowest grade, am I right?
If what I'm stating is correct, how they are sorting the list from lowest to highest using the scores.
you dont need to convert set into list for sorting.
Sorted function works on set as well and always return list irrespective of the type of iterable arugument passed
2) name = input() # Harry
score = float(input()) #37.21
At this point we get the name and score. This will be done 5 times.
3) k.append([name,score])
In list K we add the name and score to the list
4) mark = (sorted(list(set([m for n,m in k]))))
#with loop taken n= name and m = score
set : delet duplicate elements
list : creat list of score
sorted : Regular elements of mark
5) print("\n".join([a for a,b in sorted(k) if b == mark[1]]))
# b == mark[1]] = second element of mark
set means it delets the duplicate values list is keyword is converted to list and sorted is a keyword is used for sorting it's sorted the list and final value store in b
nope!
set would eliminated the repeation of numbers and then u covert it to list to make it ordered and indexible but u will get the desirable value only when u sort the numbers, so yes u have to sort date anyway.
but yes u can write it as b = sorted(set(scorelist))[1] u dont hv to convert it to a list again because sorted() function write the data in form of list
Hi there thanks for the clarification!
But wouldn't set() already sort the list? The list is already sorted at least when i tested. In that case is there still a need to call sorted() again?
By default , sorting is done in ascending order . so the indexing start from 0 . Acc. to question we have to pick a second lowest no. from input that's why [1] is taken.
b=sorted(list(set(scorelist)))[1]
Here, set will help us to create set which rule out the duplicate numbers then list of set is created using list() . finally it get sorted and placed in a variable b.
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
Brian Kernighan
god thank you. On one hand its great that they know how to condense code, and shows technical ability, but I would never want to read code like this. It is a lot easier when the logic is broken up into distinct steps.
This challenge requires the whole list to be loaded into memory. Unless you are saving each student record to a file as you read it, there is no other option. And we're told there are never more than 5 students in the input.
I use generators rather than comprehensions wherever it is possible and reasonable, but this isn't one of those situations. If you are doing this with nested lists (a dict would be more efficient), the whole list has to be traversersed at least twice, depending on your sorting strategy.
Hard to debug? Comprehensions have become core to Python. They beat hand-crafted for loops for several reasons:
More expressive (if not abused)
Less fragile and error prone
Can often easily be turned into generators for memory efficiency.
Learn them. Modern Python is full of them. Which of these is clearer?
You are wrong, for this chalenge you only need to traverse the list once. You will keep two lists:
1. list of name found for the second position
2. list of names found for the currently min value.
In case you find a another min value, the second position list of names becomes the min value list of names.
This version only stores 2 lists. If the input scores are taken from a normal distribution, the 2 lists will be extremely short and will use virtually no memory. Runs in linear time.
your code is beautiful because it is easy to read and friendly to starters especially for python starters
tincumagic's code is beautiful because it runs in linear time.
If you want to work for big IT companies, like Goolge, Facebook
as a professional developer, please note this is the answer that they want. Sometimes, verbose code can be extremely effecient
You can run in linear time without ugliness. Google and Facebook value maintainable code and have extensive coding standards devoted to that.
Start with the clean code, move to the fast code as necessary. The result will still look better than that.
The Hackerrank challenges actually offer good training in this approach. Start with the clean solution, then see which tests - if any - it fails, then see how much you have to contort the code to make it meet the challenge. Aim for the least distortion necessary, because the clean code is easier to maintain. Which will oten matter even in these challenges, when your optimisation clears one difficult test but still fails the next.
There's never an excuse for starting with something that much of a mess.
@itsbruce the code is neither ugly or a mess. It is solving an problem as efficiently as possible. That is, with one iteration. All the other solutions I see on this page are sorting the inputs after the are obtained, which has extra cost. When people are asking me these types of questions in interviews, they are looking for optimized code.
I came up with almost the exact same listing:
def GetName(pair):
return pair[0]
def GetGrade(pair):
return pair[1]
if __name__ == '__main__':
lowest=[]
runnersUp = []
for _ in range(int(input())):
name = input()
score = float(input())
pair = [name, score]
if not lowest:
lowest.append(pair)
elif lowest[0][1] == score:
lowest.append(pair)
elif lowest[0][1] > score:
runnersUp = list(lowest)
lowest.clear()
lowest.append(pair)
elif not runnersUp:
runnersUp.append(pair)
elif runnersUp[0][1] == score:
runnersUp.append(pair)
elif runnersUp[0][1] > score:
runnersUp.clear()
runnersUp.append(pair)
runnersUp = sorted(runnersUp, key=GetName)
for pair in runnersUp:
print(pair[0])
Hey itsbruce, I think you missed the point from tincumagic. If you have a gazillion names in the input, your code will store all gazillion names in your "scores = {}" dict. (And BTW your code doesn't use nested lists, which is the subject of this assignment.) My solution (that you find "ugly and verbose") only stores 2 lists. If the input scores are taken from a normal distribution, my 2 lists will be extremely short and my code will use virtually no memory.
The challenge explicitly states there will never be more than 5. If the number were open ended, I'd optimise for that. As it is, there's no point. Pointless optimisation is a waste of time, in real work even more so than in toy challenges. Your solution does more work than mine and doesn't have to because there's no gain here.
"And BTW your code doesn't use nested lists, which is the subject of this assignment.)"
A fixed limit of 5 is also part of the assignment but you pointlessly ignored that.
Nested lists are the wrong solution for this challenge. That's typical of the author, most of whose challenges are poor quality and poor teaching material. Fortunately, there's zero requirement to use nested lists.
I find your solution ugly and verbose because all the logic is tied up in one long if/else statement. If I wanted to optimise for saving space (not necessary with a guaranteed limit of 5), i'd simply adjust the code so that when a value is pruned from top2, its names are pruned from dict and all future entries for that score are ignored. And because my code isn't a long chain of if/else, that's an easy change to make.
After all, a for loop that iterates over the input and feeds each parsed number to a function called "logScore". Deeply mysterious.
IF logScore returns true, the corresponding name is added to the dictionary entry for that score, otherwise not. How could that possibly be related to the challenge? The Rosetta Stone to translate this esoteric concept has not been carved.
Sheesh. It's mostly simple Python and a couple of core library functions that have obvious names. There are, to be fair, one or two things that will not be obvious to somebody completely unfamiliar with Python. The underscore is the variable equivalent of /dev/null - here, we're iterating over a range but don't actually care about the individual numbers in the range. Using -1 to index a sequence gives you the last element. List comprehensions used to filter a list (although you'd think the "< score" and "> score" might be a clue). But somebody told me this was a Python tutorial, which might mean that people with some interest in learning the language might try it.
I never had much time for the definition of "old school programmer" that says "Don't learn anything that doesn't look like C and complain if anybody else uses it". Have you considered actually learning the language?
I think everyone mentally processes code differently so some people might find one way is better than the other. I'm sure some will like itsbruce's code (verbose in a different way as in too many for loops) but for me I find tincumagic/captainkangaroo1's code cleaner and easier to read.
I am new to programming and have started with python. I like your code because i can comprehend it, but i am having difficulty understanding some parts of it. If you could help clarifying the concepts it'd be great:
First you mention x < score and then x > score, you consider both the cases (!) and how can you concat score in between. I'm like totally lost on this line.
What is (xs[2], None) in:
This is a list comprehension. It creates a new list based on the contents of another sequence (top2). In this case, it returns a list containing all the elements in top2 which are less than score (preserving the original order). The other comprehension returns a list with all the elements which are greater than score. Meanwhile, [score] is a list containing the single value score.
So what I do in that line is create three lists - everything less than score, [score], everything bigger than score - and concatenate them into one list. What it does is take a list which may already contain scores sorted in order and adds a new item in the correct position within the list.
By doing it this way, I don't have to check to see if the list is empty or contains only one item or contains two items. I don't have to create the different strategies to cope with those 3 different possibilities. This simple strategy works in all of those situations. For example, if top2 is empty, the two list comprehensions will return empty results and two empty lists will be concatenated onto a list containing only score, which is what I would want to do if top2 were empty. If score is lower than any of the current scores in top2, then the first list comprehension will be empty and the second one will contain everything from top2; an empty list will have score added to the end of it and then the contents of top2 added to the end of that.
Oh, and I also don't have to deal with the situation where the new score has the same value as one of the scores already in top2. can you see why?
So this one line always does the right thing, no matter how many values are already in top2 and no matter how the new score value compares to them. So it works much better than a long sequence of if/else statements. It's also much clearer in its intent than a long chain of if/else - if you understand list comprehensions.
First, two thumbs up for for the detailed explanation, thank you! Now it makes so much sense to me! This is such a nifty way to deal with the problem since the order of the entries are maintained and you know where what is.
I understand what will happen when top2 is empty, that number of elements is irrelevant since you iterate over all the entries in top2 with score and you maintain the order of entries in top2, wether the score is higher or lower than top2, but i'm sure why it'd not add two entries of same value because the first comprehension will give an empty list, score will be score and the third comprehension will give an empty list so it should append score to top2 otherwise the first time the code is run, it wouldn't work in that case too?
Imagine the current content of top2 is [1, 2] and logScore is passed a value of 2. The first list comprehension returns all the scores in top2 which are less than 2: [1]. The second list comprehension returns all the scores in top2 which are greater than 2: [], the empty list. So the result is
[1]+[2]+[]
which means that the contents of top2 don't actually change. logScorereplaces the contents of top2 with the result of that line of code, it doesn't add it to the end of top2.
So I want top2 to contain only the lowest two scores (yes, I should probably have named it bottom2), but I've just added a new value to the list, so there may now be 3 scores in there. So I check and if there are 3 then I remove the last one (which will be the highest of the three and not the one I want to keep) by doing this:
xs.pop()
pop() is a function that removes the last item from a list and returns that value. But I ignore it because I don't care what it was.
But before I do that, I also remove from the scores dictionary the key and the list of names associated with the score that I'm discarding. I know it can't be the second lowest score, so I don't need to keep that list of names around. Deleting it from the dict saves memory.
Now, there is a del function that removes a key and its value from a dictionary. But there's a chance that there may not be any entry in the dictionary for this score; if score was bigger than the existing values in the list, then it's been added to the end and is about to be removed from it without there ever having been an entry for it created in. So you have to check if the key exists in the dictionary before deleting it - if you use del to try and remove a key that doesn't exist, it raises an error.
Or you can use the dictionary version of the pop() function, which takes a key as input. Like the list version of pop(), it removes an element from the collection and returns its value. If you also provide a default value (as the optional second argument), it won't complain if the key doesn't exist. I don't care what that value is, so I provide a default value of None.
So that line removes an entry from the scores dictionary if it is there; otherwise it does nothing.
Find the third score in the list xs (which will be the highest score of the three, the one we don't want to keep)
Delete that score and its list of names from the scores dictionary and return the value of that list. If there is no such entry in the dictionary, return None.
scores.pop is a method belonging to the dictionary class. It modifies the dictionary it belongs to, it doesn't modify the values passed to it. It always needs one parameter which is the key to fetch/remove from the dictionary. It optionally takes a second value, which is a default value to use if there is no such key in the dictionary.
I don't do anything with the returned value, I ignore it, so it could return anything and it wouldn't matter. I'm only providing a default value to stop pop from complaining if there is no such key in the dictionary. I use the pop method rather than the del function because popcan be made not to complain; I know there will be occasions where there is no such key and I'd rather use a function that doesn't mind, rather than have to make that check myself. I provide None as the default value to make it clearer that I don't care about the result (and to not waste the program's time by having it create and store a value that will never be used).
So if logScore(score) returned true, score is one of the two lowest scores we've seen so far, which means we want to add the name to the list of names associated with that score (if it isn't one of the lowest two, we don't care). Which is what the line above does.
So we want to fetch the list of names associated with score in the scores dictionary. But what if this is the first time we've seen this score? In that case, there will be no entry - trying to fetch it will raise an error. However, if we provide a default value, get() will return that default value if score is not a key in the scores dictionary.
So that line fetches the existing list from the dictionary or returns an empty list if there is no entry for score in the dictionary. Then we add name to the end of that list and put the resulting list into the dictionary as the list associated with score.
Here i get a bit confused when you mention "if logScore(score) returned true, score is one of the two lowest scores we've seen so far" > i thought that the job of logscore is to only get second heighest score every time it iterates and this line adds the identified second heigest scores to the dictionary scores with their names **+ [name]
According to the problem description, it's the names of the students who got the second lowest score we're looking for. My code certainly finds the lowest two scores and since my code passes the tests, that seems to be what's wanted. Can't remember precisely what I was thinking when I called the variable top2 - the two most significant and/or the two which would be at the top if you sorted the list in descending order, I suppose.
You're wrong about what logScore does. Its responsibility is to add the score to the list of the two lowest scores if it is one of the two lowest scores we've seen so far. It returns True if the score is currently one of the two lowest, False otherwise.
The program checks the result; if the returned value is True, then score is currently one of the two lowest scores (lowest or second lowest) and we should keep a record of the name associated with it. But recording the name isn't logScore's responsibility.
To be honest, logScore probably has either too much responsibility or not enough; either a separate function should manage both the addition of names to the dictionary and their removal if a score drops out of the lowest-two-scores list, or logScore should completely manage both the top2 list and the scores dictionary. As it is, it's a little messy. My excuse was that it was a quick change made to my code at somebody else's request.
Hi itsbruce. I read your explanations and understood the code. I was wondering, if i use the same comprehension to sort the names, will the code be better?
I modified the if statement,
if logScore(score):
scores[score] = scores.get(score,[]) + [name]
to
if logScore(score):
temp = scores.get(score,[])
scores[score] = [x for x in temp if x < name] + [name] + [x for x in temp if x >name]
and avoided sorted() function in the end.
full code:
scores = {}
top2 = []
def logScore(score):
global top2
xs = [x for x in top2 if x < score] + [score] + [x for x in top2 if x > score]
if len(xs) > 2:
scores.pop(xs[2], None)
xs.pop()
top2 = xs
return score <= xs[-1]
for _ in range(int(raw_input())):
name = raw_input()
score = float(raw_input())
if logScore(score):
temp = scores.get(score,[])
scores[score] = [x for x in temp if x < name] + [name] + [x for x in temp if x >name]
for name in scores[top2[1]]:
print name
I applaud your perception, but the first objection is that you've created a significantly less efficient solution. You sort the list of students with the grade you've just seen if that score is currently in the lowest two scores. Imagine if the first few students in the input get the highest score and there are more than 2 different scores. Your code will diligently sort that list, only to throw it away later. That's a waste of time.
Aside from that, reusing the technique from logScore on the list of names is likely to be significantly less efficient than Python's sorted function.
What I did in the logScore function is an insertion sort - one of the easiest sort functions to implement but one of the least efficient on data sets of any significant size. It isn't even the most efficient implementation of insertion sort - an efficient implementation would compare the next value to insert to the value just inserted, remembering the position of the value just inserted, so that the next iteration can work forward or backward from that point rather than starting from the beginning each time. That doesn't matter in logScore, because the data set never grows beyond 3 (being cropped back to a maximum of 2 elements after the sort).
As it happens, we're told there will never be more than 4 students with the second-lowest grade, so the difference in efficiency is unlikely to matter, but a) I don't see the point in dropping the core sort function for a more-than-usually-inefficient insertion sort here and b) I prefer any piece of code to do only one thing unless there's a clear and needed performance gain from doing more than one thing at once. Trying to do two things at once is also why you missed the fact that your proposed solution is inefficient.
Thank you for the clear explanation. Now i see what i did there. I never thought of insertion sort that way too! Good to have you commenting on what I did.
Here is my code will someone tell me whether my logic is correct or not.
lst = []
for _ in range(int(input())):
name = input()
score = float(input())
lst.append(name,score)
a = min(score)
while min(score) == a:
lst.sort(name)
print(name)
b = min(score)
while min(score) == b:
lst.sort(name)
print(name)
marksheet=[[input(),float(input())] for _ in range(int(input()))]
second_lowest=sorted(set(marks for name,marks in marksheet))[1] print('\n'.join([a for a,b in sorted(marksheet) if b==second_lowest]))
I would be very leery of the order in which those input() calls are being done. And given the way Python tends to upend its language standards with any given revision, I'd be very, very, very leery of relying on it to never change.
Counting on the order of items in a dictionary would be an unwise thing, which some languages deliberately randomise just to discourage the habit. Counting on the order of evaluation of items in a sequence is extremely reasonable for Python, a strictly-evaluated, imperative language.
Comprehensions and generators have long been central to idiomatic Python. The usage you're complaining about is widespread. Making the evaluation of sequences non-deterministic a) isn't something GvR is ever likely to consider given his history and expressed opinions and b) would be a code-breaking change for so much production code that the complaints would make the Python 3 hoo-ha seem a mild disagreement.
You mean a minor change between one major version and the next (2.x to 3.x) is reason to believe that sequences aren't going to be evaluated in order from one point release to the next? Python is curated conservatively compared to most dynamic languages. I'm no great fan of Python's design but there's no evidence GvR is batshit crazy.
A "minor" change could alter anything internal that isn't written down in a standard. And when it does affect order of execution, they'll shrug their shoulders and walk away.
And as for GvR, that change in print, which could have been averted simply by calling the new function pr() or something, will probably induce on the order of millions of man-hours of rework, re-review, and re-verification over time, not to mention all the arguments like this one. If that doesn't ring up as batshit crazy, the bar is set way too high.
You can argue over whether it was the best move, but it was highlighted in advance and 2.x is still supported. Nobody's code was in danger. The problem has been one of persuading everybody in the community to move, not people's code crashing.
You're criticising somebody's perfectly good, entirely idiomatic code. By your argument, all Python code is vulnerable, not just that code. Unreasonable singling out that decent solution.
Hey there. Seems you too are beginner. I think this is how we will learn. We may solve from using our basic techniques and look up to them for small advancements in our coding.
I tried this method, but I get the following error. Do, I need to import some module?
Traceback (most recent call last):
File "solution.py", line 4, in <module>
marksheet = [[input(), float(input())] for _ in range(n)]
File "<string>", line 1, in <module>
NameError: name 'Harry' is not defined
This maybe a matter of your python version. In python 2 , input takes only integer inputs and raw_input takes strings, ints and floats. In python 3, there is only one input() function which is practically same as raw_input in Python2.
Long story short, the code above is in Python3, so suit yourself.
if name == 'main':
name,score=[],[]
for _ in range(int(input())):
name.append(input())
score.append(float(input()))
print("\n".join(sorted([name[i] for i in range(len(name)) if score[i]==sorted(list(set(score)))[1]])))
I know guys those of you who are new to python ahaving hard time with ".join" . It is used to print a name and give the next line for the next name if any. When you relise this u will get to know how many function are used.
Nested Lists
You are viewing a single comment's thread. Return to all comments →
I like your use of join. Btw, you could use list expansion for the read as well if you wanted:
That's cool. Reduces the code bya further one line :)
here is the solution of probelm Nested lists https://solution.programmingoneonone.com/2020/06/hackerrank-nested-lists-problem-solution-python.html
thanks!!
here is reply
a;llfks;fsl
hy bro , can you tell me how it,s like doing cs study and job (coding)?\ I am new but still i know most of the basics like thus code ,just wanted to know how everything is like.
Hey Singh, Firstly, i do not belong to CS backgroud :D My major was in Electronics and Telecom so i won't be the right person to answer your question. But if you are in college right now, i would suggest you to try imbibing 2 habits: 1. Meet/talk with people who code (hackerrank, hackerearth, leetcode, codechef, stackoverflow etc.) 2. Write code everyday. Can be a small program or a part from a big program and keep pushing it in Git.
It would prepare you to face any coding challenges in job world :)
Thanks a lot bro. How you actually came across this thread!? last comment here was 2 months ago .Using it as brain teaser? I mean you are not in cs field.Thanks again for the help!
Why we are trying to cram the code in 2-3 lines. Is this what pythonic is?
If you are writing a code more than 50 lines and there is bug you will have hell of headache in debugging it.
One great personaility said once:
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
I feel like people prefer "to code in fewer lines" instead "to write beautiful and clean code" here.
I also agree with you and here is reason for code should be clear and simple to read.
Think someone (may be you) after few months/years may need to change/debug it, then you might have forget the cleaverness done in past :/
Be practicle and try to write clear (might not be in fewer lines or cleaverest) but working and easy read (by someone else) and in future easy to maintaine.
Even The Zen of Python states
lol...
Truely agree with u,but his is elegant coding
ridiculously rich and cool
true
if name == 'main':
I don't disagree with the principle but in this specific case there's absolutely nothing wrong with using a list comprehension instead of a for loop. The comprehension is doing a simple job elegantly.
If this were production code, I'd use a generator rather than a comprehension, to avoid loading the entire data set into memory unnecessarily, but that's not a problem with the tiny data set here.
Java dev here learning python. I don't think pythonic means cram code in as fewest lines. In fact pythonic just means to use python features to your advantages and create CLEAR, CONCISE, MAINTANABLE CODE. And also follow the "standard" ways of doing something in the python community.
The key word here is MAINTANABLE. I've seen many python challenges were people strive for less lines and even one liners and in some occassions they even fail to do the assignment for the sake of a one liner.
True
Writing a code which machine can understand is easy. Writing a code which human can understand easily is difficult.
Once you get the hang of comprehensions you will use nothing else. They are very easy to read/understand/debug. It's no different than when you learned how to use a loop for the first time.
solve this please for me:
in file handling python FI FILE HAS = A B C ; F2 FILE HAS:--- P, Q , R ;
file fif2 should be like a=p , b= q = c=r
try anyone who is intersted
solve F1F2:- A=P B=Q C= R
This is python if your code is not small consice and small , it kind of defeats the purpose of coding in python
python is type of snake. It is large is size. It is non venomous.
r u mad or what? first learn english then come to comment on other's post.
lol...
r u mad
XD
are* you*
Touché
That's hilarious lol
what
funny thought though. if you can understand the larger code it's really fascinating.
Right bro...
something like this?
This works... helped me refine my logic. Thanks @sayanta2702
just tweak this code a little bit. add this : scorelist = list(dict.fromkeys(scorelist)) before taking b.
if name == 'main': marksheet=[] scorelist=[]
what is the use of dict.fromkeys here ?
1.Create a dictionary, using the List items as keys. This will automatically remove any duplicates because dictionaries cannot have duplicate keys. 2.Then, convert the dictionary back into a list 3.Now we have a List without any duplicates, and it has the same order as the original List
the order will be different. it wont be same
in for loop what is a,c
are they anmes and scores
it will create a dictionary with keys as items in the give list as argument and values as None.
its a way to remove duplicates from the list
Any benefit of using dict.fromkeys? A simple use of set could have done the same, right?
scorelist = list(set(scorelist))
Also, why have we created a new scorelist when we already had score.
becasuse score represents the input value only .it is not a list, so we create a another list as name contain scorelist . all set and sorted operations done only on lists. i hope this is helpfull to you
agree, creating a set object by callin set() is appopriate here.
b=sorted(scorelist)[1] why 1 here?
to get second highest score from sorted list
what if the score on index 1 is still the lowest i.e., equals to the score on index 0
It can't be. The set function reduces the list to a set of unique values.
Ok, thanks!
i have tried a similar code. traceback error: index value out of range
same .... here
same ...here
coz we need 2 elements to be printed as a result
that is how I did, seeing your code, @Chaitanya_u.
why do few cases fail when we dont use "dict.fromkeys"??
"dict.fromkeys" is as similar as set() both can be used to remove duplicates.
I also have same doubt
last=min(score)#score is a list with n elements second=max(score) for i in range (len(score)):#if this gives float try abs(len(score)) if score(i)>last and score(i)
what is that meant[1] ouside of the bracket?
we need second lowset grade. after sorting second lowest will be in index 1 of sorted array.
lowest value can be twice or more...
In the initial data, yes. But that's what creating a "set" is for. It removes repeating data.
i get always this error "could not convert string to float"
oh
did you use marksheet as a list? because you wrote mark_sheet([name,score])
it is wrong
In this above program where you defined marks
u need to intialize mark_sheet=[] in the top
why it is to be declared
Traceback (most recent call last): File "Solution.py", line 9, in second_lowest_mark = sorted(list(dict.fromkeys(score_list)))[1] IndexError: list index out of range
Even i am getting the same error. Did u get the solution to overcome this error?
try this............
marks_sheet=[] score_list =[] for _ in range(int(raw_input())): name = raw_input() score = float(raw_input()) marks_sheet.append([name,score]) score_list.append(score)
second_lowest_mark = sorted(list(dict.fromkeys(score_list)))[1]
for name,marks in sorted(marks_sheet): if marks == second_lowest_mark: print(name)
Thanks a lot, it worked.But, why is it we cannot use set instead of dict.fromkeys ?
we can also use set try this................... second_lowest_mark = sorted(set(score_list))[1]
for _ in range(int(input())): new=[] scorelist=[] name = input() score = float(input()) scorelist.append(score) new+=[name, score] upda= sorted(set(scorelist))[1] for i,k in sorted(new): if k==upda: print(i)
But yet list is out of range
we can also use set try this................... second_lowest_mark = sorted(set(score_list))[1]
second_lowest_mark = sorted(list(dict.fromkeys(score_list)))[1]
can you please explain this??
Thank you for sharing your code. It's really helpful and clean
Traceback (most recent call last): File "/tmp/submission/20220125/09/42/hackerrank-726008e796df9b7633215ac4e1573e85/code/Solution.py", line 9, in b = sorted(list(dict.fromkeys(score_list)))[1] IndexError: list index out of range i am getting these errors.can someone please tell me how to resolve them.
it worked
for a,c in sorted(marksheet): if c==b: print(a)
in above case , it will be marks if your list is like :
marksheet = [score, name] then it will sort based on score what you write first is key
but if different name has same score then how the result would be. it would not provide expected output if you provide all scores same.
small correction name = raw_input() now it will take string
Does sorted(mark_sheet) sort the list according the name sublist alphabetically??
will it work if there are two students with same highest score ?
creating dict increases space complexity of code
showing TypeError: unhashable type: 'list' what could be the reason? I used same code as above.
The "TypeError: unhashable type: 'list'" error message in Python occurs when you try to use a mutable object (such as a list) as a key in a dictionary. Since dictionaries use keys to index values, keys must be hashable objects, meaning they must be immutable (i.e. their value cannot be changed). Lists are mutable, so they cannot be used as dictionary keys. To fix the error, use an immutable object like a tuple, string, or number as the dictionary key instead.
To resolve the TypeError: unhashable type: 'list' error, you need to use an immutable object as a key in a dictionary instead of a mutable one like a list. For example, you can use tuples, strings, or numbers as keys, which are all hashable objects.
d = {[1, 2, 3]: "list_key"} //Using a list as a key in a dictionary
//This will raise the TypeError: unhashable type: 'list' error
d = {(1, 2, 3): "tuple_key"} //Using a tuple as a key in a dictionary
//This will work fine as tuples are hashable
we can use sets in place Dictionary and then save converting steps like:
scorelist = sorted(set(scorelist))[1]
This should reduce the steps and will optimise the code.
which language is this + sign doesn't works in python I was trying this and it got syntax error
https://www.tutorialspoint.com/python/assignment_operators_example.htm
Both the variable on the left and the value on the right have to be the same kind of thing (lists, in this case).
why this [1] ???
can u please tell me what is use of set here
Hi, thanks for your elegent code. Could explain why you change the format of scorelist into list in b=sorted(list(set(scorelist)))[1]? I think scorelist initially set as list.
well, you can see scorelist is first converted to set 1)that will remove duplicates. 2) Then we need to convert it back to list
It isn't necessary, though. The sorted function will work on any sequence and return the result as a list. Sets are also sequences in Python.
please explain this thing :---
b=sorted(list(set(scorelist)))[1]
i think that when you assigned marksheet+=[ [name,score] ] this line and so in the for loop for a,c in sorted(marksheet):.here 'a' is for name and 'c' is for score.So you are comparing if the score matches then you print the name
May I know how the program interprets a for name and c for score automatically when we have not assigned each of them to anything?
You need to learn about Python list comprehensions.
https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions
It means that the if the second value in sorted scorelist is equal to value in marksheet then print the key of marksheet
actually here they are trying to do everything in 1 line we can split tbis code as well ,
set(scorelist) will create a set of score list (we can use dict.from keys as well because we need to rule out the duplicate entries)
list(set(scorelist)) will create a list of set, you can create a list of dictionary as well
sorted will sort your list of set(scorelist)
[1] will point to the second element in the sorted list beause we want to print the 2nd smallest element in the list
and now we store it in the b variable
a and c are the names and scores we have already stored in the marksheet
so we are comparing that if c == b that is is core in the marksheet is equal to the secondlowest score that we just found out we will print a
now a is the name that is what the question is asking huh!
What if there are more that 1 lowest scores
Most of the solutions are missing that part. They are simply taking second element.
No, you're both missing the simple fact that a set has no duplicates. Converting a list to a set removes all the duplicates.
Most of the comments on this solution are missing that fact.
Can anyone explain the multiple counters in for loop
@ramit8339 It's used because the list elements contain 2 values inside each. Therefore two counters have been used instead of one.
can you please explain this code to me i am new to python
And a special note must be made, this may look like its forgetting that the test cases might have more than one lowest score. That issue has been addressed by the use of set(). A set does not have duplicate items. Therefore the check is valid and accurate.
Thanks for ur kind explanation to beginners @pamuditha_i
From your 5th point, the position [1] is taken to the second value. I assume the list is sorted by the marks from lowest to highest. So giving[1] will take the second lowest grade, am I right?
If what I'm stating is correct, how they are sorting the list from lowest to highest using the scores.
please help what is the meaning of sorted(marksheet)
@NEMMANIWARAYUSH it is used to sort the list....in this case it will arrange the names in marksheet alphabetically.
this is easily understandable, unlike those mind breaking one liners. thanks a lot.
what is a,c in for loop?
can you plz explain variable b
why does it fail some of the test cases?
can anybody explain me what is a and c in this ?
a,c represent name,score in marksheet
what if the input has two minimas then your code will give the lowest rather the second lowest
No. He turns the list into a set and then back into a list. Turning it into a set removes duplicates.
yeah itsbruce is absolutely correct
I'm new to python can you please explain me ,why you put [1] in your code ?
when the list is sorted in increasing order, [1] is the index of the second element which is the second lowest.
b=sorted(list(set(scorelist)))[1]
can you please explain this code ?
i didnt know that a,c will switch to arguments in list thanks ahmad for taking a moment to clarify
its his pleasure
can anyone help with the explaination part. TIA
can u plz explainn this
no u have to explain
In 9th line why are you typecasting scorelist with a List? What is the purpose?
b = sorted(list(set(scorelist)))[1]
The list conversion is not needed.
Why this [1] is written at the end of b?
b=sorted(list(set(scorelist)))[1]
Can you please explain the use of [1] ?
By default sorting happens in ascending order with index starting from 0. Acc to question we have to pick second lowest grade, so after sorting
And if you know we can pick any specific element of list/set/whatever using indexing. That's why we using [1] to pick element located at index 1
thank you.
Can you please tell what is role of function set() in the code? Thank You
This is beautifully written!
Thank you brother :)
@sayanta2702 why did you use set which is unordered and unindexed and then use list why not directly use list?can you please explain
oh to remove duplicates u did that alright got it sorry to bother
I am new to python can you tell why did you add [1] at the last of syntax b=sorted(list.....)))
can you explain me this logic
hi 1) for _ in range(int(input())):
input() = 5
This loop will be repeated 5 times
2) name = input() # Harry score = float(input()) #37.21
At this point we get the name and score. This will be done 5 times.
3) k.append([name,score])
In list K we add the name and score to the list
4) mark = (sorted(list(set([m for n,m in k])))) #with loop taken n= name and m = score set : delet duplicate elements list : creat list of score sorted : Regular elements of mark
In list K we add the name and score to the list
Thanks! This makes a lot more sense than that first comment with some 400 votes.
what do you mean by for a,c in sorted(marksheet)
b=sorted(list(set(scorelist)))[1] can you plz explain this part
set means it delets the duplicate values list is keyword is converted to list and sorted is a keyword is used for sorting it's sorted the list and final value store in b
yeah..!! you're right.
Thank you for the explanation.
could u please explain me about last for loop. what is the use of a,b.
b=sorted(list(set(scorelist)))[1] what does this line mean?
it will sort the list and take out number which are at index 1 i.e second least.
thanks
Hey, what is the [1] there for?
what is mean of [1]
if by using set the scorelist is already sorted why we use the sorted function again ?
i don't understand why you use sorted() but not .sort() and plz explain me set function
b=sorted(list(set(scorelist)))[l] please explain this? (the sorted part with the l)
why m getting error 1000 times by using ur code
does anyone can explain this b=sorted(list(set(scorelist)))[1]
solve this please for me:
in file handling python FI FILE HAS = A B C ; F2 FILE HAS:--- P, Q , R ;
file fif2 should be like a=p , b= q = c=r
try anyone who is intersted
solve F1F2:- A=P B=Q C= R
THE ONLY ADDITION TO THIS CODE WOULD BE TO SORT THE MARKSHEET LIST ALSO AS IT WOULD HELP PRINTING THE OUTPUT IN ALPHABETICAL ORDER
but we dont get the names if alphabetical order right
what is the use of [1] in line9
if u create set of scorelist the similar marks will be eliminated and it will give only one name alwz
what if the lowest score is present twice in that case value of b will be lowest not 2nd lowest
Would the code still worked if i replaced b=sorted(list(set(scorelist)))[1] with b=(list(set(scorelist))[1] Essentially i removed the sorted()
nope! set would eliminated the repeation of numbers and then u covert it to list to make it ordered and indexible but u will get the desirable value only when u sort the numbers, so yes u have to sort date anyway. but yes u can write it as b = sorted(set(scorelist))[1] u dont hv to convert it to a list again because sorted() function write the data in form of list
Hi there thanks for the clarification! But wouldn't set() already sort the list? The list is already sorted at least when i tested. In that case is there still a need to call sorted() again?
what will sorted( marksheet ) will do means it sort on first index or like names or what
I am new to python can you explain this,how its adding?
marksheet+=[[name,score]] What does this mean?
Can you explain the use of [1] ? and the purpose of set() function?
nice work bro
list index out of rang error
what is 'a' and 'c' over here? i can't understand this two term in this code. pls explain!!
a for name and c for marks are defined
like for name ,marks in range(marksheet): if marks==second_lowest_marks print(name)
why did you used set(scorelist). why set()?
your code is far more good but b = sorted(list here without list we can also write and it will not show any error .
why using set why do we need unique values??
Because when the list of marks is reduced to unique values, the second element in the resulting sorted list is automatically the second lowest mark.
for what [1] is taken at last in line9
By default , sorting is done in ascending order . so the indexing start from 0 . Acc. to question we have to pick a second lowest no. from input that's why [1] is taken.
why did you convert scorelist into a set and then again into a list? I tried it without converting its not working. Reason plz??
set help us to create a set which rule out the duplicate numbers . Then, list will create a list of set
perfect code for beginners to understand, Kudos to you!
A beginner here. I have a few questions, what does this line b=sorted(list(set(scorelist)))[1] do?
Oh and also, how do the computer know which one is a,b or c? We didn't define it at all?
I don't understand the last paragraph.Help please
b=sorted(list(set(scorelist)))[1] Here, set will help us to create set which rule out the duplicate numbers then list of set is created using list() . finally it get sorted and placed in a variable b.
why you are using sorted() everytime
it arranges the data in an order
what is this [1] after sorted function? please explain
where does a and c comes from in for loop in 3rd last line
Ha Ha.
Ok boomer. Why don't admit your incompetence?
well said!
god thank you. On one hand its great that they know how to condense code, and shows technical ability, but I would never want to read code like this. It is a lot easier when the logic is broken up into distinct steps.
shuttup panjak cho
omalsa04 snippet is simple yet elegent, This is an industry standard code, why are you guys complaining about this ?
I beleive it will bloat your memory in case list is huge thats first.
Second the code will be hard to debug.
This challenge requires the whole list to be loaded into memory. Unless you are saving each student record to a file as you read it, there is no other option. And we're told there are never more than 5 students in the input.
I use generators rather than comprehensions wherever it is possible and reasonable, but this isn't one of those situations. If you are doing this with nested lists (a dict would be more efficient), the whole list has to be traversersed at least twice, depending on your sorting strategy.
Hard to debug? Comprehensions have become core to Python. They beat hand-crafted for loops for several reasons:
Learn them. Modern Python is full of them. Which of these is clearer?
your answer is shit
You are wrong, for this chalenge you only need to traverse the list once. You will keep two lists: 1. list of name found for the second position 2. list of names found for the currently min value. In case you find a another min value, the second position list of names becomes the min value list of names.
+1 for tincumagic
This version only stores 2 lists. If the input scores are taken from a normal distribution, the 2 lists will be extremely short and will use virtually no memory. Runs in linear time.
-1 for ugly and verbose code. That is a mess.
lol -9 to you
Almost all of which appeared within 24 hours. Amazing - you'd almost think somebody childish created a series of accounts.
LMAO!
Hi, Bruce,
People are using different benchmarks.
your code is beautiful because it is easy to read and friendly to starters especially for python starters
tincumagic's code is beautiful because it runs in linear time. If you want to work for big IT companies, like Goolge, Facebook as a professional developer, please note this is the answer that they want. Sometimes, verbose code can be extremely effecient
You can run in linear time without ugliness. Google and Facebook value maintainable code and have extensive coding standards devoted to that.
Start with the clean code, move to the fast code as necessary. The result will still look better than that.
The Hackerrank challenges actually offer good training in this approach. Start with the clean solution, then see which tests - if any - it fails, then see how much you have to contort the code to make it meet the challenge. Aim for the least distortion necessary, because the clean code is easier to maintain. Which will oten matter even in these challenges, when your optimisation clears one difficult test but still fails the next.
There's never an excuse for starting with something that much of a mess.
@itsbruce the code is neither ugly or a mess. It is solving an problem as efficiently as possible. That is, with one iteration. All the other solutions I see on this page are sorting the inputs after the are obtained, which has extra cost. When people are asking me these types of questions in interviews, they are looking for optimized code.
I came up with almost the exact same listing:
I dont know why it fails with this: 3 jorge 20.0 jorge 20.0 juan 21.0
You mean like this?
I think you may have missed the point of what I was commenting on (the solution techniques presented in this thread, not on how I did it).
Hey itsbruce, I think you missed the point from tincumagic. If you have a gazillion names in the input, your code will store all gazillion names in your "scores = {}" dict. (And BTW your code doesn't use nested lists, which is the subject of this assignment.) My solution (that you find "ugly and verbose") only stores 2 lists. If the input scores are taken from a normal distribution, my 2 lists will be extremely short and my code will use virtually no memory.
"If you have a gazillion names in the input"
The challenge explicitly states there will never be more than 5. If the number were open ended, I'd optimise for that. As it is, there's no point. Pointless optimisation is a waste of time, in real work even more so than in toy challenges. Your solution does more work than mine and doesn't have to because there's no gain here.
"And BTW your code doesn't use nested lists, which is the subject of this assignment.)"
A fixed limit of 5 is also part of the assignment but you pointlessly ignored that.
Nested lists are the wrong solution for this challenge. That's typical of the author, most of whose challenges are poor quality and poor teaching material. Fortunately, there's zero requirement to use nested lists.
I find your solution ugly and verbose because all the logic is tied up in one long if/else statement. If I wanted to optimise for saving space (not necessary with a guaranteed limit of 5), i'd simply adjust the code so that when a value is pruned from top2, its names are pruned from dict and all future entries for that score are ignored. And because my code isn't a long chain of if/else, that's an easy change to make.
show me
-1 for incomprehensible code for the old school programmers like me. Maybe some Python experts find it readable.
Truly it is indecipherable.
After all, a for loop that iterates over the input and feeds each parsed number to a function called "logScore". Deeply mysterious.
IF logScore returns true, the corresponding name is added to the dictionary entry for that score, otherwise not. How could that possibly be related to the challenge? The Rosetta Stone to translate this esoteric concept has not been carved.
Sheesh. It's mostly simple Python and a couple of core library functions that have obvious names. There are, to be fair, one or two things that will not be obvious to somebody completely unfamiliar with Python. The underscore is the variable equivalent of /dev/null - here, we're iterating over a range but don't actually care about the individual numbers in the range. Using -1 to index a sequence gives you the last element. List comprehensions used to filter a list (although you'd think the "< score" and "> score" might be a clue). But somebody told me this was a Python tutorial, which might mean that people with some interest in learning the language might try it.
I never had much time for the definition of "old school programmer" that says "Don't learn anything that doesn't look like C and complain if anybody else uses it". Have you considered actually learning the language?
I think everyone mentally processes code differently so some people might find one way is better than the other. I'm sure some will like itsbruce's code (verbose in a different way as in too many for loops) but for me I find tincumagic/captainkangaroo1's code cleaner and easier to read.
Hey Bruce!
I am new to programming and have started with python. I like your code because i can comprehend it, but i am having difficulty understanding some parts of it. If you could help clarifying the concepts it'd be great:
I dont understand this:
First you mention x < score and then x > score, you consider both the cases (!) and how can you concat score in between. I'm like totally lost on this line. What is (xs[2], None) in:
What does (score,[]) + [name] do in:
Thanks in advance!
Hi. OK, first line...
This is a list comprehension. It creates a new list based on the contents of another sequence (top2). In this case, it returns a list containing all the elements in top2 which are less than score (preserving the original order). The other comprehension returns a list with all the elements which are greater than score. Meanwhile, [score] is a list containing the single value score.
So what I do in that line is create three lists - everything less than score, [score], everything bigger than score - and concatenate them into one list. What it does is take a list which may already contain scores sorted in order and adds a new item in the correct position within the list.
By doing it this way, I don't have to check to see if the list is empty or contains only one item or contains two items. I don't have to create the different strategies to cope with those 3 different possibilities. This simple strategy works in all of those situations. For example, if top2 is empty, the two list comprehensions will return empty results and two empty lists will be concatenated onto a list containing only score, which is what I would want to do if top2 were empty. If score is lower than any of the current scores in top2, then the first list comprehension will be empty and the second one will contain everything from top2; an empty list will have score added to the end of it and then the contents of top2 added to the end of that.
Oh, and I also don't have to deal with the situation where the new score has the same value as one of the scores already in top2. can you see why?
So this one line always does the right thing, no matter how many values are already in top2 and no matter how the new score value compares to them. So it works much better than a long sequence of if/else statements. It's also much clearer in its intent than a long chain of if/else - if you understand list comprehensions.
First, two thumbs up for for the detailed explanation, thank you! Now it makes so much sense to me! This is such a nifty way to deal with the problem since the order of the entries are maintained and you know where what is.
I understand what will happen when top2 is empty, that number of elements is irrelevant since you iterate over all the entries in top2 with score and you maintain the order of entries in top2, wether the score is higher or lower than top2, but i'm sure why it'd not add two entries of same value because the first comprehension will give an empty list, score will be score and the third comprehension will give an empty list so it should append score to top2 otherwise the first time the code is run, it wouldn't work in that case too?
Imagine the current content of top2 is [1, 2] and logScore is passed a value of 2. The first list comprehension returns all the scores in top2 which are less than 2: [1]. The second list comprehension returns all the scores in top2 which are greater than 2: [], the empty list. So the result is
which means that the contents of top2 don't actually change. logScore replaces the contents of top2 with the result of that line of code, it doesn't add it to the end of top2.
On to the second line you had an issue with:
So I want top2 to contain only the lowest two scores (yes, I should probably have named it bottom2), but I've just added a new value to the list, so there may now be 3 scores in there. So I check and if there are 3 then I remove the last one (which will be the highest of the three and not the one I want to keep) by doing this:
pop() is a function that removes the last item from a list and returns that value. But I ignore it because I don't care what it was.
But before I do that, I also remove from the scores dictionary the key and the list of names associated with the score that I'm discarding. I know it can't be the second lowest score, so I don't need to keep that list of names around. Deleting it from the dict saves memory.
Now, there is a del function that removes a key and its value from a dictionary. But there's a chance that there may not be any entry in the dictionary for this score; if score was bigger than the existing values in the list, then it's been added to the end and is about to be removed from it without there ever having been an entry for it created in. So you have to check if the key exists in the dictionary before deleting it - if you use del to try and remove a key that doesn't exist, it raises an error.
Or you can use the dictionary version of the pop() function, which takes a key as input. Like the list version of pop(), it removes an element from the collection and returns its value. If you also provide a default value (as the optional second argument), it won't complain if the key doesn't exist. I don't care what that value is, so I provide a default value of None.
So that line removes an entry from the scores dictionary if it is there; otherwise it does nothing.
Just to clarify here,
Means: Python pop key position 2 from the list xs and return value None
No, it means
scores.pop is a method belonging to the dictionary class. It modifies the dictionary it belongs to, it doesn't modify the values passed to it. It always needs one parameter which is the key to fetch/remove from the dictionary. It optionally takes a second value, which is a default value to use if there is no such key in the dictionary.
I don't do anything with the returned value, I ignore it, so it could return anything and it wouldn't matter. I'm only providing a default value to stop pop from complaining if there is no such key in the dictionary. I use the pop method rather than the del function because pop can be made not to complain; I know there will be occasions where there is no such key and I'd rather use a function that doesn't mind, rather than have to make that check myself. I provide None as the default value to make it clearer that I don't care about the result (and to not waste the program's time by having it create and store a value that will never be used).
OK, third and final line:
So if logScore(score) returned true, score is one of the two lowest scores we've seen so far, which means we want to add the name to the list of names associated with that score (if it isn't one of the lowest two, we don't care). Which is what the line above does.
So we want to fetch the list of names associated with score in the scores dictionary. But what if this is the first time we've seen this score? In that case, there will be no entry - trying to fetch it will raise an error. However, if we provide a default value, get() will return that default value if score is not a key in the scores dictionary.
So that line fetches the existing list from the dictionary or returns an empty list if there is no entry for score in the dictionary. Then we add name to the end of that list and put the resulting list into the dictionary as the list associated with score.
Here i get a bit confused when you mention "if logScore(score) returned true, score is one of the two lowest scores we've seen so far" > i thought that the job of logscore is to only get second heighest score every time it iterates and this line adds the identified second heigest scores to the dictionary scores with their names **+ [name]
And thanks again!
According to the problem description, it's the names of the students who got the second lowest score we're looking for. My code certainly finds the lowest two scores and since my code passes the tests, that seems to be what's wanted. Can't remember precisely what I was thinking when I called the variable top2 - the two most significant and/or the two which would be at the top if you sorted the list in descending order, I suppose.
You're wrong about what logScore does. Its responsibility is to add the score to the list of the two lowest scores if it is one of the two lowest scores we've seen so far. It returns True if the score is currently one of the two lowest, False otherwise.
The program checks the result; if the returned value is True, then score is currently one of the two lowest scores (lowest or second lowest) and we should keep a record of the name associated with it. But recording the name isn't logScore's responsibility.
To be honest, logScore probably has either too much responsibility or not enough; either a separate function should manage both the addition of names to the dictionary and their removal if a score drops out of the lowest-two-scores list, or logScore should completely manage both the top2 list and the scores dictionary. As it is, it's a little messy. My excuse was that it was a quick change made to my code at somebody else's request.
Hi itsbruce. I read your explanations and understood the code. I was wondering, if i use the same comprehension to sort the names, will the code be better?
I modified the if statement,
to
and avoided sorted() function in the end. full code:
I applaud your perception, but the first objection is that you've created a significantly less efficient solution. You sort the list of students with the grade you've just seen if that score is currently in the lowest two scores. Imagine if the first few students in the input get the highest score and there are more than 2 different scores. Your code will diligently sort that list, only to throw it away later. That's a waste of time.
Aside from that, reusing the technique from logScore on the list of names is likely to be significantly less efficient than Python's sorted function.
What I did in the logScore function is an insertion sort - one of the easiest sort functions to implement but one of the least efficient on data sets of any significant size. It isn't even the most efficient implementation of insertion sort - an efficient implementation would compare the next value to insert to the value just inserted, remembering the position of the value just inserted, so that the next iteration can work forward or backward from that point rather than starting from the beginning each time. That doesn't matter in logScore, because the data set never grows beyond 3 (being cropped back to a maximum of 2 elements after the sort).
As it happens, we're told there will never be more than 4 students with the second-lowest grade, so the difference in efficiency is unlikely to matter, but a) I don't see the point in dropping the core sort function for a more-than-usually-inefficient insertion sort here and b) I prefer any piece of code to do only one thing unless there's a clear and needed performance gain from doing more than one thing at once. Trying to do two things at once is also why you missed the fact that your proposed solution is inefficient.
Thank you for the clear explanation. Now i see what i did there. I never thought of insertion sort that way too! Good to have you commenting on what I did.
thanks bruce this worked for me in python 2
It fails with this custom input: 3 jorge 20.0 jorge 20.0 juan 21.0
Its just a challenge with title "Nested List" and not about cleaverest solution.
Oh..........................
Here is my code will someone tell me whether my logic is correct or not. lst = [] for _ in range(int(input())): name = input() score = float(input())
marksheet=[[input(),float(input())] for i in range(int(input()))] //another line and go on
ohh
make it in one line
i like to coode in lesser number of code for fun
dl;falsd;lk
What happens when there are multiple last value. [['Harry', 37.21], ['Berry', 37.21], ['Tina', 37.2], ['Akriti', 41], ['Harsh', 39], ['Tanya', 37.2]]
Then the second last value will be the at [2] index.
nicely done!!!
here is python problem solution https://programs.programmingoneonone.com/2021/01/hackerrank-nested-lists-solution-python.html
Updated solution is here
https://www.thecscience.com/2021/05/HackerRank-nested-lists-in-python-problem-solution.html
Solution https://codecracksol.blogspot.com/2022/03/nested-lists.html
marksheet = [[input(), float(input())] for _ in range(int(input()))]
I would be very leery of the order in which those input() calls are being done. And given the way Python tends to upend its language standards with any given revision, I'd be very, very, very leery of relying on it to never change.
Counting on the order of items in a dictionary would be an unwise thing, which some languages deliberately randomise just to discourage the habit. Counting on the order of evaluation of items in a sequence is extremely reasonable for Python, a strictly-evaluated, imperative language.
Comprehensions and generators have long been central to idiomatic Python. The usage you're complaining about is widespread. Making the evaluation of sequences non-deterministic a) isn't something GvR is ever likely to consider given his history and expressed opinions and b) would be a code-breaking change for so much production code that the complaints would make the Python 3 hoo-ha seem a mild disagreement.
I dunno. Someone who'd change print from a statement to a function is not going to make anyone trust the stability of the platform.
You mean a minor change between one major version and the next (2.x to 3.x) is reason to believe that sequences aren't going to be evaluated in order from one point release to the next? Python is curated conservatively compared to most dynamic languages. I'm no great fan of Python's design but there's no evidence GvR is batshit crazy.
A "minor" change could alter anything internal that isn't written down in a standard. And when it does affect order of execution, they'll shrug their shoulders and walk away.
And as for GvR, that change in print, which could have been averted simply by calling the new function pr() or something, will probably induce on the order of millions of man-hours of rework, re-review, and re-verification over time, not to mention all the arguments like this one. If that doesn't ring up as batshit crazy, the bar is set way too high.
You can argue over whether it was the best move, but it was highlighted in advance and 2.x is still supported. Nobody's code was in danger. The problem has been one of persuading everybody in the community to move, not people's code crashing.
You're criticising somebody's perfectly good, entirely idiomatic code. By your argument, all Python code is vulnerable, not just that code. Unreasonable singling out that decent solution.
don't you have any other work?
could you please tell me how to learn all these types of syntax
try to read about list comprhensions thats basically what he is using. :)
could you please suggest me the sources to get them.
You Tube will be of great help. Also I personally recommend python docs, though they are extremely time consuming. Read them at your own risk.
And hit and trial always work out
Thank you!
Hey there. Seems you too are beginner. I think this is how we will learn. We may solve from using our basic techniques and look up to them for small advancements in our coding.
Thanks for your advice SIr!
shaikalfaaz8 , list comprehension
Go for some list comprehensions problems .......
Can u suggest, where can I find more such problems?
You can go to CodeChef site . It's great for practise.
it's list comprehension it's covered pretty densely. youtube is a great resource
+1
Practise dude
hi can u kindly tell me how th loop is working in your code ! i am new to this language and i am pretty confused my now. thanks for the help
he is using list comprehensions, for more
https://www.youtube.com/watch?v=3dt4OGnU5sM
visit that link
this is a helpful, well-presented introduction to python list comprehensions. thank you for posting it :)
I tried this method, but I get the following error. Do, I need to import some module?
I was having the same problem. The way i fixed it is by using raw_input() for the name instead of input(). Hope this helps
This maybe a matter of your python version. In python 2 , input takes only integer inputs and raw_input takes strings, ints and floats. In python 3, there is only one input() function which is practically same as raw_input in Python2.
Long story short, the code above is in Python3, so suit yourself.
change your compiler to python 3 if you are using python 2 or vice versa
Hope it will help :)
marksheet = [[input(), float(input())] for _ in range(int(input()))]
Reduce one more line :-)
will u please tell me why we use[1] at the end second heighest=sorted(())[1]
because we want the second highest value of the list. if you do [0], you will get the highest which the problem has not asked.
Should be second lowest grade ;)
i did it in one line, it works
Is there a need to convert a set to list , Also what is the result of sorted(marksheet) will it sort based on Names or marks?
or simply:
marksheet = [[input(), float(input())] for _ in range(int(input()))]
it will not work because input() return a inputed line (string)
you have to map it with split function and then only you can convert it into float
like map(MySplitFunction, input()) for _ in range(int(input()))
marksheet = [[input(), float(input())] for _ in range(int(input()))]
This is help full. Thnak you
really very cool
what is the meaning of "_" after for
It is simply a variable.
yeah
yup..CoOl :-)
okay!!
marksheet = [[input(),float(input())] for _ in range(int(input())]
It was cool
This further reduces memory usage and a line of code. :)
to further reduce one line : marksheet = [[input(), float(input())] for _ in range(int(input()))]
solve this please for me:
in file handling python FI FILE HAS = A B C ; F2 FILE HAS:--- P, Q , R ;
file fif2 should be like a=p , b= q = c=r
try anyone who is intersted
solve F1F2:- A=P B=Q C= R
solve this please for me:
in file handling python FI FILE HAS = A B C ; F2 FILE HAS:--- P, Q , R ;
file fif2 should be like a=p , b= q = c=r
try anyone who is intersted
solve F1F2:- A=P B=Q C= R
while you are there, might as well
marksheet = [[input(), float(input())] for _ in range(int(input()]
u can get away with a single line if u modify your use of range function as range(n) to range(int(input()))
: )
aslo reduce this by this code
marksheet = [[input(), float(input())] for i in range(int(input()))]
marksheet = [[input(), float(input())] for _ in range(int(input()))]
Please explain this. I am a beginner to python
if name == 'main': name,score=[],[] for _ in range(int(input())): name.append(input()) score.append(float(input())) print("\n".join(sorted([name[i] for i in range(len(name)) if score[i]==sorted(list(set(score)))[1]])))
I know guys those of you who are new to python ahaving hard time with ".join" . It is used to print a name and give the next line for the next name if any. When you relise this u will get to know how many function are used.
marksheet = [[input(), float(input())] for _ in range(int(input()))]
marksheet = [[input(), float(input())] for _ in range(int(input())]
taking separately the input value you could have just used in one line in nested comprehension
marksheet=[[input(),float(input())] for _ in range(int(input()))]
Also no need for list the set, it works fine with just set second_highest = sorted(set([marks for name, marks in marksheet]))[1]
could you please tell me what the second line will take the input & how