Calculate circular shift pairs in a list - python

A circular shift moves some of the digits in a number to the beginning of the number, and shifts all other digits forward to the next position. For example, all of the circular shifts of 564 are 564, 645, 456.
Lets say two numbers of equal length a and b are circular pairs if a can become b via circular shifting. Using the example above, the circular pairs of 564 are 645 and 456.
Given an array of positive integers nums, count the number of circular pairs i and j where 0 <= i < j < len(nums)
For example, circular_shifts([13, 5604, 31, 2, 13, 4560, 546, 654, 456]) should return 5. With the pairs being (13, 31), (13, 13), (5604, 4560), (31, 13), (546, 654).
I wrote a brute force solution that saves all circular shifts of a number in a dictionary shifts and for every number num in nums, I check all the following numbers and if a number num2 the same digits as num, I see if num2 is in num's circular shifts. If it is then I added this to the total count.
Unfortunately this algorithm runs too slowly and times out, I'm looking for a faster way to solve this problem can anyone think of optimizations, clever tricks, or other strategies to speed this up?

Not very elegant as not much time but the following should be faster as does not repeatedly access the list. Shifting is done on string for simplicity.
from collections import Counter
def big(num):
max = num
s = str(num)
for _ in s:
x = int(s[-1] + s[0:-1])
if x > max:
max = x
return max
circs = [big(z) for z in mylist]
c = Counter(circs)
total = 0
for i in c:
if c[i] > 1:
total += c[i]
print(total)

Replace every number in the array with its greatest cyclic shift. 1234, for example, would become 4123
Count the occurrences of each resulting number
If a number occurs n times, that represents n(n-1)/2 cyclic shift pairs. Add them all up.

Here's my solution, where we
iterate through the list
rotate each number length-1 times
and print only if the number is found in the remaining list
numbers = [13, 5604, 31, 2, 13, 4560, 546, 654, 456]
# shift_pairs = [(13,31),(13,13),(5604,4560),(31,13),(546,654)]
pairsFound = 0
for i in range(len(numbers)):
number = numbers[i]
length = len(str(number))
numberToRotate = number
shift_remaining = length - 1
temp_list = numbers[i+1:]
while(shift_remaining >= 0):
t_remainder = numberToRotate % 10 # 4
numberToRotate = numberToRotate // 10 # 560
numberToRotate = numberToRotate + t_remainder * 10 **(length-1) # 4560
# we should also check for length for cases like 4560, where on a shift we get 456
if(numberToRotate in temp_list and len(str(numberToRotate)) == length):
print("({},{})".format(number,numberToRotate))
pairsFound += 1
shift_remaining -= 1
print("no of pairs:", pairsFound)
output
(13,31)
(13,13)
(5604,4560)
(31,13)
(546,654)
no of pairs: 5

Related

Getting an incorrect output which is off by 1 - Min number of moves required to make all elements equal

This is from the leetcode question 453 which says :
Given an integer array nums of size n, return the minimum number of moves required to make all array elements equal.
In one move, you can increment n - 1 elements of the array by 1.
I have created a solution that works fine on most of the test cases but fails on one of the test cases. I have given that test case below. I am not sure, where am I going wrong.
class Solution(object):
def minMoves(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
max_number = max(nums)
min_number = min(nums)
total_count = max_number - min_number
_nums = nums[:]
while max_number - min_number != 1 and (max_number - min_number != 0):
diff = max_number - min_number
max_list = []
for i, n in enumerate(_nums):
if n != max_number:
_nums[i] += diff
else:
max_list.append(i)
if len(max_list) > 1:
# if there are duplicate max_numbers
for i in max_list[1:]:
_nums[i] += diff
max_number = max(_nums)
min_number = min(_nums)
if max_number - min_number == 1:
total_count += 1
else:
total_count += (max_number - min_number)
return total_count
The test case:
[83,-14,77,15,93,35,86,-8,-51,-79,62,-73,-10,-41,63,26,40,-74,72,36,-89,68,67,-71,82,30,-38,23,-33,35,29,-98,-78,-42,-31,67,93,-44,-89,-58,-71,73,-79,19,84,37,98,24,15,70,-87,26,-9,80,56,-27,-38,70,96,-19,5,25,-16,27,36,5,-54,29,13,-43,24,-5,82,45,-86,67,-66,64,-57,50,-13,-92,-24,78,88,84,-97,-49,54,99,32,-40,-24,68,39,-88,-74,86,-6,39,95,70,-66,78,-33,-99,-3,2,17,-8,-48,56,1,-20,-14,-59,-35,-11,-56,-81,-60,29,-69,17,-3,71,-19,-25,9,27,67,-44,-3,53,86,65,6,-17,-81,-76,28,-29,32,-71,3,-81,-30,68,8,15,40,49,96,23,-82,-55,-54,-49,21,55,79,-12,64,-72,-59,50,93,0,-66,64,24,14,87,-44,43,-9,-73,65,-41,36,-68,51,-63,-72,-25,-93,-26,21,-42,95,-71,-63,-65,93,-82,-72,43,-89,28,29,76,-96,-57,63,-87,38,-94,-60,4,-82,28,-12,69,17,17,96,24,43,-30,83,-10,-1,72,25,-56,90,5,39,54,86,-31,-18,42,-36,97,7,55,-96,48,-89,-78,-72,-1,43,46,68,40,-78,11,-90,-95,-99,-39,30,-22,5,20,36,-56,-74,22,-35,8,-84,-18,-42,24,-63,-38,-76,-100,-64,-48,-1,79,50,-32,-29,73,31,-19,30,33,-6,-40,63,99,81,-1,96,59,73,-87,-32,90,-5,26,-34,-16,40,-10,-16,76,42,36,7,-55,56,79,-82,-13,-88,48,72,-41,-91,36,-90,42,87,-94,1,13,72,21,-45,-81,99,21,4,39,-89,40,-33,5,-72,27,50,84,-42,20,-76,-78,-31,96,-19,-70,-16,-8,72,-28,-50,-75,85,-78,-1,-60,-58,-2,13,-2,90,24,90,-91,81,-81,36,32,55,94,-96,79,69,-27,76,-50,-45,-40,42,79,-16,93,-95,-79,67,4,-87,61,54,26,-41,44,-98,-98,6,84,-79,-58,-32,28,89,-28,8,58,-2,-64,-92,53,-52,3,33,33,-52,-10,54,67,46,68,29,0,-54,88,97,-51,90,3,-67,63,-3,-47,-8,-14,25,52,96,75,88,57,29,-64,-40,-86,21,-40,4,-72,-73,-50,48,56,2,94,-3,-1,-57,-61,-98,-72,-97,0,-19,-53,38,59,51,35,34,39,-8,-85,27,4,-71,-51,64,-15,-71,43,35,77,0,-62,71,49,-11,67,88,-8,95,43,44,-71,90,-18,40,41,69,-74,-68,-39,-58,60,17,-77,61,-19,9,90,-75,96,67,-23,-66,-10,-74,24,-43,-86,68,-95,58,12,86,0,46,26,94,16,52,78,29,46,-10,-53,70,-49,-20,-69,93,-43,-73,12,-14,-86,55,12,-10,-88,-21,-90,69,89,-26,55,-59,-80,-67,87,-12,38,66,70,-16,-44,-83,-94,-40,-51,-63,-95,-41,-83,18,45,83,-27,-42,-27,-63,-11,-17,-93,-22,57,14,-29,29,0,-41,-82,-62,-75,88,-26,-67,57,-19,-7,58,-30,-1,-83,-61,69,63,-78,94,73,-53,-69,-38,-18,90,-8,91,-43,15,21,57,74,-9,47,51,-69,-79,37,40,-46,-70,-2,25,-19,16,16,-98,-69,39,96,-96,38,80,-82,-79,70,-38,-88,79,77,-15,36,4,76,-17,-93,59,-43,44,-1,11,27,50,-64,60,-82,5,63,-51,-56,11,-95,34,-9,75,55,-86,89,68,93,18,-95,-18,-78,82,17,-70,-7,74,26,93,-14,-47,43,-26,-86,13,79,77,62,75,-12,19,10,32,-6,-83,46,-65,37,-9,53,43,73,28,25,-9,10,-82,-83,-64,63,-45,-10,-42,30,4,71,-39,-67,-15,89,-27,-96,-49,-95,-50,-32,3,-15,-94,95,-61,49,20,67,-74,63,-23,96,81,-35,60,-64,55,70,18,-89,42,32,96,79,21,-30,84,72,-73,-66,-60,-17,-28,98,-70,-37,47,50,-70,73,14,-41,22,-53,24,-18,-65,-68,-96,54,-57,-2,-14,-60,-22,59,-38,-38,-17,-59,-52,23,24,-28,22,54,35,-79,-43,65,47,71,76,-31,-82,1,3,-47,33,7,59,28,-94,97,20,-16,8,34,-2,91,76,-2,15,-48,71,89,59,6,-90,-84,-76,9,39,-100,78,9,-47,-19,14,38,89,-74,-33,47,-77,87,-69,32,22,-19,-25,-50,79,90,-46,50,31,-87,-43,-6,81,-19,-97,20,-67,82,81,-13,-85,-4,-75,-96,22,-8,51,-3,-68,34,81,6,-85,-43,8,95,99,62,-3,-17,76,54,77,9,87,32,82,-79,-34,63,-40,-18,-89,-15,-14,-15,30,90,83,14,-24,16,-80,-8,25,28,-61,25,-10,36,60,-82,-57,37,28,82,-79,10,55,-12,-75,-85,70,-63,-47,-92,22,83,50,-43,-3,-73,26,-31,-29,-49,49,10,28,-61,98,-12,-90,93,77,-10,76,99,52,31,-13,77,-1,-43,66,52,-83,-59,35,68,-2,84,95,76,-95,-34,-72,54,28,8,93,-22,97,55,-28,74,-55,-100,25,97,-17,-88,27,82,-79]
The method that I am using is simple. For example, for an array like:
[1,2,3,100]
Minimum number of moves can be maximizing the smallest number towards greatest. So,
[100, 101, 102, 100] (100 - 1 = 99 and everybody except 1 gets incremented by that). This makes 99 moves
[102, 103, 102, 102] (102 - 100 = 2 and everybody gets except 1 incremented by that. This makes 2 moves with total moves now being 99 + 2 = 101
[103, 103, 103, 103] Just one move is required here. (101 + 1 = 102)
It looks like your algorithm doesn't handle duplicate maximums correctly. It fails for [0,1,1], for example, which requires 2 moves to make all the elements the same.
This problem doesn't require such a complicated algorithm. In terms of making all elements equal, incrementing n-1 elements is the same as decrementing one element. To make all elements the same, all elements must be relatively decremented to the minimum value.
The answer is just sum(nums) - min(nums)*len(nums).

Python sum pairs from text file

I am given a sorted array of positive integers and a number X and I need to print out all pairs of numbers whose sum is equal to X. Print out only unique pairs and the pairs should be in ascending order.
However the program needs to read lines of text from standard input where each line contains a comma separated list of sorted numbers, followed by a semicolon, followed by the integer X.
e.g. test input:1,2,3,4,6;5
output: 1,4;2,3
I have tried
list1 = []
for line in sys.stdin:
for n in line:
list1.append(n)
strlist = [ x for x in list1 if x.isdigit() ]
numlist = list(map(int, strlist))
sum = numlist[-1]
res = []
while numlist:
num = numlist.pop()
diff = sum - num
if diff in numlist:
res.append((diff, num))
res.reverse()
print(res, end="")
But i get
Test Input: 1,2,3,4,6;5
Expected Output: 1,4;2,3
My Output: [(2, 3), (1, 4)]
This might not be the most efficient, but I came up with this that worked.
Replace the test_case with sys.stdin and remove the test_case should work.
Sorry if this looks bad, it's my first time posting on stackoverflow.
test_case = ["1,2,3,4,6;5"]
for line in test_case:
line = line.split(";")
numbers = line[0].split(",")
pairs = []
for number in numbers:
difference = int(line[1]) - int(number)
difference = str(difference)
if difference in numbers and difference != number:
pair = ",".join((number, difference))
pairs.append(pair)
del pairs[len(pairs)//2:len(pairs)]
print(";".join(pairs))
Output : 1,4;2,3
Solution 1:
Time complexity of O(n^2). This is based on the original solution. The corrections made were:
The iteration of the string and parsing per character wouldn't work for 2-digit numbers (or more) e.g. 12 thus it is incorrect. Also it is not efficient. Instead of manually iterating each character, checking .isdigit(), and then redoing it again for the next number for the whole list, just split the string by the characters ; and , and then transform them to int.
In your original logic, the target sum would be the last element in the list numlist. But you are considering that number for the sum (since it will be the first number to be popped out). You should pop it first before entering the while loop.
The order of the pairs would start from the highest number (pop until list is empty). So, the pair for the highest number would be the smallest number e.g. 1 is to 4, then 2 is to 3, thus no need to call .reverse() as it will do the opposite.
for input_text in [
"1,2,3,4,6;5",
"5,10,15,20,25,30,35,40,45;50",
"0,2,4,6,8,10,12,14;12",
]:
num_str, sum_str = input_text.split(';')
num_list = list(map(int, num_str.split(',')))
target_sum = int(sum_str)
res = []
while num_list:
num = num_list.pop()
diff = target_sum - num
if diff in num_list:
res.append((diff, num))
res_formatted = ";".join(map(lambda pair: f"{pair[0]},{pair[1]}", res))
print(f"{input_text}\n\t{res}\n\t{res_formatted}")
Solution 2:
Time complexity of O(n). Since we already have sorted data, instead of iterating the whole list finding the other number that will arrive to the target sum for each number, just use 2 pointers, one at the start/left lhs and one at the end/right rhs.
If the sum is lower than the target, then it means that we need to move forward/right the lhs. Why? Because if we already added it to the maximum number which is rhs, then there is no point of trying it with the other numbers. What we need is to increase lhs and see the next result.
If the sum is higher than the target, then it means we need to move back/left the rhs. Why? Same point as above, If the sum was already higher, then we can't use the number in rhs as it is too high even if added with the smallest number lhs, thus move it to the next smaller number.
If the sum is equal to the target sum, then we include in the result the numbers pointed to by lhs and rhs. Then we move both pointers respectively.
def sum_pairs(numbers, target_sum):
lhs = 0
rhs = len(numbers) - 1
pairs = []
while lhs < rhs:
current_sum = numbers[lhs] + numbers[rhs]
if current_sum == target_sum:
pairs.append((numbers[lhs], numbers[rhs]))
lhs += 1
rhs -= 1
elif current_sum > target_sum:
rhs -= 1
else:
lhs += 1
return pairs
for input_text in [
"1,2,3,4,6;5",
"5,10,15,20,25,30,35,40,45;50",
"0,2,4,6,8,10,12,14;12",
]:
num_str, sum_str = input_text.split(';')
num_list = list(map(int, num_str.split(',')))
target_sum = int(sum_str)
res = sum_pairs(num_list, target_sum)
res_formatted = ";".join(map(lambda pair: f"{pair[0]},{pair[1]}", res))
print(f"{input_text}\n\t{res}\n\t{res_formatted}")
Output
1,2,3,4,6;5
[(1, 4), (2, 3)]
1,4;2,3
5,10,15,20,25,30,35,40,45;50
[(5, 45), (10, 40), (15, 35), (20, 30)]
5,45;10,40;15,35;20,30
0,2,4,6,8,10,12,14;12
[(0, 12), (2, 10), (4, 8)]
0,12;2,10;4,8

Complete n-Digit Factor

I Was trying a problem but my time complexity is very high. Is there any way to reduce my time complexity. The Question Below with my code.
A number is said to be a complete ‘n’ digit factor, if it is a factor
of all ‘n’ digit numbers when concatenated (joined to right) to
itself.
For example, 7 is a complete 3-digit factor as it divides all three
digit numbers from 100 to 999 when concatenated to itself (i.e.
100100, 101101,102102, ... ..., 998998, 999999).
Given the value of n and m(Max Value to be checked), write a code to
generate all numbers from 2 to m (both inclusive) that are complete
n-digit factor and print ‘No complete factors’ otherwise. For example,
if n is 3 and m is 15 then print 7, 11, 13
N = int(input()) #No Of Digits
M = int(input()) #Max Value to be Checked
#Im Assuming Max Value will be less than or equal to 9
Nu = '100000000'
NuN = '9'*N
NuM_1 = int(Nu[:N])
NuM_2 = int(NuN)
Lis = [int(str(i)*2) for i in range(NuM_1,NuM_2+1)]
Count = 0
Res = []
for i in range(2,M+1):
Count = 0
for j in Lis:
if(j%i==0):
Count += 1
if(Count==len(Lis)):
Res.append(i)
if(len(Res)!=0):
for i in Res:
print(i)
You're attacking the problem from the functional definition, rather than analyzing the numerical properties of that definition.
Concatenating an n-digit number to itself is the same as multiplying by 10^n + 1. For instance, doing this with 3-digit numbers is equivalent to multiplying each by 10^3 + 1, or 1001.
A number divides all such integers iff that number divides the multiplier. Therefore, you can drop this massive iteration and check; simply factor 10^n + 1.
For instance, 1001 factors into 7 * 11 * 13; from there, you can generate the seven needed integers in the answer: 7, 11, 13, 77, 91, 143, 1001.
There are many available factoring programs; a simple search will find you that code.
Try this variation, using a break, and a faster creation of Lis :
N = int(input("Enter N: ")) #No Of Digits
M = int(input("Enter M: ")) #Max Value to be Checked
#Im Assuming Max Value will be less than or equal to 9
Nu = '100000000'
NuN = '9'*N
NuM_1 = int(Nu[:N])
NuM_2 = int(NuN)
Lis = [i + (i * (10**N)) for i in range(NuM_1, NuM_2+1)]
Res = []
for i in range(2,M+1):
for j in Lis:
if j%i:
break
else:
Res.append(i)
print(Res)

How do I efficiently find out how many numbers are not divisible from a list of primes?

I'm new to python and in order to learn I'm trying to solve a problem as an exercise.
N is a integer between [1, 10^9]
K is a list of length <= 40 of random distinct prime numbers that are all equal or less to N.
My code has to find the quantity of number that are <= N that are not divisible by any number of the list K.
I've written the following code:
first_line = input().split()
second_line = input().split()
n = int(first_line[0])
list_of_primes = second_line
all_multiples_set = set()
for i in range(len(list_of_primes)):
prime = int(list_of_primes[i])
# Creates a set of all multiples numbers of this prime that are equal or less than N.
one_multiple_set = set(range(prime ,n if n % prime != 0 else n + prime ,prime ))
# Makes a Union of this set with the previous sets of multiples, thus getting all multiples of a and b.
all_multiples_set = all_multiples_set.union(one_multiple_set)
print(n - len(all_multiples_set))
The first input consist of 2 numbers: N and length of K respectively. (ie. "10 3").
The second input is a series of length of K primes that are less or equal to N. (ie. "2 3 7").
The output should be a integer that represents the quantity of number equal or less than N that are not dividable by any number in list K. (ie. "2" in this case)
I know my code works for some cases, but unfortunately the platform where I found this puzzle does not tell me for which cases my code does not work, it only tells me that it does not work for some cases.
I believe it is a question of memory. Given that 10^9 is a very large number, but it could also be an error that I'm not seeing.
I would appreciate some guidance in how to improve my code or a suggestion of a better approach. It is worth noticing that since this is an exercise, I can not import modules and also since I'm trying to learn, I would appreciate an explanation of why my code is ineficiente.
EDIT:
Execution time is also a factor. The code has 1 second max run time.
On my first try I wrote this code:
linha1 = input().split()
linha2 = input().split()
n = int(linha1[0])
s = linha2
x = len(s)
value_to_add = 0
value_to_subtract = 0
for i in range(1 << x):
single_set = []
multiply = 1
for j in range(x):
if i & (1 << j):
single_set.append(int(s[j]))
for num in single_set:
multiply *= num
if multiply > n:
break
if len(single_set) == 1:
value_to_add += n//single_set[0]
elif len(single_set) > 1:
value_to_subtract += n//multiply
print(n - value_to_add + value_to_subtract)
It also gets the right answer, but it takes to long to run.
Since the list contains distinct prime numbers, this problem can be reduced to finding how many numbers less than or equal to N are divisible by these primes then deduct that number from N.
Since N can be large (10^9) and K is not, you can use inclusion-exclusion principle to find that.
N/x = quantity of numbers less than or equal to N and are divisible by x
N/(x*y) = quantity of numbers less than or equal to N and are divisible by both x and y at the same time.
using inclusion exclusion principle and your sample data:
According to inclusion-exclusion, you add the number to the result when the
list_of_primes = [2, 3, 7]
n = 10
We add these:
10 / 2 = 5
10 / 3 = 3
10 / 7 = 1
-----------
9
Subtract these:
10 / (2 * 3) = 1
10 / (2 * 7) = 0
10 / (3 * 7) = 0
----------------
1
And add this:
10 / (2 * 3 * 7) = 0
--------------------
0
result = 9 - 1 + 0 = 8
n - result = 10 - 8 = 2 <-- this is the answer
You can implement that using a recursive approach as the following:
list_of_primes = [2, 3, 7]
n = 10
k = 3
def get_count(i, num, taken):
if num > n:
return 0
if i == k:
# the case 0 numbers taken
if taken == 0:
return 0
# if odd number of numbers are taken
if taken % 2:
return n // num
# if even number of numbers are taken
return -1 * (n // num)
return get_count(i+1, num * list_of_primes[i], taken+1) + get_count(i+1, num, taken)
print(n - get_count(0, 1, 0))
# 2
From wikipedia:
Generalizing the results of these examples gives the principle of
inclusion–exclusion. To find the cardinality of the union of n sets:
Include the cardinalities of the sets.
Exclude the cardinalities of the pairwise intersections.
Include the cardinalities of the triple-wise intersections.
Exclude the cardinalities of the quadruple-wise intersections.
Include the cardinalities of the quintuple-wise intersections.
Continue, until the cardinality of the n-tuple-wise intersection is included (if n is odd) or excluded (n even).
[Edited]
Be sure to convert to int before sorting:
list_of_primes = list(map(int, input().split()))
I also found a way to optimize the code roughly 2x faster. Note that if in some branch num is multiplied by min prime number from list is larger then N, than there is no need to continue and branch more, since we wouldn't change num as it is already big enough. Therefore, the following code:
list_of_primes = [11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193]
n = 10 ** 9
list_of_primes.sort(reverse=True)
k = len(list_of_primes)
min_prime = list_of_primes[-1]
def get_count(i, num, taken):
if num > n:
return 0
# if min_prime * num > n then we won't take any new numbers
# thus taken won't change
if min_prime * num > n or i == k:
# the case 0 numbers taken
if taken == 0:
return 0
# if odd number of numbers are taken
if taken % 2:
return n // num
# if even number of numbers are taken
return - 1 * (n // num)
return get_count(i+1, num * list_of_primes[i], taken+1) + get_count(i+1, num, taken)
print(n - get_count(0, 1, 0))
is almost two times faster on the given test than the previous solution: 0.25s vs 0.63s.
Old solution:
I found a way to decrease the depth of the recursion. You should iterate through descending sorted array of prime numbers to faster finish branching, i.e.:
list_of_primes.sort(reversed=True)
Thus in the worst case I improved the time from 5 seconds to 1.2 seconds.
list_of_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173]
n = 10 ** 9
list_of_primes.sort(reverse=True)
k = len(list_of_primes)
def get_count(i, num, taken):
if num > n:
return 0
if i == k:
# the case 0 numbers taken
if taken == 0:
return 0
# if odd number of numbers are taken
if taken % 2:
return n // num
# if even number of numbers are taken
return -1 * (n // num)
return get_count(i+1, num * list_of_primes[i], taken+1) + get_count(i+1, num, taken)
print(n - get_count(0, 1, 0))
It's very easy for your all_multiples_set to grow to a number very close to 10^9, which is going to consume on the order of 40GB of memory -- more than is reasonable on most machines! So you'll need a strategy that doesn't require you to keep track of so many numbers.
Start by getting N and K:
n, _ = map(int, input().split())
k = list(map(int, input().split()))
From there, one possible strategy would be to keep track of only the numbers that might actually match, and prune that number down as you go:
candidates = [c for c in range(1, n + 1) if c % k[0]]
for j in k[1:]:
candidates = [c for c in candidates if c % j]
print(len(candidates))
This has the advantage of getting faster and smaller when you're going through a large K list, but it still has the space problem because you start off with a lot of candidates (e.g. if N is 10^9 and your first value of K is 2, you have 5 billion ints to keep track of, which is better than 10 billion but still too many).
The way to do this without taking up any space at all is to iterate through all the candidates from 1 to N, completely evaluate each one against each element of K, and add 1 to the count if it meets the criteria. That way the only thing you need to keep track of is the count, and not what all the actual numbers are.
print(sum(
1 if all(c % j for j in k) else 0
for c in range(1, n+1)
))

loop finding "bouncy" numbers

Consider the following definitions of positive numbers:
A number is nondecreasing if its digits never get smaller as you go from left to right. For example, 12345
and 3388 are nondecreasing.
A number is nonincreasing if its digits never larger as you go from left to right. For example, 987542 and
881 are nonincreasing.
A number is bouncy if it is neither nondecreasing nor nonincreasing. For example, 12134 and 98462 are
bouncy.
Write a Python function bouncy that consumes a positive natural number (called n) and produces the
percentage of numbers between 1 and n, inclusive, which are bouncy. The result should be produced as a
natural number between 0 and 100, inclusive. Use round to convert the floating point percentage to an
integer.
def bouncy(input):
list1 = [0 for i in range(input)]
list1[0] = 0
for x in range(1, input-1):
if x < 100:
list1[x] = list1[x - 1]
else:
n=x
a = [0 for i in range(x)]
i = 0
while n > 0:
a[i]=n % 10
n/= 10
i+=1
flag = 1
for k in range(1, len(a) - 2):
if not ((a[k - 1] < a[k] < a[k + 1]) or (a[k - 1] > a[k] > a[k + 1])):
flag = 0
break
if flag == 0:
list1[x]==list[x-1]+ 1
return list1[input-1]
when i ran my code, it displays builtins.IndexError: list assignment index out of range.
Anyone got an idea?
You don't have to do any of that. Just turn the number into a string. If it's sorted it's nondecreasing, if it's reverse sorted it's nonincreasing, otherwise it's bouncy.
def bouncy(n):
return round(sum(list(i) not in (sorted(i), sorted(i, reverse=True)) for i in map(str, range(1, n+1)))/n*100)
This map()s each number in the range to a string, then checks whether a list() of that string is not found in a sorted() version of that string (either increasing or decreasing). Then it adds together how many numbers match that, divides by n, multiplies by 100, round()s that, and returns it.

Categories

Resources