Return a result in descending order - python

Teachers of Horizon Academy Public School collect the names of those students who are going to participate in the Mathematics exhibition, that is to be held in a week's time. They have collected all the names and now, they want to store all the names into a system, in the descending order of the length of the names. This means, the longest name should get stored first, followed by the name that is shorter than the previous, and so on. Can you help the teachers to perform this task easily by creating a program in Python?
Note: The number of names specified must be positive, else the program should display the message "Invalid Input" terminate the program.
Input format:
Input consists of an integer that corresponds to the number of names followed by the names.
Output Format:
Print the name list sorted by the names' length, if name length are equal sort based on alphabetical order in descending order as shown in the sample input and output.
Sample Input 1:
Enter the number of names :
5
Enter the names:
William
James
Ella
Lily
Jackson
Sample Output 1:
The sorted name list is:
William
Jackson
James
Lily
Ella
Sample Input 2:
Enter the number of names:
Sample Output 2:
Invalid Input
Sample Input 3:
Enter the number of names :
3
Enter the names:
Lily
Jack
Lucy
Sample Output 3:
The sorted name list is:
Lucy
Lily
Jack
Above is the question and below is my code.
n=int(input("Enter the number of names:\n"))
l=[]
if n>0:
print("Enter the names:")
for i in range(n):
l.append(input())
print("The sorted name list is:")
l.sort(key=len,reverse=True)
for i in l:
print(i)
else:
print("Invalid Input")
I can't seem to figure out why I can't sort it alphabetically. Any suggestion? For example if my input is "Lily, Jake, Lucy", I want it to display the result "Lucy, Lily, Jake"

The issue in the code is that you are specifying a key to sort. It is currently sorting by length in decending order. I tried this and it gets the result you are looking for:
people = ['Lily', 'Lucy', 'Jack']
people.sort(reverse=True)
print(people)
Read more about sort() here

Hi I think you're misunderstanding the behavior of the <list>.sort() method, here you don't need to use the key parameter:
number_of_names = int(input('Number of names: '))
names = list()
if number_of_names > 0:
print('Enter the names:')
for _ in range(number_of_names):
names.append(input())
names.sort(reverse=True)
for name in names:
print(name)
Key isn't useful there, it can be if you want to modify each key, for example, if I want to sort my items after applying a specific transformation:
l = ["tato", "taty", "tyta", "tate"]
# if I want to sort this list based on the last character of each items
l.sort(key=lambda x: x[-1])
# l = ['tyta', 'tate', 'tato', 'taty']
Actually this parameter, will be very useful when you have a list of dicts and you want to sort it based on a parameter:
users = [{"name": "Jack", "age": 22}, {"name": "John", "age": 16}]
users.sort(key=lambda user: user['age']) # sort the users by age

use reverse = True while using sort method
l = list(["Lilly", "Lucky", "Jack"])
l.sort(key=lambda x: x, reverse=True)
print(l)
Updated ans:
key = len doesn't make sense
n=int(input("Enter the number of names:\n"))
l=[]
if n>0:
print("Enter the names:")
for i in range(n):
l.append(input())
print("The sorted name list is:")
l.sort(reverse=True)
for i in l:
print(i)
else:
print("Invalid Input")
Output:
$ python3 test.py
Enter the number of names:
3
Enter the names:
Lilly
Lucky
Jack
The sorted name list is:
Lucky
Lilly
Jack

Related

TypeError without a clue

student_scores = input('Input a list of student scores: ')
for n in range(0, len(student_scores)):
student_scores[n] = int(student_scores[n])
print(student_scores)
highest = 0
for scores in student_scores:
if highest < scores:
highest = scores
print(f'The highest score is {highest}')
I'm learning the basic of Python and input the code accurately that the tutorial video says, but only mine gets TypeError: 'str' object does not support item assignment on the line 3.
I checked it several times, but still have no clue why.
The input() function will invariably return a string. What you want to do is have the user input several numbers (presumably separated by a space) and get a list of integer values from that. You can do that as follows (with some explanations on my part):
student_scores_string = input('Input a list of student scores: ')
(That line will just get a string inputted by the user.)
student_scores = student_scores_string.split()
(That line will give you a list, with each item in the list being one of the values inputted by the user, with a space as a separator.)
student_scores = [int(x) for x in student_scores]
(That line will loop over the elements in the student_scores list, turn each of them into an inetger - remember, so far we have strings! - and put that into the list.)
Then you can continue with your code.
Assume that the input is in the form '25 30 23' - i.e., a string with integer tokens and whitespace delimiters
scores = input('Input a list of student scores: ')
print('The highest score is', max(map(int, scores.split())))
Output:
The highest score is 30
You need to split the input as list, cause student_scores is a string and does not support item assignment (immutable). Assuming the input separated by space:
student_scores = input('Input a list of student scores: ').split()
for n in range(0, len(student_scores)):
student_scores[n] = int(student_scores[n])
print(student_scores)
highest = 0
for scores in student_scores:
if highest < scores:
highest = scores
print(f'The highest score is {highest}')
To get the highest value, you can use highest = max(student_scores):
print(student_scores := [int(n) for n in input('Input a list of student scores: ').split()])
highest = max(student_scores)
print(f'The highest score is {highest}')
Or:
highest = max([int(n) for n in input('Input a list of student scores: ').split()])
print(f'The highest score is {highest}')

How to find the average of an array and pin it with its corresponding name with another array

I have my code set to allow the user to make a list of names for students and another list for their corresponding grades. What I cant seem to figure out is how to take the highest grade, the lowest grade, and the closest to the average then state it with the student it belongs to.
This is what I have so far
# creating statements
students = []
grades = []
print('students:',students)
print('grades:',grades)
looper1 = 0
looper2 = 0
studentappend = 0
gradeappend = 0
# list creation
while looper1 != 2:
print('please choose an option:')
print('1: add student and grade')
print('2: Finish step')
looper1 = int(input())
if looper1 ==1:
students.append(input('enter student name: '))
grades.append(int(input('enter grade:')))
print('students:',students)
print('grades:',grades)
if looper1 ==2:
break
if looper1 !=1 and looper1 !=2:
print('Invalid. enter 1 or 2')
print('students:',students)
print('grades:',grades)
print("Largest element is:", max(grades))
On the last line I have it set to say "Largest grade is: 55" for example, but I want to make it say the name the grade belongs to as well. For example "Bill has the largest grade of 55" This will apply to the lowest grade and the grade that is the closest to the average. I was hoping the max() function would print the number that would tell me where the grade I was looking for was located rather then simply stating it.
Here is a solution with modifications to make your code more streamlined:
students = []
grades = []
#gather input
looper = 1
while looper == 1:
students.append(input('enter student name: '))
grades.append(int(input('enter grade: ')))
looper = int(input('Enter 1 to add more data or another number to exit: '))
#calculate closest to mean
true_mean = sum(grades)/len(grades)
close_to_mean = 0
for i, grade in enumerate(sorted(grades)):
if grade < true_mean < sorted(grades)[i+1]:
close_to_mean = grade
print('students:',students)
print('grades:',grades)
print(f"Highest grade is: {max(grades)} and belongs to {students[grades.index(max(grades))]}.")
print(f"Lowest grade is: {min(grades)} and belongs to {students[grades.index(min(grades))]}.")
print(f"Closest to mean grade is: {close_to_mean} and belongs to {students[grades.index(close_to_mean)]}.")
You can reference the index location for the highest value in the grades list and use that index to return the corresponding student in the students list.
print(students[grades.index(max(grades))]+" has the larges grade of "+str(max(grades)))
Note that the index method returns the index of the first matching item in the list. So if two students are tied with the highest score, it will only return the one listed first.
If you aren't opposed, another approach is to use NumPy functions.
np.argmax and np.argmin give the indices of the (first occurrence of) the maximum and minimum value in an array or list.
To get the name of the student with the highest grade: students[np.argmax(grades)]
To get the name of the student with the lowest grade: students[np.argmin(grades)]
To get the name of the student with the grade closest to the average, you may need list comprehension to calculate the absolute difference between the average grade and each student's grade:
students[np.argmin(np.abs([x - np.mean(grades) for x in grades]))]
Alternatively, instead of list comprehension, you can directly cast it to a numpy array:
students[np.argmin(np.abs(np.array(grades) - np.mean(grades)))]

TypeError: 'float' object is not iterable in nested list

TypeError: 'float' object is not iterable.
In my code I used a nested list comprehension, the score is float values.
Question: Given the names and grades for each student in a Physics class of N students, store them in a nested list and print the name(s) of any student(s) having the second lowest grade.
if __name__ == '__main__':
for _ in range(int(input())):
name = input()
score = float(input())
l=[[x,y] for x in name for y in score if (max(score)-y) > 0]
max=l[0]
for mark in l:
if mark[1]>max[1]:
max=mark
m=[x[0] for x in l if (max-x[1])==0]
print(m.sort())
So, as I said in my comment, but more detailed. You need to preserve the student info in a list, then sort the grades to find the second lowest, then loop over them again to print those that are the second lowest grades.
I also highly suggest not using max as a variable name as it replaces the builtin.
students = []
for i in range(1, int(input("How many students? "))+1):
name = input(f"What is student {i}'s name? ")
score = float(input(f"What is student {i}'s grade? "))
students.append([name, score])
second_lowest_grade = sorted({s[1] for s in students})[1]
for student in students:
if student[1] == second_lowest_grade:
print(*student, sep=': ')
I enhanced the first comment a little bit:
#!/usr/bin/env python
students = []
for i in range(1, int(input("How many students? "))+1):
name = input(f"What is student {i}'s name? ")
score = float(input(f"What is student {i}'s grade? "))
students.append([name, score])
student_with_second_lowest_grade = sorted(students, key=lambda t:t[1])[1]
print("Student {0} has the second lowest grade={1}!".format(*student_with_second_lowest_grade))
So you can execute this way:
# python3 test.py
How many students? 4
What is student 1's name? John
What is student 1's grade? 10
What is student 2's name? Mary
What is student 2's grade? 9
What is student 3's name? Ken
What is student 3's grade? 8
What is student 4's name? Peter
What is student 4's grade? 7
Student Ken has the second lowest grade=8.0!
FYI

HackerRank's Nested List Problem:-Facing issues with 2 out of 10 test cases

The following is my attempt at the solution.The result needs to be ordered in lexicographical order which i did but i am not getting why the test cases which i mentioned below after the #Code aren't working.
#Code
N=int(input("enter number of students in the range of 2 to 5"))
physics_students=[]
#creating a list of student names with their grades
for i in range(N):
name = input()
score = float(input())
physics_students.append([name,score])
physics_students.sort()
#Removing the lowest grade
grades_list=[]
for i in range(N):
grades_list.append(physics_students[i][1])
grades_list.sort()
grades_list.remove(min(grades_list))
#finding out the names of students with second lowest grade
for i in range(N):
if physics_students[i][1]==grades_list[0]:
print("name",physics_students[i][0])
Test Cases which didn't pass are as follows:
Test Case 1:
4
abhay
-50
sri
-50
rakesh
-50
kishore
51
Test Case 2:
5
ram
20
ramesh
20
suresh
19
venkat
19
jaydeep
21
Hacker Rank's problem link
The blunder's here:
grades_list=[]
for i in range(N):
grades_list.append(physics_students[i][1])
grades_list.sort()
grades_list.remove(min(grades_list))
HackerRank Problem Descriptor
Note: If there are multiple students with the same grade, order their names alphabetically and print each name on a new line.
emphasis mine
Now consider if there were multiple students with the same lowest grade. Let's say the grades were [1, 1, 2, 3]. This becomes your sorted grades_list.
Now what happens when you call .remove()?
>>> grades_list.remove(min(grades_list))
>>> print(grades_list)
[1, 2, 3]
So you see, that the min isn't fully removed.
There are several ways to solve this, but I want to leave the implementation to you since this is a pretty good exercise.
Spoiler:
Hint: Maybe try keeping only distinct elements in your grades_list?
Other Issues
N=int(input("enter number of students in the range of 2 to 5"))
There shouldn't need to be a prompt there. It'll spoil the standard output and HackerRank will mark it as wrong.
print("name",physics_students[i][0])
This also. You can remove name. : )
here is the short code for problem.
score_list = [];
if __name__ == '__main__':
for _ in range(int(input())):
name = input()
score = float(input())
score_list.append([name, score])
second_highest = sorted(set([score for name, score in score_list]))[1]
print('\n'.join(sorted([name for name, score in score_list if score ==
second_highest])))

Selecting multiple elements from array python

this is a pretty basic question but here goes:
I would like to create an array and then would like to compare a user input to those elements within the array.
If one element is matched then function 1 would run. If two elements were matched in the array the an alternative function would run and so on and so forth.
Currently i can only use an IF statement with no links to the array as follows:
def stroganoff():
print ("You have chosen beef stroganoff")
return
def beef_and_ale_pie():
print ("You have chosen a beef and ale pie")
return
def beef_burger():
print ("You have chosen a beef burger")
return
ingredients = ['beef','mushrooms','ale','onions','steak','burger']
beef = input("Please enter your preferred ingredients ")
if "beef" in beef and "mushrooms" in beef:
stroganoff()
elif "beef" in beef and "ale" in beef:
beef_and_ale_pie()
elif "beef" in beef and "burger" in beef:
beef_burger()
As said, this is basic stuff for some of you but thank you for looking!
Since you only can work with IF statements
beef=input().split()
#this splits all the characters when they're space separated
#and makes a list of them
you can use your "beef" in beef and "mushrooms" in beef and it should run as you expected it to
So I understand your question such that you want to know, how many of your ingredients are entered by the user:
ingredients = {'beef','mushrooms','ale','onions','steak','burger'}
# assume for now the inputs are whitespace-separated:
choices = input("Please enter your preferred ingredients ").split()
num_matches = len(ingredients.intersection(choices))
print('You chose', num_matches, 'of our special ingredients.')
You may do something like:
# Dictionary to map function to execute with count of matching words
check_func = {
0: func_1,
1: func_2,
2: func_3,
}
ingredients = ['beef','mushrooms','ale','onions','steak','burger']
user_input = input()
# Convert user input string to list of words
user_input_list = user_input.split()
# Check for the count of matching keywords
count = 0
for item in user_input_list:
if item in ingredients:
count += 1
# call the function from above dict based on the count
check_func[count]()

Categories

Resources