I want to generate all possible outputs of a list of size N that acts as a 3 digit odometer. For example, if N = 4, I want the following output:
0000
1000
2000
3000
0100
1100
...
3332
3333.
Here is my code, any help is much appreciated!
odom = [0]*N ## initialize odometer
print odom
while odom[N-1] <= 3:
idx = 1
odom[0] += 1
if odom[0] > 3:
while odom[idx] > 3:
idx += 1
for i in range(idx):
odom[i] = 0
print odom
def foo(n, digits = 4):
if digits == 0:
return ''
msb, lsb = divmod(n, 4)
return str(lsb) + foo(msb, digits - 1)
result = []
number_of_digits = 4
maxn = sum(3 * pow(number_of_digits,n) for n in range(number_of_digits))
for n in range(maxn + 1):
result.append(foo(n, number_of_digits))
result = [foo(n, number_of_digits) for n in range(maxn + 1)]
foo_4 = functools.partial(foo, digits=4)
result = list(map(foo_4, range(maxn + 1)))
The easy way is to just use itertools.product:
import itertools
for odom in itertools.product('0123', repeat=4):
print ''.join(odom)
If you need to increment the first digit first, you can use ''.join(odom)[::-1] instead.
The order of your example doesn't seem to be correct given that it starts by incrementing the first digit by one but it ends by incrementing the last digit by one. Assuming you just want to increase the first digit by 1 in base 4 with 4 digits (change the print if you're using python 2)
import numpy as np
def odo(numdigits, maxdigit):
x = 1
while len(np.base_repr(x, base=maxdigit)) <= numdigits:
padding = numdigits - len(np.base_repr(x, base=maxdigit))
yield np.base_repr(x, base=maxdigit, padding=padding)[::-1]
x += 1
for x in odo(4, 4):
print(x)
Related
I'm trying to count the number of ways you can divide a given string into three parts in Python.
Example: "bbbbb" can be divided into three parts 6 ways:
b|b|bbb
b|bb|bb
b|bbb|b
bb|b|bb
bb|bb|b
bbb|b|b
My first line of thinking was N choose K, where N = the string's length and K = the number of ways to split (3), but that only works for 3 and 4.
My next idea was to iterate through the string and count the number of spots the first third could be segmented and the number of spots the second third could be segmented, then multiply the two counts, but I'm having trouble implementing that, and I'm not even too sure if it'd work.
How can I count the ways to split a string into N parts?
Think of it in terms of the places of the splits as the elements you're choosing:
b ^ b ^ b ^ ... ^ b
^ is where you can split, and there are N - 1 places where you can split (N is the length of the string), and, if you want to split the string into M parts, you need to choose M - 1 split places, so it's N - 1 choose M - 1.
For you example, N = 5, M = 3. (N - 1 choose M - 1) = (4 choose 2) = 6.
An implementation:
import scipy.special
s = 'bbbbb'
n = len(s)
m = 3
res = scipy.special.comb(n - 1, m - 1, exact=True)
print(res)
Output:
6
I came up with a solution to find the number of ways to split a string in python and I think it is quite easier to understand and has a better time complexity
def slitStr(s):
i = 1
j= 2
count = 0
while i <= len(s)-2:
# a, b, c are the split strings
a = s[:i]
b = s[i:j]
c = s[j:]
#increase j till it gets to the end of the list
#each time j gets to the end of the list increment i
#set j to i + 1
if j<len(s):
j+= 1
if j==len(s):
i += 1
j = i+1
# you can increment count after each iteration
count += 1
You can customize the solution to fit your need. I hope this helps.
Hope this helps you too :
string = "ABCDE"
div = "|"
out = []
for i in range(len(string)):
temp1 = ''
if 1 < i < len(string):
temp1 += string[0:i-1] + div
for j in range(len(string) + 1):
temp2 = ""
if j > i:
temp2 += string[i-1:j-1] + div + string[j-1:]
out.append(temp1 + temp2)
print(out)
Result :
['A|B|CDE', 'A|BC|DE', 'A|BCD|E', 'AB|C|DE', 'AB|CD|E', 'ABC|D|E']
I have a string
x = "yfbrtutcfyugytfytfytcfdycfyrcdtrdrcdtreextredydsadyradrydstrdfrdfrrdecrcxhx"
and I wanna split the string x into the following list.
y = [
"yfbrtutcfyugytfyt",
"cfdycfyrcdtrdrcdtreextredy",
"strdfrdfrrdecrcx"
]
How can I do this by providing the number 3 and have it split into a list of the length 3? The length of the text could be both odd and even.
You can use x[start_index:end_index] which yields a substring from x (last index excluded). So just specify 2 positions and use them e.g.:
a = len(x) // 3
b = 2* len(x) // 3
s0 = x[:a]
s1 = x[a:b]
s2 = x[b:]
You can make use of the split function in python
word = 'yfbrtutcfyugytfytfytcfdycfyrcdtrdrcdtreextredydsadyradrydstrdfrdfrrdecrcxhx'
x=round(len(word)/3)
print([word[i:i+x] for i in range(0, len(word),x)])
And it gives you:
['yfbrtutcfyugytfytfytcfdyc', 'fyrcdtrdrcdtreextredydsad', 'yradrydstrdfrdfrrdecrcxhx']
I hope you are creating random test cases by splitting into 3 parts of any length.
You can try using random:
import random as rnd
x = "yfbrtutcfyugytfytfytcfdycfyrcdtrdrcdtreextredydsadyradrydstrdfrdfrrdecrcxhx"
len_x = len(x)
idx1 = rnd.randint(0,len_x-1)
idx2 = rnd.randint(idx1,len_x)
l = [x[0:idx1], x[idx1:idx2], x[idx2:len_x]]
l:
['yfbrtutcfyugytfytfytcfdycfyrcdtrdrcdtreextredydsadyrad',
'rydstrdfrdfrr',
'decrcxhx']
This is my perspective of solution on your problem
x = "yfbrtutcfyugytfytfytcfdycfyrcdtrdrcdtreextredydsadyradrydstrdfrdfrrdecrcxhx"
length = len(x)
list_x = []
count = 0
for i in range(3):
count += 1
if count == 1:
X = x[:(length // 3)]
list_x.append(X)
elif count == 2:
X = x[(length // 3):((length // 3)*2)]
list_x.append(X)
else:
X = x[((length // 3)*2):length]
list_x.append(X)
print(list_x)
And you get those results:
['yfbrtutcfyugytfytfytcfdyc', 'fyrcdtrdrcdtreextredydsad', 'yradrydstrdfrdfrrdecrcxhx']
n=10
num=int(len(x) / n) + (len(x) % n > 0)
y=[x[i:i+num] for i in range(0, len(x),num)]
Output:
['yfbrtutc',
'fyugytfy',
'tfytcfdy',
'cfyrcdtr',
'drcdtree',
'xtredyds',
'adyradry',
'dstrdfrd',
'frrdecrc',
'xh']
I don't know of a python built-in function that does this.
The function below divides a long string into N chunks.
def split_string_N(string, N):
chunk_size = len(string) / N
return [string[int(n * chunk_size): int((n+1) * chunk_size)] for n in range(N)]
test_string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
chunks = split_string_N(test_string, 10)
print(chunks)
['abcde', 'fghij', 'klmno', 'pqrst', 'uvwxyz', 'ABCDE', 'FGHIJ', 'KLMNO', 'PQRST', 'UVWXYZ']
Notice that since this is not equally divisible by 10 that some chunks are length 5 (pqrst) and some length 6 (uvwxyz), and it occurs 'naturally' where the remainder rolls over to the next higher integer. Also, it will give bad output where N > len(string). You can add some logic to prevent that if you want :) Gl!
Given an array of even and odd numbers, I want to get the number of (even-even) and (odd-odd) pairs whose XOR is greater than or equal to 4. I tried this with the code below but it runs in O(n^2), (yikes). Please can anyone suggest a means of optimization?
n = int(raw_input()) #array size
ar = map(int, raw_input().split()) #the array
cnt = 0
for i in xrange(len(ar)):
for j in xrange(i+1, len(ar)):
if ar[i] ^ ar[j] >= 4 and (not ar[i] & 1 and not ar[j] & 1):
cnt += 1; #print ar[i],ar[j],ar[i]^ar[j];
elif ar[i] ^ ar[j] >= 4 and (ar[i] & 1 and ar[j] & 1):
cnt += 1
print cnt
EDIT: I discovered something. any number x, which gives a remainder after % 4, i.e x % 4 != 0, will result to 2 when XORed to a number -2 itself. For example, 6. It is not divisible by 4, therefore, 6 XOR 6-2 (4),==> 2. 10 is not divisible by 4, hence, 10 XOR 10-2 (8) ==> 2. Can you please tell me how this could help me optimize my code? I just know now that I will just look for numbers divisible by 4 and find the count of their + 2.
For simplicity, let´s assume the array does not have duplicates. For the XOR between 2 numbers to be >= 4, they need to have any different bit (excluding lower 2 bits). Given that we already know they are even-even or odd-odd pairs, their lowest bit is the same.
Note that for any number X, X XOR (X + 4 + k) will always be >= 4. So the problem is considering what happens with X XOR (X + 1), X XOR (X + 2) and X XOR (X + 3).
X XOR (X + 1) will be >= 4 when the third lowest bit has changed by adding only 1. That means, we had X ending in 011 so X + 1 ends in 100 or we had X ending in 111 so X + 1 ends in 000. In both cases, this means X % 4 = 3. In any other case (X % 4 != 3), X XOR (X + 1) will be < 4.
For X XOR (X + 2) to be >= 4, the third lowest bit has changed by adding 2. This means, X ended in 011, 010, 111, or 110. So we now have X % 4 = 3 or X % 4 = 2.
For X Xor (X + 3) to be >= 4, the third lowest bit has changed by adding 3. This means, X ended in 011, 010, 001, 111, 110, 101. So we now have X % 4 = 3, X % 4 = 2 or X % 4 = 1.
Here is pseudocode:
for each element in array:
count[element] += 1
total += 1
for each X in sorted keys of count:
if X % 4 == 3:
answer += count[X + 1] + count[X + 2] + count[X + 3]
if X % 4 == 2:
answer += count[X + 2] + count[X + 3]
if X % 4 == 1:
answer += count[X + 3]
total -= count[X]
answer += total - (count[X + 1] + count[X + 2] + count[X + 3]) # all X + 4 + K work
To account for duplicates, we need to avoid counting a number against itself. You will need to keep the count of each number, and do the same as the above with the modification that the answer will be the count of that number * (all the others - the amount of X + 2 numebers)
You should work on separating your code, one improvement is the use of set to avoid repeating operations, although it may get more memory overhead.
import random
from operator import xor
import itertools
random.seed(10)
in_values = [random.randint(0, 10) for _ in range(100)]
def get_pairs_by(condition, values):
odds = set(filter(lambda x: x % 2 == 0, values))
evens = set(filter(lambda x: x % 2 == 1, values))
def filter_pairs_by_condition(values):
return (
(x, y) for x, y in set(
map(lambda x: tuple(sorted(x)),
itertools.product(iter(values), iter(values))))
if condition(xor(x, y))
)
return list(
itertools.chain.from_iterable(
(filter_pairs_by_condition(x) for x in (odds, evens))
)
)
print(get_pairs_by(lambda x: x >= 4, in_values))
The keypoint is:
set(map(lambda x: tuple(sorted(x)),
itertools.product(iter(values), iter(values)))))
What we are doing is that pairs of (5, 7) and (7, 5) should be evaluated as being the same, so we take rid of them there.
Here you have the live example
EDIT:
As a quick update to your code, you can use a dictionary to memoize previously computed pairs, hence:
n = int(raw_input()) #array size
ar = map(int, raw_input().split()) #the array
cnt = 0
prev_computed = {}
for i in xrange(len(ar)):
for j in xrange(i+1, len(ar)):
if any(x in prev_compued for x in ((ar[i], ar[j]), (ar[j], ar[i]))):
cnt += 1
continue
if ar[i] ^ ar[j] >= 4 and (not ar[i] & 1 and not ar[j] & 1):
cnt += 1; #print ar[i],ar[j],ar[i]^ar[j];
prev_computed[(ar[i], ar[j])] = True
prev_computed[(ar[j], ar[i])] = True
elif ar[i] ^ ar[j] >= 4 and (ar[i] & 1 and ar[j] & 1):
cnt += 1
prev_computed[(ar[i], ar[j])] = True
prev_computed[(ar[j], ar[i])] = True
print cnt
def xor_sum(lst)
even_dict = a dictionary with keys being all even numbers of lst and values being their frequencies
odd_dict = a dictionary with keys being all odd numbers of lst and values being their frequencies
total_even_freq = sum of all frequencies of even numbers
total_odd_freq = sum of all frequencies of odd numbers
even_res = process(even_dict, total_even_freq)
odd_res = process(odd_dict, total_odd_freq)
return even_res + odd_res
def process(dict, total_freq)
res = 0
for num in dict.keys
# LSB of XOR of 2 even numbers is always 0
# Let p = XOR of 2 even numbers; if p < 4 then p = 00000000 (minus_2) or 00000010 (plus_2)
plus_2 = num+2
minus_2 = num-2
count = 0
if( (plus_2 XOR num) < 4 and (plus_2 is a key of dict) )
count = count + frequency_of_plus_2
if( (minus_2 XOR num) < 4 and (minus_2 is a key of dict) )
count = count + frequency_of_minus_2
count = count + num
res = res + (total_freq+1-count)
return res
Complexity:
Assuming you have a good hash function for your dictionaries (a hashmap), the average time complexity is O(n)
I want to create a function so that it will find the integer a so that a <= n.
If n is 99, then the program will return a = 3.
This is because the function is finding the sums of the consecutive cubes.
So, 1 + 8 + 27 + 64 = 100, which is more than 99. But 1 + 8 + 27 is less than 99, so a = 3 is the correct answer.
I was trying to do something like:
cubes = 0
for i in xrange(1, 1+x)
cubes += i*i*i
while cubes <= n
but I am very confused. How should I proceed?
First replace the for loop with a while loop:
cubes, i = 0, 0
while cubes <= n:
i += 1
cubes += i ** 3
Then, after the loop, subtract the last cube because you'll have gone over the limit n:
cubes -= i ** 3
i still has the final value it had in the loop.
Alternatively, you can do everything in one loop, by first computing the new value of cubes as a temporary variable, then only updating cubes if you've not gone over the limit:
cubes, i = 0, 0
while True: # infinite loop
i += 1
new_cubes = cubes + i ** 3
if new_cubes > n:
break
else:
cubes = new_cubes
Using itertools.count and a for-loop:
from itertools import count
def solve(n, pow):
total = 0
for i in count(1):
if total + i**pow > n:
return i-1
total += i**pow
Demo:
>>> solve(99, 3)
3
>>> solve(50, 2)
4
Here's how I'd do it.
def cubes(n=1):
while True:
yield n ** 3
n += 1
def sum(array):
total = 0
for item in array:
total += item
yield total
def sum_cubes_lt(n):
for i, sum in enumerate(sum(cubes()):
if sum > n:
return i
# prints '3'
print sum_cubes_lt(99)
Can somebody tell me why this should be wrong?
#Each new term in the Fibonacci sequence is generated
#by adding the previous two terms. By starting with 1 and 2,
#the first 10 terms will be:
#1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
#Find the sum of all the even-valued terms in the sequence
#which do not exceed four million.
sum=2
list = [1,2]
for x in range(2,100):
a = list[x-2]+list[x-1]
print(a)
list.append(a)
if a % 2 == 0:
sum += a
print('sum', sum)
if sum >= 4000000:
break
Here's a completely different way to solve the problem using a generator and itertools:
def fib():
a = b = 1
while 1:
yield a
a, b = b, a + b
import itertools
print sum(n for n in itertools.takewhile(
lambda x: x <= 4000000, fib()) if n % 2 == 0)
Output:
4613732
So your code, even though it is wrong (see other answers), happens to give the correct answer.
replace
sum += a
print('sum', sum)
if sum >= 4000000:
break
with
if a > 4000000:
break
sum += a
print('sum', sum)
You should compare "a" with 4000000, not "sum", like Daniel Roseman said.
The question asked for the sum of even terms which do not exceed four million. You're checking if the sum doesn't exceed 4m.
I'm trying to solve the same problem - although I understand the logic to do it, I don't understand why this works (outputs the right sum)
limit = 4000000
s = 0
l = [1,2]
while l[-1]<limit:
n = l[-1]+l[-2]
l.append(n)
print n
And then then moment I put in the modulo function, it doesn't output anything at all anymore.
limit = 4000000
s = 0
l = [1,2]
while l[-1]<limit:
n = l[-1]+l[-2]
if n % 2 == 0 :
l.append(n)
print n
I'm sure this is fairly simple...thanks!
This is the code I used. It is very helpful and teaches you about generators.
def fib():
x,y = 0,1
while True:
yield x
x,y = y, x+y
def even(seq):
for number in seq:
if not number % 2:
yield number
def under_a_million(seq):
for number in seq:
if number > 4000000:
break
yield number
print sum(even(under_a_million(fib())))
-M1K3
Keep it simple and it should take you less than 0.1 seconds.
from datetime import datetime
x, y = 1, 1
total = 0
for i in xrange (1, 100):
x = x + y
if x % 2 == 0 and x <= 4000000:
total += x
y = y + x
if y % 2 == 0 and x <= 4000000:
total += y
print total
starttime = datetime.now()
print datetime.now() - starttime