Home > Software design >  Python: Replacing numbers in a range that meet the conditions with symbols
Python: Replacing numbers in a range that meet the conditions with symbols

Time:07-10

Question:

Take two integers a and b, output all the integers inside the range from b to b. Replace numbers ended by 3 and 7 with the Asterisk* symbol; And for each integer inside the range, if the sum of all digits is greater than or equal to 8, replace the integer with the % symbol (except for the ones ended with 3 and 7).

Sample Input:

a = 12
b = 30

Sample Output:

12 * 14 15 16 * % % 20 21 22 * 24 25 % * % % 30

My codes:

a = int(input())
b = int(input())

summation = 0
for i in range(a, b   1):
    if (i == 3 or i == 7) or (i % 10 == 3 or i % 10 ==7):
        print('*', end = ' ')
        while i <= b:
            n = i % 10
            i = i // 10
            summation = i   n
            break
            if summation >= 8:
                print('%', end = ' ')
    else:
        print(i, end = ' ')

My Output:

12 * 14 15 16 * 18 19 20 21 22 * 24 25 26 * 28 29 30

Apparently, I've noticed there's something wrong with my code's logic. But I just can't come up with any solutions yet, please help provide some tips to help me fix my logic, appreciate it!

Additionally, I would like tips relating to my current method, converting to strings will be easier but I prefer to understand more about iteration, thank you!

CodePudding user response:

Use this:

def solution(a, b):
    r = list(map(str, range(a, b 1)))  # Get list of numbers and convert to str
    for i, s in enumerate(r):          # Loop through r
        if s[-1] in '37':              # Check if s ends in 3 or 7
            r[i] = '*'                 # If it does, replace with '*'
        elif sum(map(int, s)) >= 8:    # If it doesn't, check if digits add up to more than 8
            r[i] = '%'                 # If they do, replace with '*'
    return ' '.join(r)                 # Return r, joined by ' '


print(solution(12, 30))

Output: 12 * 14 15 16 * % % 20 21 22 * 24 25 % * % % 30


Without converting to strings:

def solution2(a, b):
    r = list(range(a, b 1))                     # Get list of numbers
    for i, n in enumerate(r):                   # Loop through r
        if n % 10 in (3, 7):                    # Check if n ends in 3 or 7
            r[i] = '*'                          # If it does, replace with '*'
        elif sum(int(d) for d in str(n)) >= 8:  # Otherwise, check sum of digits
            r[i] = '%'                          # If greater than or equal to 8, replace with '%'
    return r

print(*solution2(12, 30), sep=' ')

Output: 12 * 14 15 16 * % % 20 21 22 * 24 25 % * % % 30

CodePudding user response:

No need to convert the values to strings. You could do it like this:

a = 10
b = 30
result = []

def sd(n):
    r = 0
    while n > 0:
        r  = n % 10
        n //= 10
    return r

for n in range(a, b 1):
    if n % 10 in {3, 7}:
        result.append('*')
    elif sd(n) >= 8:
        result.append('%')
    else:
        result.append(n)

print(' '.join(map(str, result)))

Output:

10 11 12 * 14 15 16 * % % 20 21 22 * 24 25 % * % % 30

CodePudding user response:

This answer will aim to debug your existing program, but see also @Stuart's answer for a simpler method.

The while loop in which you calculate the sum is inside the if statement for ending with a 3 or 7. But a % should only be possible when the number doesn't end in 3 or 7, so the loop should be in the else statement.

Then the default case, printing out the number directly, can be done in an else block attached to the while loop as follows:

if (i == 3 or i == 7) or (i % 10 == 3 or i % 10 ==7):
    ...
else:
    while i <= b:
        ...
    else:
        print(i, end=' ')

The else block will be executed if the while loop finishes without breaking, i.e. if % isn't printed.

The condition on the while loop is incorrect. i <= b is always going to be true, because i starts less than or equal to b and only decreases. In order to loop for as long as i has digits remaining, this should be i > 0.

The summation is being calculated incorrectly. You want to cumulatively sum each n in each pass through the while loop, so rather than doing i n, you want summation n to add the new n to the previous total. summation must also be reset to 0 just before the while loop.

The break statement should be at the bottom of the if statement to only break if the condition is met.

Finally, in order to print the original i in the case that the digit sum is less than 8, we need to keep it rather than modifying in the while loop. We can copy the value of i to m and use m instead:

m = i
summation = 0
while m > 0:
    n = m % 10
    m = m // 10
    summation = summation   n
    ...

Final code:

a = int(input())
b = int(input())

for i in range(a, b   1):
    if (i == 3 or i == 7) or (i % 10 == 3 or i % 10 == 7):
        print('*', end=' ')
    else:
        m = i
        summation = 0
        while m > 0:
            n = m % 10
            m = m // 10
            summation = summation   n
            if summation >= 8:
                print('%', end=' ')
                break
        else:
            print(i, end=' ')

CodePudding user response:

This is aa possible one line solution :)

print(*('*' if n % 10 in (3, 7) else ('%' if sum(int(x) for x in str(n)) >= 8 else n) for n in range(a, b   1)))

Output with a=12 and b=30:

12 * 14 15 16 * % % 20 21 22 * 24 25 % * % % 30
  • Related