Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a number into another according to a rule

i have a sequence of numbers like:

1234
5678
778899

I want to convert them into a form where they start from the lowest number possible

Example:

5678 would be 1234
778899 would be 112233
2452 would be 1231

I tried to do:

index = 0
digit = 1
newCode = []
newCode.append(digit)

while index != len(codice)-1:
    index += 1

    if code[index] == code[index-1]:
        newCode.append(digit)

    else:
        digit += 1
        newCode.append(digit) 

But it converts numbers like 5675 to 1234, so it doesn't work. Is there a better way to do this and what am i doing wrong?

like image 316
John Poe Avatar asked Oct 29 '17 17:10

John Poe


Video Answer


4 Answers

This can be done with dictionaries:

Edit: So I might have misinterpreted the question. From the example cases I presumed it meant convert the first digit appearing to a 1, the second to a 2, etc..

x = "5512"
function = {}
count = 1
output = ""

for digit in x:
     if digit in function:
         output += function[digit]
     else:
         function[digit] = str(count)
         count += 1
         output += function[digit]

print(output)
#Outputs 1123 (5->1, 1->2, 2->3)
like image 102
wjmccann Avatar answered Oct 06 '22 22:10

wjmccann


t = {}
int(''.join(t.setdefault(d, str(len(t) + 1)) for d in str(n)))

Demo:

>>> for n in 5678, 778899, 2452:
        t = {}
        print(n, '->', int(''.join(t.setdefault(d, str(len(t) + 1)) for d in str(n))))

5678 -> 1234
778899 -> 112233
2452 -> 1231
like image 41
Stefan Pochmann Avatar answered Oct 06 '22 21:10

Stefan Pochmann


You only check whether the digit is equal to the last digit, but that does not work for, e.g., 2452. You have to keep track of all the past digits, using e.g. a dictionary, as in @wjmccann answer.

You can make this a bit shorter, though, by combining a defaultdict with a count. The defaultdict will memorize already seen digits, and the count provides values for new ones.

import itertools, collections, functools

def convert(n):
    d = collections.defaultdict(functools.partial(next, itertools.count(1)))
    return int(''.join(str(d[x]) for x in str(n)))

print(convert(5678))   # 1234
print(convert(778899)) # 112233
print(convert(2452))   # 1231

Or even shorter, as suggested in comments:

def convert(n):
    d = collections.defaultdict(list("987654321").pop)
    return int(''.join(d[x] for x in str(n)))

This again uses defaultdict, but uses pop from a list of digits as the factory function, removing elements from the end of the list as new digits are needed.

like image 28
tobias_k Avatar answered Oct 06 '22 21:10

tobias_k


TL;DR

The following code works for your requirements, making use of dictionary.

out = []
for n in num:
    digits = {}
    last_digit = 1

    new_num = ''

    #assign new values
    for s in str(n):                       #go through digits of number
        if digits.get(s, None) == None :    #if new digit not assigned
                digits[s] = str(last_digit)   #assign
                new_num += str(last_digit)
                last_digit += 1
        else :
                new_num += digits[s]         #get the val

    out.append(int(new_num))


print(out)

#driver values :

IN : num = [1234, 5678, 778899, 2452]
OUT : [1234, 1234, 112233, 1231]
like image 39
Kaushik NP Avatar answered Oct 06 '22 20:10

Kaushik NP