1

For all indices, i am required to remove that place's Digit. An integer a, converting it to String, i.e. S. And there after iterate through the length of string,

for i in range(len(S)):
    new =S[:i]+S[i+1:]

Is there any more efficient way to remove the digit from integer?

7
  • You remove the digit by position or you remove all occurences of a given number? Commented Oct 28, 2017 at 16:39
  • Please post the input and the desired output. Commented Oct 28, 2017 at 16:39
  • @GeorgeBou By position. Commented Oct 28, 2017 at 16:41
  • And the position is counted from left or right? Please add an example with I/O Commented Oct 28, 2017 at 16:41
  • Sorry, i made some mistake while typing. It has been corrected now. Commented Oct 28, 2017 at 16:43

4 Answers 4

2

UPDATE: It seems to be counterintuitive, but string-based solution is much faster then int-based. Here're my code and results in seconds for 103-, 226-digit and 472-digit numbers. I decided not to test 102139-digit number on my laptop :)

import timeit, math

digits = [100, 200, 500, 1_000, 2_000, 5_000, 10_000, 50_000, 100_000]

def print_str(n):
  s = str(n)
  for i in range(len(s)):
    #print(i)
    n2 = int(s[:i] + s[i+1:])


def print_int(a):
  p = 1
  while p <= a:
        n2 = a//p//10*p + a%p
        p *= 10

if __name__ == '__main__':
  number = 1
  for i in digits:
    n = 17**math.ceil(math.log(10**i, 17))
    str_ = timeit.timeit('print_str(n)', setup='from __main__ import print_str, n', number=number)
    int_ = timeit.timeit('print_int(n)', setup='from __main__ import print_int, n', number=number)
    print("{:8d}\t{:15.6f}\t{:15.6f}".format(len(str(n)), str_/number*1000, int_/number*1000))

Results (in milliseconds for particular number length):

$ time python3 main.py
     101           0.169280        0.185082
     201           0.502591        0.537000
     501           3.917680        3.195815
    1001          13.768999       22.781801
    2001         114.404890      120.546628
    5001        1066.541904     1625.172070
   10002        8033.144731     8802.031382
   50001      937385.167088  1045865.986814
  100002     7800950.456252  8189620.010314

First column - number of digits, second one - time in milliseconds for the str-based solution, and third - for the int-based.

But how is it possible?

It could be understood if we remember how endless integer numbers are constructed in Python. Under the hood there's an array of 15- or 30-bit integers which being joined produces the result number. So when you divide this number you have to walk through the whole array and modify every every digit. Also take in account complexity - sometimes you have to add or subtract from more significant digit, that complicates process.

When you use strings, you only copy bytes from one place to another. It's extremely fast procedure made with internal cpu instruction.

But what if we do not need conversion to int? For example, we want to print a number, so having it in a string form is better? How will it enfaster process?

Here're results - also in ms for different length

 $ time python3 main.py
     101           0.051510        0.124668
     201           0.091741        0.442547
     501           0.357862        2.562110
    1001           0.787016       15.229156
    2001           2.545076      111.917518
    5001           4.993472     1334.944235

UPD: Bencharks of updated versions:

$ time python3 main2.py

digits        str1        str2        int1        int2
   101       0.047       0.101       0.110       0.073
   201       0.091       0.315       0.380       0.145
   501       0.338       2.049       2.540       0.778
  1001       1.342      16.878      16.032       1.621
  2001       1.626      85.277      97.809       5.553
  5001       4.903    1039.889    1326.481      32.490
 10002      15.987    7856.753    9512.209     129.280
 20001      72.205   60363.860   68219.334     487.088

real    2m29.403s
user    2m27.902s
sys 0m0.577s
Sign up to request clarification or add additional context in comments.

7 Comments

But this will take O(|S|) to generate n for one i. Is there any way so that this can be modified?
It's a new requirement. Do you have really long number, so it matters?
Yeah, it is really a long number, no. of digits in a number are 10^5.
@RudrakshaBaplawat Length makes sense. I've updated the answer with some tests.
@StefanPochmann Thank you for you attention and ideas. I've introduced some changes.
|
2

Another answer producing integers, much faster at that than my other answer and the OP's string solution:

>>> a = 12345

>>> digits = [0] + list(map(int, str(a)))
>>> p = 10**(len(digits) - 2)
>>> for x, y in zip(digits, digits[1:]):
        a += (x - y) * p
        p //= 10
        print(a)

2345
1345
1245
1235
1234

This goes from 2345 to 1345 by replacing the 2 with the 1, which it does by subtracting 2⋅1000 and adding 1⋅1000. Or in short, by adding (1-2)⋅1000. Then it goes from 1345 to 1245 by adding (2-3)⋅100. And so on.

Benchmark results, using a modified version of Eugene's program:

digits        str1        str2        int1        int2
   101       0.085       0.255       0.376       0.157
   201       0.161       0.943       1.569       0.389
   501       0.514       9.180       9.932       0.983
  1001       0.699      30.544      39.796       2.218
  2001       1.402     203.429     291.006       8.435
  5001       4.852    2691.292    3983.420      50.616
 10002      16.080   21139.318   29114.274     197.343
 20001      54.884  167641.593  222848.841     789.182

str1 is the time for the OP's string solution, producing strings.

str2 is the time for the OP's string solution, turning the strings into ints.
int1 is my other solution producing ints.
int2 is my new solution producing ints.

No surprise that the OP's string solution is the fastest overall. Its runtime complexity is quadratic in the number of digits. Which is the total output size, so that's optimal. My new solution is quadratic as well, but doing calculations is of course more work than pure copying.

For producing ints, my new solution is by far the fastest. My old one and the OP's have cubic runtime for that (with the OP's apparently being around 1.4 times as fast as my old one).

The benchmark program (modified version of Eugene's):

import timeit, math

digits = [100, 200, 500, 1_000, 2_000, 5_000, 10_000, 20_000]

def print_str_1(n):
  s = str(n)
  for i in range(len(s)):
    #print(i)
    n2 = s[:i] + s[i+1:]

def print_str_2(n):
  s = str(n)
  for i in range(len(s)):
    #print(i)
    n2 = int(s[:i] + s[i+1:])

def print_int_1(a):
  p = 1
  while p <= a:
        n2 = a//p//10*p + a%p
        p *= 10

def print_int_2(a):
    digits = [0] + list(map(int, str(a)))
    p = 10**(len(digits) - 2)
    for x, y in zip(digits, digits[1:]):
        a += (x - y) * p
        p //= 10
        #print(a)

if __name__ == '__main__':
  print(("{:>6}" + 4 * "{:>12}").format('digits', 'str1', 'str2', 'int1', 'int2'))
  number = 1
  for i in digits:
    n = 17**math.ceil(math.log(10**i, 17))
    str1 = timeit.timeit('print_str_1(n)', setup='from __main__ import print_str_1, n', number=number)
    str2 = timeit.timeit('print_str_2(n)', setup='from __main__ import print_str_2, n', number=number)
    int1 = timeit.timeit('print_int_1(n)', setup='from __main__ import print_int_1, n', number=number)
    int2 = timeit.timeit('print_int_2(n)', setup='from __main__ import print_int_2, n', number=number)
    print(("{:6d}" + 4 * "{:12.3f}").format(len(str(n)), *(x/number*1000 for x in (str1, str2, int1, int2))))

Comments

0

You could also do it without strings:

>>> a = 12345
>>> p = 1
>>> while p <= a:
        print a/p/10*p + a%p
        p *= 10

1234
1235
1245
1345
2345

Comments

0
#This Method will help you Get first n elements 
    def GetFirstNNumber(number,n):
        lenght=int(math.log10(i))+1 #to know the number of digit in the number take log10
        print(i//(10**(lenght-n)))

#This Method will help you Remove first n elements
    def RemoveFirstNNumber(number,n):
        lenght=int(math.log10(i))+1 #to know the number of digit in the number take log10
        print(i%(10**(lenght-n)))
        
    
    i=25985
    n=3
    GetFirstNNumber(i,n)
    RemoveFirstNNumber(i,n)

Output

259
85

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.