# Finding the "Runner Up" (Second Highest Value)

• WWGD
In summary: I don't know, it didn't say.I don't know if it would accept 1,3,2,4. Some input parsers will recognize comma-delim'ed lists.

#### WWGD

Gold Member
Hi,
I have a Python 3 algorithm to output the "Runner Up", not originally mine:
We're given a list of numbers and we're expected to output the second largest of these.
It runs well, but I'm unclear as to what output is/are expected

Python:
n=int(input())
arr=map(int,input().split())
print(sorted(list(set(arr))[-2])

So that, e.g., for [1,4,2,4], it would output 2, the 2nd largest value.

I (think) I get the idea:
We start with a list(?). We then use 'map" to iterate over int, which I assume
means we turn each element into an int data type, as map() takes input(fun, iter), i.e., it
iterates a function on a data structure and stores it as an array.
Then 'set' turns it into a set, eliminating repeated entries, turns it into a list,
sorts it, returns the second highest element through the [-2]

Thing is I'm prompted to enter an input, and I'm not clear on just what input that is.
I've tried the obvious, an integer, which works, but I get the error:

Python:
      AttributeError                            Traceback (most recent call last)
<ipython-input-12-57efaba15b2f> in <module>
1 n=int(input())
----> 2 arr=map(int, input.split())
3 print(sorted(list(set(arr)))[-2])
4

AttributeError: 'function' object has no attribute 'split'

If I try to input a list instead, I get an error too :

---------------------------------------------------------------------------
Python:
     ValueError                                Traceback (most recent call last)
<ipython-input-13-57efaba15b2f> in <module>
1 ----> n=int(input())
2 arr=map(int, input.split())
3 print(sorted(list(set(arr)))[-2])
4

ValueError: invalid literal for int() with base 10: '[1,3,2,4]'

Any ideas?

Last edited by a moderator:
What exactly is your input string?
Is it '[1,3,2,4]'?
Will it accept just a comma-delimited list of integers?

WWGD
I Googled python int(input()) to see what it wants and the results seem to be informative.

DaveC426913 said:
What exactly is your input string?
Is it '[1,3,2,4]'?
Will it accept just a comma-delimited list of integers?
There is no default input string. That's part of the problem. It runs in Hackerrank(HR) and it's deemed correct, but it doesn't ask for any input when it runs. HR provides, under the hood, a few use cases. But I don't know what these are.

I confess I'm a little unclear where the code comes from and its context.

Is the code you've provided declared by fiat to be correct and working? Or is it perhaps a generic snippet that needs to be provided some code to turn it into a working function?

Your code says input().split() but the error says input.split(), and the error is consistent with that typo - the function object input has no method split, although the string the input function would return should have.

DaveC426913
DaveC426913 said:
I confess I'm a little unclear where the code comes from and its context.

Is the code you've provided declared by fiat to be correct and working? Or is it perhaps a generic snippet that needs to be provided some code to turn it into a working function?
I ran it in HR's IDE and it replied it was correct. HR provides it's own use cases to test. But it does that without telling you what these use cases are.

WWGD said:
There is no default input string. That's part of the problem. It runs in Hackerrank(HR) and it's deemed correct, but it doesn't ask for any input when it runs. HR provides, under the hood, a few use cases. But I don't know what these are.
No, I meant what input were you giving it when it split out the error in the second case: ValueError: invalid literal for int() with base 10: '[1,3,2,4]' ?

I wonder if it might accept 1,3,2,4. Some input parsers will recognize comma-delim'ed lists.

WWGD
DaveC426913 said:
No, I meant what input were you giving it when it split out the error in the second case: ValueError: invalid literal for int() with base 10: '[1,3,2,4]' ?
Ah, I used first [1,2,3,4], then [1,2,3,1] . Got the same error both times.

WWGD said:
Ah, I used first [1,2,3,4], then [1,2,3,1] .
Well try it without the square brackets.

WWGD
I tried both 1,2,3,1 and then 1231. Both got error messages.

OK, I'm still not sure if we're allowed to critique the code. i.e. I might do it differently.

As for HR accepting it, did it simply check the syntax? Or does it actually run test cases? and does it check the output for correctness?

WWGD
DaveC426913 said:
OK, I'm still not sure if we're allowed to critique the code. i.e. I might do it differently.

As for HR accepting it, did it simply check the syntax? Or does it actually run test cases? and does it check the output for correctness?
It runs a few test cases, under the hood, i.e., without telling you which, and only tells you if the runs were successful.
Edit: I just don't want to change the code here, because it makes perfect sense to me, and I'm training, so this is not just for the sake of intellectual inquiry.

You are asked for two inputs. The first is a number that doesn't seem to be used for anything. The second expects a space separated list of integers, so 1 2 3 4 should work for that.

WWGD
Ibix said:
You are asked for two inputs. The first is a number that doesn't seem to be used for anything. The second expects a space separated list of integers, so 1 2 3 4 should work for that.
I had the impression that the first input is the length of the list. But will give it a try. Thx.

WWGD said:
I had the impression that the first input is the length of the list. But will give it a try. Thx.
Thx, did not work out.

Did you correct the typo in input().split()?

WWGD
"The input() function reads a line from the input (usually from the user), converts the line into a string by removing the trailing newline, and returns it. If EOF is read, it raises an EOFError exception."

Ibix points out there are two input prompts, the first of which is not used.
That suggests it should accept

0
followed by
1324

WWGD
Ibix said:
Did you correct the typo in input().split()?
Yeah, that too.

DaveC426913 said:
"The input() function reads a line from the input (usually from the user), converts the line into a string by removing the trailing newline, and returns it. If EOF is read, it raises an EOFError exception."

Ibix points out there are two input prompts, the first of which is not used.
That suggests it should accept

0
followed by
1324
Sorry, I just was able to use my paint to copy the output of the HR run:
u

So the issue is how to enter the input as you did, but it doesn't seem to give me that option. Let me retry.
Edit: @Ibix @DaveC426913 They're closing the Public Library in a few min. Thanks for your help, let's continue tomorrow.

WWGD said:
So that, e.g., for [1,4,2,4], it would output 2, the 2nd largest value.
Before delving too deep into syntax, are you sure this is what you want? [2,2,2,2,2,1] means the runner-up is 1? [1,1,1,1,1] means "no solution"?

I think most people would say the runner up is "sort the list and take #2" (this is not terribly efficient, and there are faster ways to do this, but that's the expected behavior), If you are sure you want something else, I would definitely call it something else.

WWGD
Before delving too deep into syntax, are you sure this is what you want? [2,2,2,2,2,1] means the runner-up is 1? [1,1,1,1,1] means "no solution"?

I think most people would say the runner up is "sort the list and take #2" (this is not terribly efficient, and there are faster ways to do this, but that's the expected behavior), If you are sure you want something else, I would definitely call it something else.
Well, yes, thanks, I do want what I asked for, at least until I pass the training exam. And I do understand the algorithm well-enough to remember it, and likely be able to apply it in slightly different situations .
I believe the problem arises from not knowing how to enter the input, a number and then a list.
But now I'm on my phone and not my PC, so I'll wait till tomorrow for further changes.

OK, just want to make sure you're solving the right problem. (Which is often half the battle)

WWGD
You need to take more care. Clearly what you typed in your OP is not what you typed in your IDE: apart from anything else the change of indent is a syntax error.

The correct code is shown below, with some notes or see it running at replit: https://replit.com/@pbuk/ThinUnlinedParentheses#main.py
Python:
# The following line reads unused input so I have commented it out.
# n = int(input())

# The error message shows that you missed out () after input.
arr = map(int, input().split())

# The line in your OP is missing a ) before the [.
print(sorted(list(set(arr)))[-2])

# Input '1 6 8 5 2 8 8 5 6 6' without the quotes.
# Outputs '6'

WWGD
Thanks.
The thing is the error messages show up when I input data. I ran the program as a stand alone in Hackerrank, which generated several cases, which checked out without a problem.
The error messages are generated only when I enter input into the program. Likely because I'm not entering the input in the right format/data type. I'm having trouble reading your post from my phone. Will look it up tomorrow. Thank you.

pbuk said:
You need to take more care. Clearly what you typed in your OP is not what you typed in your IDE: apart from anything else the change of indent is a syntax error.

The correct code is shown below, with some notes or see it running at replit: https://replit.com/@pbuk/ThinUnlinedParentheses#main.py
Python:
# The following line reads unused input so I have commented it out.
# n = int(input())

# The error message shows that you missed out () after input.
arr = map(int, input().split())

# The line in your OP is missing a ) before the [.
print(sorted(list(set(arr)))[-2])

# Input '1 6 8 5 2 8 8 5 6 6' without the quotes.
# Outputs '6'
Thanks, @pbuk ,all, you were right all along. Egg on my face :(
First the missing () .
After fixing, I was indeed prompted to succesively enter two 1-line inputs. Second
was to be entered with spacing, as in:
2 3 4 5 2

" Mystery" (carelessness) solved. Sorry.
Thanks to all.
That led to

Sort of a recap...
WWGD said:
We're given a list of numbers and we're expected to output the second largest of these.
Python:
n=int(input())
arr=map(int,input().split())
print(sorted(list(set(arr))[-2])

So that, e.g., for [1,4,2,4], it would output 2, the 2nd largest value.
I've edited the code snippet above to fix the indentation.
Since you're given a list of numbers, the algorithm can assume that a variable containing a list of numbers, presumably ints, already exists. The first line of your code above seems to be intended to set n to a single number. However, n isn't used again. If you haven't already read the documentation for input(), it takes input from the user in the form of a string. The expression int(input()) converts that string to an integer. I haven't investigated what your second line of code does, but I suspect that it doesn't work.

If I were doing this problem, I would write a function whose input parameter is a list of numbers, and whose return value is the "runner-up", the second largest number in the list. Filling the list would be done elsewhere so that the function's task would be nothing more than finding the second-largest value of the list input parameter.

I'm using my laptop at the moment, which doesn't have Python installed. However, I do have Erlang installed, so I'll show an alternative approach to the problem.

Code:
-module(runnerup).
-export([second/1]).

second([]) -> {error, empty};
second([_|[]]) -> {error, singleton}
second(List) ->                          %% General version
SortedList = lists:sort(List),        %% Sorts from small to large
RevList = lists:reverse(SortedList),
hd(tl(RevList)).         %% Return the first element of the tail

The first two lines are boilerplate, listing the name of this module and the function it exports, second(). The /1 suffix indicates the "arity," or number of parameters it takes.

Following that are three versions of this function: one that handles empty lists (line 4), one that handles lists with only one element (line 5), and the last (starting on line 6) that handles lists with at least two elements.

Obviously, lists with zero or one element can't have a second largest element, so these versions return a tuple that indicates an error and why that's an error.

The third version sorts the passed list using the sort() function in the lists library module. There are two sort() functions in that module. The one I'm using takes one argument. By default, this sort() version returns a list sorted by increasing order.

The next line of code reverses the sorted list, using the reverse() function of the lists module.

The last line of code, hd(tl(RevList)) requires a bit of explanation as it uses the built-in hd and tl functions. which return, respectively, the head and tail of a list. The head of a list is its first element. The tail of a list is everything past the head. As far as I know, there is no counterpart in Python, but these functions are common in other function languages such as Lisp and likely others.

If the list is [6, 4, 3, 1], the head is 6 and the tail is the sublist [4, 3, 1]. The head of the tail is therefore 4, the second largest value in the list.

Mark44 said:
I haven't investigated what your second line of code does, but I suspect that it doesn't work.
It works fine, creating a list of integers from the space-separated numbers in the input string.

Mark44 said:
If I were doing this problem, I would write a function whose input parameter is a list of numbers,
This is a HackerRank problem and the format of the input (a string of numbers with spaces in between) is part of the specification (the HackerRank backend presumably directs its test cases via stdin).

Mark44 said:
and whose return value is the "runner-up", the second largest number in the list.
...
Your solution does not deal with duplicates in the manner specified in the problem: that is the whole point of converting to and from a set (which eliminates duplicates).

Mark44 said:
The head of a list is its first element. The tail of a list is everything past the head. As far as I know, there is no counterpart in Python, but these functions are common in other function languages such as Lisp and likely others.
More powerful in Python:
Python:
myList = 'a b c d'.split()
print(myList)      # ['a', 'b', 'c', 'd']
print(myList[1:])  # ['b', 'c', 'd'] (tail)
print(myList[0:2]) # ['a', 'b'] (longer head)
print(myList[2:])  # ['c', 'd'] (shorter tail)

Mark44 said:
If the list is [6, 4, 3, 1], the head is 6 and the tail is the sublist [4, 3, 1]. The head of the tail is therefore 4, the second largest value in the list.
Yes, lists are a pain in Lisp(!) what if you wanted the 137th element? Compare with myList[136] in Python (and similar in most other procedural languages).

Last edited:
pbuk said:
This is a HackerRank problem and the format of the input (a string of numbers with spaces in between) is part of the specification (the HackerRank backend presumably directs its test cases via stdin).

pbuk said:
Your solution does not deal with duplicates in the manner specified in the problem
In reply to both of the above, I didn't see the problem description as shown on HackerRank.
pbuk said:
Yes, lists are a pain in Lisp(!) what if you wanted the 137th element?
The nth() function in the lists module returns the Nth element of its list parameter. E.g., assuming the list has at least 137 elements, this will do the trick:
Code:
lists:nth(137, List)

There's also the nthtail() function, also in the lists module, that returns the sublist (tail) following the Nth element.

pbuk