-2

The following code snippet is written for returning the numbers which don't contain the number which having repeated digits.

For example, if an input is 7 the program should return the count of numbers 7 counts of (1,2,3,4,5,6,7) then output should be 7.

If an input is 23 the program should return the count of numbers 23 count of (1,2,3,4,5,6,7,8,9,10,12,13,14,15,16,17,18,19,20,21,23) here the count excluded the numbers like 11,22 and output should be 21.

To optimize this code what should I do?

def nonrep1(n):
    return sum(all(c != d for c, d in zip(str(i), str(i)[1:])) for i in xrange(1, n+1))

I have to optimize this code, how do I do that?

test case 1:

simple input:

7

simple output:

7

test case 2:

simple input:

3456

simple output:

2562
Community
  • 1
  • 1
Mickey Jack
  • 115
  • 1
  • 6
  • 5
    Probably a candidate for https://codereview.stackexchange.com/ – languitar Apr 06 '17 at 08:33
  • 2
    The question in this form would likely not be well received on Code Review, as it lacks all context as to what the code is for, and may get closed as unclear. If it is to get posted there I would strongly recommend to add more context. – Phrancis Apr 06 '17 at 08:36
  • 1
    What do you mean by 'optimize this code'? Do you want to optimize length of the source code? Performance? Number of used functions? Readability of source code?... – kravemir Apr 06 '17 at 08:38
  • Performance and number of function used @kravemir – Mickey Jack Apr 06 '17 at 08:41
  • I'm looking at this so please don't close the question – user3684792 Apr 06 '17 at 08:56
  • It looks like algorithmic homework. Optimizing brute-force search will only result in minimal improvement. Raise a question at: http://math.stackexchange.com/ – kravemir Apr 06 '17 at 10:25
  • @ kravemir actually optimising the above using cython results in a factor of 80 improvement despite no real conceptual difference – user3684792 Apr 06 '17 at 12:25
  • With "repeated digits", do you mean *consecutive* repeated digits? –  Apr 07 '17 at 01:27

1 Answers1

-1

Always surprised with how slow 'pythonic' solutions can be. Here is a factor of 80 speedup using cython:

from libc.math cimport log10
from cython.operator cimport preincrement as preinc
import cython

@cython.cdivision(True)
cdef int add_number(int i):
    cdef int cur_last = i % 10, next_last = 0
    cdef int cur_val = i / 10

    cdef int jj = 0
    for jj in xrange(int(log10(cur_val) + 1)):
        next_last = cur_val % 10
        if next_last == cur_last:
            return 0
        cur_val /= 10
        cur_last = next_last

    return 1

cpdef int cython_nonrep1(int n):
    cdef int s = 0
    cdef int i = 0
    if n < 10:
        return n

    for i in xrange(10, n+1):
        s += add_number(i)
    return s

To use it, save it in a .pyx file and use pyximport (or build it with distutils etc)

Some benchmarks:

%timeit nonrep1(3456)
100 loops, best of 3: 4.92 ms per loop


% timeit cython_nonrep1(3456)
10000 loops, best of 3: 63.4 µs per loop
Community
  • 1
  • 1
user3684792
  • 2,542
  • 2
  • 18
  • 23