简体   繁体   中英

Why can't I find the number of zeroes by forming a loop

I want to find the number of zeroes included from 1 to 1000 by making a loop. The code is mentioned below.

var = 0
for n in range(1, 1001):
   for "0" in n:
       var += 1
       print(var)

The output which I should get is 192 but it is showing an error

   for "0" in n:
      ^
SyntaxError: can't assign to literal

Therefore, I would like to know from the community where am I going wrong.

THANK YOU

You probably want to do something like

var = 0
for n in range(0, 1001):
   for digit in str(n):
       if digit == '0':
           var += 1
           print(var)

the idea being that by turning the int into a str , you can iterate over each of the digits just like you can iterate over the letters in a word.

A more Pythonic approach to the same problem would be to simply do

sum(d == '0' for n in range(1001) for d in str(n))

or the shorter version

sum(str(n).count('0') for n in range(1001))

or the code-golfy

''.join(map(str, range(1001))).count('0')

A different approach would be the functional-ish

from collections import Counter
from operator import itemgetter
sum(map(itemgetter('0'), map(Counter, map(str, range(1001)))))

or sort of along the same lines

from operator import reduce
reduce(lambda x, y: x + y.count('0'), map(str, range(1001)), 0)

I agree with the comments above : you should use str(n) to cast the integer 0 into the character "O" that you are searching for.

One other way to do is to use the numeric value and not the character:

var = 0
for n in range(0, 1001):
   for digit in n:
       if digit == 0: #numerical value
           var += 1
print(var)

Your range(0,1001) should start a 1, otherwise you'll be counting an extra zero. Going through all numbers and converting to a string works but it is very inefficient. You can obtain the number of zero using a recursive function that will go exponentially faster:

# String based version
def strZeroCount(N):
    z = 0
    for n in range(1,N+1):
        z += str(n).count("0")
    return z

# numerical version (recursive)
def numZeroCount(N):
    if N < 10 : return 0
    R = N % 10 + 1
    Q = N // 10
    return  Q + numZeroCount(Q-1)*(10-R) + numZeroCount(Q)*R

Performance of the string version will be roughly O(n) while the recursive function will be closer to O(log n):

numZeroCount(1000)    0.006  ms  (120x faster)
strZeroCount(1000)    0.727  ms

numZeroCount(1000000) 0.031  ms  (12,000x faster)
strZeroCount(1000000) 374.3  ms

numZeroCount(1000000000)  0.180 ms (1,700,000x faster)
strZeroCount(1000000000) 310550 ms = 5.2 minutes

They way numZeroCount() works is by separating the problem in two parts:

  • Number of times the last digit will be zero.
  • Number of times the zero count of the leading digits will occur.

For example, if you take number 1037:

  • We first break it in two parts Q=103 and R=8 (7+1) where Q is the prefix and R is the number of digits up to and including the last digits.
  • The leading digits (Q) will go from 1 to 103 with an extra digit at the end. For each of these 103 prefixes, the last digit will be a zero only once. So we can count Q zeroes for the cases where the number ends with zero.
  • These leading digits form a new number that will through values (prefixes) totalling a certain number of zeroes. Given that each of these prefix value will be combined to the 10 suffix digits (0...9), we could recursively compute the number of zeroes up to that prefix number and multiply it by 10.
  • This would work fine if our number ended with a 9. But it happens to end with 7 so not all of the prefixes will use all the (0...9) suffixes.
  • The last prefix of the series (103) will only use suffixes 0 through 7.
  • This can be taken into account by computing the prefix counts up to 102 (1..N-1) combined with all 10 digits and only adding the zero count of the last prefix 103 (N) eight times (R).
  • Since we only have a function that will count zeroes from 1 to N, we will need to obtain that total differently. We know that the suffix digits up to 7 (R) will apply to all prefix values including 103 (N). The other digits, above 7 (10-R=2), will only apply to prefix values up to 102 (N-1). The sum of these two products gives the total we are looking for.
  • So the recursion counts the zeroes for 102 (N-1) and 103 (N) and multiplies them with their respective number of trailing digits 10-R and R, then adds all this to the Q count of the first part.

The recursive function can be further improved using a cache. This provides an acceleration because many of the recursions will compute the zero counts for the same prefixes:

from functools import lru_cache
@lru_cache(maxsize=100)
def numZeroCount(N):
    if N < 10 : return 0
    R = N % 10 + 1
    Q = N // 10
    return  Q + numZeroCount(Q-1)*(10-R) + numZeroCount(Q)*R

numZeroCount(1000)             0.002 ms   vs 0.006 ms
numZeroCount(1000000)          0.018 ms   vs 0.031 ms
numZeroCount(1000000000)       0.020 ms   vs 0.180 ms
numZeroCount(1000000000000)    0.021 ms   vs 1.113 ms
numZeroCount(1000000000000000) 0.024 ms   vs 8.099 ms

或使用外壳:

seq 0 1001 | grep '0' | tr -c -d '0' | wc -c

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM