3

I wish to write a Python program that gets a number from the keyboard, and outputs a number built from the minimum of each pair of digits of the original number. For example:

Enter number please:  84372216
Original number: 84372216 
New number:   4321

I had an idea to transform the original number into a string, to create a list of digits (chars) in the odd locations and the even locations, and then to compare them by the index of the lists. This doesn't sound too efficient or easy to implement, as it involves too many conversions from int to string and vice versa. The advantage is that this solves easily the problem of a number with odd number of digits.

Is there a way of solving this problem without using strings ?

Thank you.

vaultah
  • 44,105
  • 12
  • 114
  • 143
Jankel
  • 33
  • 1
  • 7
  • 2
    No conversions needed: `s = input(); ''.join([min(t) for t in zip(s[::2], s[1::2])])`. For numbers with odd number of digits you could use `zip_longest`. – vaultah Dec 24 '17 at 14:29
  • 1
    @RoryDaulton I think the primary concern of OP for not using string is that he think it would require a lot of conversions from string to int, which is clearly not the case. I didn't get your second part of comment. – Sohaib Farooqi Dec 24 '17 at 14:34
  • @RoryDaulton After `s = input()` `s` is a string. I only used empty string in `''.join`, what should I have used instead? I don't get the last sentence either. – vaultah Dec 24 '17 at 14:34

5 Answers5

3

Use zip() on slices of the original number and min() on each tuple returned:

>>> number = input('Enter number please: ')
Enter number please: 84372216
>>> print('Original number: {}'.format(number))
Original number: 84372216
>>> new_number = ''.join(min(tup) for tup in zip(number[::2], number[1::2]))
>>> print('New number: {}'.format(new_number))
New number: 4321
srikavineehari
  • 2,502
  • 1
  • 11
  • 21
2
num = 84372216
int(''.join(min(i) for i in zip(*[iter(str(num))]*2)))
#4321

list(zip(*[iter(str(num))]*2)) splits num into pairs as below

[('8', '4'), ('3', '7'), ('2', '2'), ('1', '6')]

Then use min and join combination to get the output

Transhuman
  • 3,527
  • 1
  • 9
  • 15
2

Transhuman's answer is cool, but here's a more readable version:

s = str(num)
r = int(''.join(min(s[i:i+2]) for i in range(0, len(s), 2)))

Another nifty trick is to use re.findall:

r = int(''.join(min(i) for i in re.findall('..', str(num))))

EDIT

I didn't notice you said "without using strings". In that case:

def f(n):
    return n if n < 10 else min(n % 10, n // 10 % 10) + 10 * f(n // 100)
Dan Gittik
  • 3,460
  • 3
  • 17
  • 24
  • Is this code not working or am I missing something ? It gave me 8321 for the above example. I mean the second code, without strings. The string code works nice. – Jankel Dec 24 '17 at 15:12
  • Nope, it's working. You sure you haven't called it on ``8437221`` or ``8437216`` by mistake (note that it works left to right)? – Dan Gittik Dec 24 '17 at 15:17
1

It's quick and dirty, but it works:

def pairmin( n ):
        result = 0
        mult = 1
        while n > 0:
                if n > 10:
                        result =  min( n % 10, (n / 10) % 10 ) * mult + result
                else:
                        result = n * mult + result
                n = n / 100
                mult = mult * 10
        return result

print( pairmin( 84372216 ) )
print( pairmin( 8372216 ) )
Nick
  • 4,820
  • 18
  • 31
  • 47
1

A slight variation of what Vaultah posted in comment above. You can use map function, supply it with consecutive pairs and determine minimum from it.

 s = "84372216"
 "".join(list(map(lambda x,y: str(min([x,y])), s[::2],s[1::2])))
 #'4321'

Here map(lambda x, y: str(min([x,y])) takes two arguments from iterable s[::2],s[1::2] and determine what is the minimum value from the supplied args. Min result is being cast to str to join the final result. You can however cast the result back to int if you require further processing of result. Just add int() to overall expression.

To unserstand s[::2],s[1::2], please check Understand Python Slice Notation. Slice notation works like s[start:end:step]

Sohaib Farooqi
  • 5,457
  • 4
  • 31
  • 43