sumanth kumar
sumanth kumar

Reputation: 39

How to do this using lambda function

you are given an array A of size N. You need to print the array in the decreasing order of number based on sum of digits of the numbers up to single digit. In case two numbers have same sum value, the larger one's value comes first.

I am able to put the first condition in lambda but not the second one My code

test_cases=int(input())
n=int(input())
arr=list(map(int,input().split()))

print(sorted(arr,key=lambda x:(sum(list(map(int,list(str(n))))), ?)))

I am a beginner

Upvotes: 1

Views: 331

Answers (2)

The biggest problem I see is that your teacher has not taught you the process of software development. That should have been lesson 1, the very first thing. No matter how advanced your skills, there are some basics:

  1. Decompose the problem into functions/classes that have clear, understandable and testable purpose.

  2. Test everything. Even a single non-trivial test case is better than nothing.

  3. Document the building blocks of your code: functions/methods, classes and modules. Even a single sentence is better than nothing - but don't just repeat what the name of the function implies

One way to approach such problems is to do them in steps, with later steps building upon the previous steps.

Thus, let's start with the easiest: the sum of digits.

def digit_sum(num):
    """Computes a sum of digits of a number.
    The number can be an integer or a string.

    >>> digit_sum("123")
    6
    >>> digit_sum(642)
    12
    """

    return sum(map(int, str(num)))

The function includes a short description, and examples of how it works. This documentation is called a docstring: a string that appears as the first expression in the function/class/module/script.

The built-in help function can access it for us - it does that as well with Python's built-in functions, and with modules and their contents.

>>> help(digit_sum)
Help on function digit_sum in module __main__:

digit_sum(num)
    Computes a sum of digits of a number.
    The number can be an integer or a string.
    
    >>> digit_sum("123")
    6
    >>> digit_sum(642)
    12

Now we can try our function out. We manually enter digit_sum(123) and get 7 as the output - the sum of digits of 124 is 1+2+4 = 7:

>>> digit_sum(124)
7

That seems tedious. You need to be able to trust your code at all times - trust, but verify! When you change things, you should be able to quickly test every function/method/class/module to make sure they work as expected. This allows you to embrace change: there's never a question "did my changes break stuff"? You should never worry about it: the machine is good with the tedium, and it must give you an answer right away. Ideally with a single keystroke.

Keyboard input should not be used when checking your code: you can add some interactive functionality but keep it disabled in an if False: block so that you can easily run automated tests without human interaction.

If you can't trust your code, if you can't easily test it anytime you want to, you will instead dread change, and the code will be quite awful as once something will work you'll be afraid to change it to make it nicer/easier to read/better performing - after all, you'll often end up breaking things, and then it'll take forever to fix on larger code bases, as the errors may not be caught until later. Never put yourself into this situation. If you dread change, your development process is not sane, and will drive you nuts.

So, how do we do it right?

First of all, I assume you're using IDLE as the development environment. It comes with every Python installation, so that's handy.

Whenever you start working on a homework assignment, open a new file for it. E.g. hw_5_1.py for problem 5.1, from the textbook/notes, and so on.

At the end of the file - after all the functions - add the two lines that run automated tests on your code. Your hw1.py would now look like:

"""Sumanth Kumar, Python Course, HW Assignment 1"""

def digit_sum(num):
    """Computes a sum of digits of a number.
    The number can be an integer or a string.

    >>> digit_sum("123")
    6
    >>> digit_sum(642)
    12
    """

    return sum(map(int, str(num)))

# after all the functions
import doctest
doctest.testmod()

doctest.testmod() runs the so-called doctests on each of the functions that have doctests included. Doctests are test cases included as examples in the docstring.

testmod() doesn't care about the narrative for humans, only about lines that start with >>> - it takes them as examples of input to the interpreter, evaluates them, and compares the output to the succeeding lines that don't start with >>>.

See also doctest documentation.

From Python's IDLE shell, just press F5 in the file hw1.py file, and the tests are executed for us - the doctest.testmod() statement does it. Thus far, you'll get no output: when the tests pass, doctest is quiet.

If running tests is hard, you won't ever do it - so never put yourself in that situation. Test everything, and make it as easy as hitting a single key (F5 in IDLE)!

Now let's add a function that fails - put it at the beginning of hw1.py:

def successful_failure():
    """This function returns 1.
    >>> successful_failure()
    1
    """

    return 42

The doctests claim that the function will return 1, but of course it doesn't return 1. We test via F5 and get some complaints:

>>> 
=================== RESTART: C:/Users/skumar/hw1.py ===================
**********************************************************************
File "C:/Users/skumar/hw1.py", line 50, in __main__.successful_failure
Failed example:
    successful_failure()
Expected:
    1
Got:
    42
**********************************************************************
1 items had failures:
   1 of   1 in __main__.successful_failure
***Test Failed*** 1 failures.

That's how test failures look. You can immediately attempt to fix the function, press F5, if tests fail, you keep working, until the tests pass. And make sure the test cases are correct, of course :)

Now we can implement the sort_key function, that provides the sorting key according to the assignment's requirement:

def sort_key(num):
    """Provides a sort key tuple for a number.
    The primary sort key is the sum of digits of the number,
    the secondary (tie-breaker) key is the number itself.
    The number can be an integer or a string.
    The sort key has integer values.

    >>> sort_key("123")
    (6, 123)

    >>> sort_key(321)
    (6, 321)
    """

    return (digit_sum(num), int(num))

Test the script again by pressing F5: all should be quiet.

Now we add the final function that generates the sorted sequence - the output in the assignment you're working on:

def problem_seq(nums):
    """Takes an iterable of numbers (integers or strings).
    Returns a list of the original values sorted in descending
    order of the sums of digits of values taken as integers.
    Whenever the digit sums are the same, the larger value itself comes first.
    The types of the input elements are preserved in the output list.

    >>> problem_seq([1, 2])
    [2, 1]
    >>> problem_seq([12, 23])
    [23, 12]
    >>> problem_seq([12, '21', "23", 32])
    [32, '23', '21', 12]
    >>> problem_seq((55, 64, 73, 46, 1, 984, 849, 6361))
    [984, 849, 6361, 73, 64, 55, 46, 1]
    """

    return sorted(nums, key=sort_key, reverse=True)

The reverse argument selects the descending sort order demanded in the assignment.

Press F5, and if tests pass: you're mostly done with this homework problem.

If you want to also provide some interactive functionality, you can add:

user_input = input("Enter numbers to sort, separated by space: ")
print(problem_seq(user_input.split()))

Exmaple interaction:

================== RESTART: C:/Users/skumar/hw1.py ===================
Enter numbers to sort, separated by space: 42 24 36
['36', '42', '24']
>>> 

The complete script:

"""Sumanth Kumar, Python Course, HW Assignment 1"""

def successful_failure():
    """This function returns 1.

    >>> successful_failure()
    1
    """
    
    return 1

def digit_sum(num):
    """Computes a sum of digits of a number.
    The number can be an integer or a string.

    >>> digit_sum("123")
    6
    >>> digit_sum(642)
    12
    """
    
    return sum(map(int, str(num)))

def sort_key(num):
    """Provides a sort key tuple for a number.
    The primary sort key is the sum of digits of the number,
    the secondary (tie-breaker) key is the number itself.
    The number can be an integer or a string.
    The sort key has integer values.

    >>> sort_key("123")
    (6, 123)

    >>> sort_key(321)
    (6, 321)
    """
    
    return (digit_sum(num), int(num))

def problem_seq(nums):
    """Takes an iterable of numbers (integers or strings).
    Returns a list of the original values sorted in descending
    order of the sums of digits of values taken as integers.
    Whenever the digit sums are the same, the larger value itself comes first.
    The types of the input elements are preserved in the output list.
    
    >>> problem_seq([1, 2])
    [2, 1]
    >>> problem_seq([12, 23])
    [23, 12]
    >>> problem_seq([12, '21', "23", 32])
    [32, '23', '21', 12]
    >>> problem_seq((55, 64, 73, 46, 1, 984, 849, 6361))
    [984, 849, 6361, 73, 64, 55, 46, 1]
    """

    return sorted(nums, key=sort_key, reverse=True)

# after all the functions
import doctest
doctest.testmod()

user_input = input("Enter numbers to sort, separated by space: ")
print(problem_seq(user_input.split()))

Upvotes: 1

rdas
rdas

Reputation: 21275

Use the element itself as the second value in a 2-value sort key.

print(sorted(arr,key=lambda x:(sum(list(map(int,list(str(x))))), x)), reverse=True)

Your sort key is then:

(sum of digits, number itself)

So your numbers get sorted based on their sum of digits, and if the sum of digits are the same, then based on the number itself.

You also need to pass reverse=True to make the sort decreasing since the default is to sort by increasing values.

Upvotes: 2

Related Questions