My Code is below. I want to count the letters in the output
s = string and n is number of times to repeat. n = 10, means the string s = "aba" is repeated over the course of 10 letters. i.e abaabaabaa.
s, n = input().strip(), int(input().strip())
print(s.count("a")
Out = 7
my code is below
a = 'aba'
t = list(a)
n = 3
new_list = []
if n <= len(t):
for i in range(n):
new_list.append(t[i])
m = t + new_list
print (''.join(m))
elif n > len(t):
x,y = divmod(n,len(t))
if y == 0:
new_list.append(a * x)
else:
new_list.append((a * x) + ''.join(map(str,t[:y])))
if n is large then need to loop like len(list(s)) = 3, if n = 10, divide 10/3 and we got 3 equal part and we got 1 remainder
In case the ultimate intention is to iterate over the generated string rather than directly printing it as output, an alternative is to use the itertools library.
from itertools import cycle, islice
s = "aba"
n = 10
for c in islice(cycle(s), n):
... do other stuff ...
Another scenario is that you try to compare the generated string with another string s2 of length n. In that case, islice can be omitted.
for c, c2 in zip(cycle(s), s2): # zip() truncates cycle(s) to the same length as s2
... operate on c and c2 ...
You could use something like this:
def repeat_n(s, n):
return (s * (n // len(s) + 1))[:n]
s = 'aba'
print(repeat_n(s, 2))
# ab
print(repeat_n(s, 10))
# abaabaabaa
print(repeat_n(s, 12))
# abaabaabaaba
n // len(s) gives you the number of times we can repeat s and stay below n characters so n // len(s) + 1 is the number of time we can repeat s to get at least n characters (plus potentially some others).
With that number we just repeat the string with s * (n // len(s) + 1) and then take the first n characters (s * (n // len(s) + 1))[:n].
Hope this helps.
EDIT: fixed for python 3
What are you looking for is modulo (%) operator:
s = 'aba'
n = 10
out = ''
for i in range(n):
out += s[i % len(s)]
print(out)
Prints:
abaabaabaa
Here's another option, using the * operator for strings:
s = 'aba'
n = 10
out = (s * (n // len(s)))[:n]
print(out)
Breaking it down:
n // len(s) => This is just the number of whole times s will need to be repeated
+ 1 => We add one to this, so our string will be a little longer than needed
s * => This repeats s that number of times
[:n] => Takes the first n characters of the string
So while it isn't as readable, it's very fast. Compared to the accepted answer:
def original_calc():
out = ''
for i in range(n):
out += s[i % len(s)]
result = out
def new_calc():
result = (s * (n // len(s)))[:n]
import timeit
s = 'aba'
n = 10
>>> timeit.timeit(original_calc, number=100000)
0.20508930005598813
>>> timeit.timeit(new_calc, number=100000)
0.027835099957883358
Related
Please advise how I can reorder digits of a number and add a digit 5 to the result so that its absolute value will be the highest.
For example, if the input is 578 the expected result is 8755. Otherwise, if the input is negative -483, the output is expected to be -8543.
I've managed to make it work on positive numbers only, however, I need to make it work for negative numbers as well:
def solution(N):
a = [] # list of digits, e.g. int(123)
while N != 0:
v = N % 10 # last digit as div remainder, e.g.: 123 % 10 = 3
N = int(N / 10) # remove last digit using integer division: 123 / 10 = 12.3; int(12.3) = 12
a = [v] + a # concatenate two lists: newly created list with one element (v = 3) and list a
# as a result the digits will be in natural order => [1,2,3]
if len(a) == 0: # need to create list with one element [0] as the cycle before ignores 0
a = [0]
inserted = False
for i in range(0, len(a)): # i = 0, 1, 2; len = 3
if a[i] < 5:
# a[from:to exclusive] e.g.: [1, 2, 3][0:2] => [1, 2]. index of 1 is 0, index of 2 is 1, index 2 is excluded
a = a[0:i] + [5] + a[i:]
inserted = True
break
if not inserted:
a = a + [5]
N = 0 # reconstruct number from digits, list of digits to int
for i in range(0, len(a)):
N = N * 10 + a[i] # 0 + 1; 1 * 10 + 2; 12 * 10 + 3 = 123
return N
if __name__ == ‘__main__’:
print(“Solution:”, solution(0))
here i made some major changes by using some inbuilt python methods :
def solution(N):
sign = False #to determine the sign of N (positive or negative )
if N < 0:
sign = True
N= N * -1 # as N<0 we make it positive
a = []
while N != 0:
v = N % 10
N = int(N / 10)
a = [v] + a
a.append(5) # in built method to add an element at the end of the list
a.sort() # in built method to sort the list (ascending order)
a.reverse() # in build method to reverse the order of list (make it descending order)
N = 0
for i in range(0, len(a)):
N = N * 10 + a[i]
if sign: # convert negative integers back to negative
N = N * -1
return N
Sample output :
for negative
solution(-2859)
-98552
positive
solution(9672)
97652
If you need to insert 5 and to make the output number the maximum number both for negative and positive numbers (and without the condition to not replace or transform the input set of digits), then this may be a solution:
def solution(N):
negative = False
if N < 0:
negative = True
N = N * -1 # as N<0 we make it positive
a = []
while N != 0:
v = N % 10
N = int(N / 10)
a = [v] + a
if len(a) == 0:
a = [0]
inserted = False
for i in range(0, len(a)):
if (not negative and a[i] < 5) or (negative and a[i] > 5):
a = a[0:i] + [5] + a [i:]
inserted = True
break
if not inserted:
a = a + [5]
N = 0
for i in range(0, len(a)):
N = N * 10 + a[i]
if negative:
N = N * -1
return N
if __name__ == '__main__':
print("Solution:", solution(N))
Will the below do the trick:
x=-34278
no_to_insert=5
res=int(''.join(sorted(list(str(abs(x)))+[str(no_to_insert)], reverse=True)))
if x<0:
res=-res
Output:
-875432
Java Solution
public int solution(int N) {
int digit = 5;
if (N == 0) return digit * 10;
int neg = N/Math.abs(N);
N = Math.abs(N);
int n = N;
int ctr = 0;
while (n > 0){
ctr++;
n = n / 10;
}
int pos = 1;
int maxVal = Integer.MIN_VALUE;
for (int i=0;i<=ctr;i++){
int newVal = ((N/pos) * (pos*10)) + (digit*pos) + (N%pos);
if (newVal * neg > maxVal){
maxVal = newVal*neg;
}
pos = pos * 10;
}
return maxVal;
}
You are given two strings of length n, you have to find distinct xor values by rearranging the elements in an arbitrary way of the two strings.
Here is what I tried:
String1 = input()
String2 = input()
s1_ones = String1.count('1') #Number of 1's in string1
s2_ones = String2.count('1') #Number of 1's in string2
minimum_overlap = s1_ones+s2_ones-n #minimum overlapping 1's when performing xor
maximum_overlap = min(s1_ones,s2_ones) #maximum overlapping 1's when performing xor
if(minimum_overlap<0):
minimum_overlap = 0
ans = 0
for x in range(minimum_overlap,maximum_overlap+1):
resulting_ones = s1_ones + s2_ones - 2*x #number of ones in resulting string
ans+=(nCr(n,resulting_ones)) #nCr is a function which returns number of possible values of resulting String.
print(ans)
I would like to explain nCr(n,r) funtion a little more. Given that you have string of length 5 in which number of ones are say 3. Here, N = 5 String = '11100' nCr(5,3) will give all the possible values of the provided string which is (5!/3!*2!) = 10.
What is wrong with this approach?
Here is the nCr(n,k):
def nCr(n, k):
if(k > n - k):
k = n - k
res = 1
for i in range(k):
res = res * (n - i)
res = res / (i + 1)
return (res)
I hope, This answers all your questions
import operator as op
from functools import reduce
import operator as op
from functools import reduce
def nCr(n, r):
r = min(r, n-r)
numer = reduce(op.mul, range(n, n-r, -1), 1)
denom = reduce(op.mul, range(1, r+1), 1)
return numer / denom
String1 = input()
String2 = input()
n=len(String1)
s1_ones = String1.count('1')
s2_ones = String2.count('1')
minimum_overlap = max(s1_ones,s2_ones)-min(s1_ones,s2_ones)
zero=n-max(s1_ones,s2_ones)
x=min(s1_ones,s2_ones)
ans = 0
while zero>-1 and x>-1:
zero-=1
x-=1
ans+=nCr(n,minimum_overlap)%1000000007
minimum_overlap+=2
print(int(ans))
now this nCr function is faster than factorial version, but if it still take time to execute, you can use fermat's theorem for nCr%p (also precompute factorial array) which you can find on internet
Stern's Diatomic Sequence can be read about in more details over here; however, for my purpose I will define it now.
Definition of Stern's Diatomic Sequence
Let n be a number to generate the fusc function out of. Denoted fusc(n).
If n is 0 then the returned value is 0.
If n is 1 then the returned value is 1.
If n is even then the returned value is fusc(n / 2).
If n is odd then the returned value is fusc((n - 1) / 2) + fusc((n + 1) / 2).
Currently, my Python code brute forces through most of the generation, other than the dividing by two part since it will always yield no change.
def fusc (n):
if n <= 1:
return n
while n > 2 and n % 2 == 0:
n /= 2
return fusc((n - 1) / 2) + fusc((n + 1) / 2)
However, my code must be able to handle digits in the magnitude of 1000s millions of bits, and recursively running through the function thousands millions of times does not seem very efficient or practical.
Is there any way I could algorithmically improve my code such that massive numbers can be passed through without having to recursively call the function so many times?
With memoization for a million bits, the recursion stack would be extremely large. We can first try to look at a sufficiently large number which we can work by hand, fusc(71) in this case:
fusc(71) = fusc(35) + fusc(36)
fusc(35) = fusc(17) + fusc(18)
fusc(36) = fusc(18)
fusc(71) = 1 * fusc(17) + 2 * fusc(18)
fusc(17) = fusc(8) + fusc(9)
fusc(18) = fusc(9)
fusc(71) = 1 * fusc(8) + 3 * fusc(9)
fusc(8) = fusc(4)
fusc(9) = fusc(4) + fusc(5)
fusc(71) = 4 * fusc(4) + 3 * fusc(5)
fusc(4) = fusc(2)
fusc(3) = fusc(1) + fusc(2)
fusc(71) = 7 * fusc(2) + 3 * fusc(3)
fusc(2) = fusc(1)
fusc(3) = fusc(1) + fusc(2)
fusc(71) = 11 * fusc(1) + 3 * fusc(2)
fusc(2) = fusc(1)
fusc(71) = 14 * fusc(1) = 14
We realize that we can avoid recursion completely in this case as we can always express fusc(n) in the form a * fusc(m) + b * fusc(m+1) while reducing the value of m to 0. From the example above, you may find the following pattern:
if m is odd:
a * fusc(m) + b * fusc(m+1) = a * fusc((m-1)/2) + (b+a) * fusc((m+1)/2)
if m is even:
a * fusc(m) + b * fusc(m+1) = (a+b) * fusc(m/2) + b * fusc((m/2)+1)
Therefore, you may use a simple loop function to solve the problem in O(lg(n)) time
def fusc(n):
if n == 0: return 0
a = 1
b = 0
while n > 0:
if n%2:
b = b + a
n = (n-1)/2
else:
a = a + b
n = n/2
return b
lru_cache works wonders in your case. make sure maxsize is a power of 2. may need to fiddle a bit with that size for your application. cache_info() will help with that.
also use // instead of / for integer division.
from functools import lru_cache
#lru_cache(maxsize=512, typed=False)
def fusc(n):
if n <= 1:
return n
while n > 2 and n % 2 == 0:
n //= 2
return fusc((n - 1) // 2) + fusc((n + 1) // 2)
print(fusc(1000000000078093254329870980000043298))
print(fusc.cache_info())
and yes, this is just meomization as proposed by Filip Malczak.
you might gain an additional tiny speedup using bit-operations in the while loop:
while not n & 1: # as long as the lowest bit is not 1
n >>= 1 # shift n right by one
UPDATE:
here is a simple way of doing meomzation 'by hand':
def fusc(n, _mem={}): # _mem will be the cache of the values
# that have been calculated before
if n in _mem: # if we know that one: just return the value
return _mem[n]
if n <= 1:
return n
while not n & 1:
n >>= 1
if n == 1:
return 1
ret = fusc((n - 1) // 2) + fusc((n + 1) // 2)
_mem[n] = ret # store the value for next time
return ret
UPDATE
after reading a short article by dijkstra himself a minor update.
the article states, that f(n) = f(m) if the fist and last bit of m are the same as those of n and the bits in between are inverted. the idea is to get n as small as possible.
that is what the bitmask (1<<n.bit_length()-1)-2 is for (first and last bits are 0; those in the middle 1; xoring n with that gives m as described above).
i was only able to do small benchmarks; i'm interested if this is any help at all for the magitude of your input... this will reduce the memory for the cache and hopefully bring some speedup.
def fusc_ed(n, _mem={}):
if n <= 1:
return n
while not n & 1:
n >>= 1
if n == 1:
return 1
# https://www.cs.utexas.edu/users/EWD/transcriptions/EWD05xx/EWD578.html
# bit invert the middle bits and check if this is smaller than n
m = n ^ (1<<n.bit_length()-1)-2
n = m if m < n else n
if n in _mem:
return _mem[n]
ret = fusc(n >> 1) + fusc((n >> 1) + 1)
_mem[n] = ret
return ret
i had to increase the recursion limit:
import sys
sys.setrecursionlimit(10000) # default limit was 1000
benchmarking gave strange results; using the code below and making sure that i always started a fresh interperter (having an empty _mem) i sometimes got significantly better runtimes; on other occasions the new code was slower...
benchmarking code:
print(n.bit_length())
ti = timeit('fusc(n)', setup='from __main__ import fusc, n', number=1)
print(ti)
ti = timeit('fusc_ed(n)', setup='from __main__ import fusc_ed, n', number=1)
print(ti)
and these are three random results i got:
6959
24.117448464001427
0.013900151001507766
6989
23.92404893300045
0.013844672999766772
7038
24.33894686200074
24.685758719999285
that is where i stopped...
Let's say I have two strings made with only 1 character:
'aaaaaaa'
'bbb'
I'd like to find an algorithm to produce a combined string of:
'aabaabaaba'
The two are merged so that there is the fewest # of consecutive characters from either list (in this case that # is 2). The length of each string is arbitrary, and I'd like for it to be symmetrical. Bonus points for extending it to more than just 2 strings.
I am doing this in python, but the language doesn't matter. This is for a load balancing problem I'm working on.
You can use the elements alternatively and use a letter of the longer string if necessary. You can determine whether an additional letter is possible with integer arithmetics: A fraction tells you how many letters come between each letter pair. You accumulate this fraction and use letters from the longer array as long as that accumulated fraction is larger than ½:
def intertwine(a, b):
""" Return a combination of string with fewest number of
consecutive elements from one string
"""
if len(b) > len(a):
return intertwine(b, a)
if not b:
return a
a = list(a)
b = list(b)
num = len(a) - len(b)
denom = len(b)
acc = 0
res = []
while a or b:
acc += num
while acc >= denom / 2:
if a: res += a.pop(0)
acc -= num
if a: res += a.pop(0)
if b: res += b.pop(0)
return "".join(res)
print intertwine("aaabaaa", "bbb") # "aababbaaba"
print intertwine("aaaaaaa", "b") # "aaabaaaa"
print intertwine("aaaaaa", "b") # "aaabaaa"
print intertwine("aa", "bbbbbb") # "bbabbabb"
print intertwine("", "bbbbbb") # "bbbbbb"
print intertwine("", "") # ""
import itertools
def intermix(*containers):
mix = []
for c in sorted(containers, key=lambda c: len(c)):
if len(c) >= len(mix):
bigger, smaller = c, mix
else:
bigger, smaller = mix, c
ratio, remainder = divmod(len(bigger), len(smaller) + 1)
chunk_sizes = (ratio + (1 if i < remainder else 0) for i in range(len(smaller) + 1))
chunk_offsets = itertools.accumulate(chunk_sizes)
off_start = 0
new_mix = []
for i, off in enumerate(chunk_offsets):
new_mix.extend(bigger[off_start:off])
if i == len(smaller):
break
new_mix.append(smaller[i])
off_start = off
mix = new_mix
return mix
Given any iterable, for example: "ABCDEF"
Treating it almost like a numeral system as such:
A
B
C
D
E
F
AA
AB
AC
AD
AE
AF
BA
BB
BC
....
FF
AAA
AAB
....
How would I go about finding the ith member in this list? Efficiently, not by counting up through all of them. I want to find the billionth (for example) member in this list. I'm trying to do this in python and I am using 2.4 (not by choice) which might be relevant because I do not have access to itertools.
Nice, but not required: Could the solution be generalized for pseudo-"mixed radix" system?
--- RESULTS ---
# ------ paul -----
def f0(x, alph='ABCDE'):
result = ''
ct = len(alph)
while x>=0:
result += alph[x%ct]
x /= ct-1
return result[::-1]
# ----- Glenn Maynard -----
import math
def idx_to_length_and_value(n, length):
chars = 1
while True:
cnt = pow(length, chars)
if cnt > n:
return chars, n
chars += 1
n -= cnt
def conv_base(chars, n, values):
ret = []
for i in range(0, chars):
c = values[n % len(values)]
ret.append(c)
n /= len(values)
return reversed(ret)
def f1(i, values = "ABCDEF"):
chars, n = idx_to_length_and_value(i, len(values))
return "".join(conv_base(chars, n, values))
# -------- Laurence Gonsalves ------
def f2(i, seq):
seq = tuple(seq)
n = len(seq)
max = n # number of perms with 'digits' digits
digits = 1
last_max = 0
while i >= max:
last_max = max
max = n * (max + 1)
digits += 1
result = ''
i -= last_max
while digits:
digits -= 1
result = seq[i % n] + result
i //= n
return result
# -------- yairchu -------
def f3(x, alphabet = 'ABCDEF'):
x += 1 # Make us skip "" as a valid word
group_size = 1
num_letters = 0
while 1: #for num_letters in itertools.count():
if x < group_size:
break
x -= group_size
group_size *= len(alphabet)
num_letters +=1
letters = []
for i in range(num_letters):
x, m = divmod(x, len(alphabet))
letters.append(alphabet[m])
return ''.join(reversed(letters))
# ----- testing ----
import time
import random
tries = [random.randint(1,1000000000000) for i in range(10000)]
numbs = 'ABCDEF'
time0 = time.time()
s0 = [f1(i, numbs) for i in tries]
print 's0 paul',time.time()-time0, 'sec'
time0 = time.time()
s1 = [f1(i, numbs) for i in tries]
print 's1 Glenn Maynard',time.time()-time0, 'sec'
time0 = time.time()
s2 = [f2(i, numbs) for i in tries]
print 's2 Laurence Gonsalves',time.time()-time0, 'sec'
time0 = time.time()
s3 = [f3(i,numbs) for i in tries]
print 's3 yairchu',time.time()-time0, 'sec'
times:
s0 paul 0.470999956131 sec
s1 Glenn Maynard 0.472999811172 sec
s2 Laurence Gonsalves 0.259000062943 sec
s3 yairchu 0.325000047684 sec
>>> s0==s1==s2==s3
True
Third time's the charm:
def perm(i, seq):
seq = tuple(seq)
n = len(seq)
max = n # number of perms with 'digits' digits
digits = 1
last_max = 0
while i >= max:
last_max = max
max = n * (max + 1)
digits += 1
result = ''
i -= last_max
while digits:
digits -= 1
result = seq[i % n] + result
i //= n
return result
Multi-radix solution at the bottom.
import math
def idx_to_length_and_value(n, length):
chars = 1
while True:
cnt = pow(length, chars)
if cnt > n:
return chars, n
chars += 1
n -= cnt
def conv_base(chars, n, values):
ret = []
for i in range(0, chars):
c = values[n % len(values)]
ret.append(c)
n /= len(values)
return reversed(ret)
values = "ABCDEF"
for i in range(0, 100):
chars, n = idx_to_length_and_value(i, len(values))
print "".join(conv_base(chars, n, values))
import math
def get_max_value_for_digits(digits_list):
max_vals = []
for val in digits_list:
val = len(val)
if max_vals:
val *= max_vals[-1]
max_vals.append(val)
return max_vals
def idx_to_length_and_value(n, digits_list):
chars = 1
max_vals = get_max_value_for_digits(digits_list)
while True:
if chars-1 >= len(max_vals):
raise OverflowError, "number not representable"
max_val = max_vals[chars-1]
if n < max_val:
return chars, n
chars += 1
n -= max_val
def conv_base(chars, n, digits_list):
ret = []
for i in range(chars-1, -1, -1):
digits = digits_list[i]
radix = len(digits)
c = digits[n % len(digits)]
ret.append(c)
n /= radix
return reversed(ret)
digits_list = ["ABCDEF", "ABC", "AB"]
for i in range(0, 120):
chars, n = idx_to_length_and_value(i, digits_list)
print "".join(conv_base(chars, n, digits_list))
What you're doing is close to a conversion from base 10 (your number) to base 6, with ABCDEF being your digits. The only difference is "AA" and "A" are different, which is wrong if you consider "A" the zero-digit.
If you add the next greater power of six to your number, and then do a base conversion to base 6 using these digits, and finally strip the first digit (which should be a "B", i.e. a "1"), you've got the result.
I just want to post an idea here, not an implementation, because the question smells a lot like homework to me (I do give the benefit of the doubt; it's just my feeling).
First compute the length by summing up powers of six until you exceed your index (or better use the formula for the geometric series).
Subtract the sum of smaller powers from the index.
Compute the representation to base 6, fill leading zeros and map 0 -> A, ..., 5 -> F.
This works (and is what i finally settled on), and thought it was worth posting because it is tidy. However it is slower than most answers. Can i perform % and / in the same operation?
def f0(x, alph='ABCDE'):
result = ''
ct = len(alph)
while x>=0:
result += alph[x%ct]
x /= ct-1
return result[::-1]
alphabet = 'ABCDEF'
def idx_to_excel_column_name(x):
x += 1 # Make us skip "" as a valid word
group_size = 1
for num_letters in itertools.count():
if x < group_size:
break
x -= group_size
group_size *= len(alphabet)
letters = []
for i in range(num_letters):
x, m = divmod(x, len(alphabet))
letters.append(alphabet[m])
return ''.join(reversed(letters))
def excel_column_name_to_idx(name):
q = len(alphabet)
x = 0
for letter in name:
x *= q
x += alphabet.index(letter)
return x+q**len(name)//(q-1)-1
Since we are converting from a number Base(10) to a number Base(7), whilst avoiding all "0" in the output, we will have to adjust the orginal number, so we do skip by one every time the result would contain a "0".
1 => A, or 1 in base [0ABCDEF]
7 => AA, or 8 in base [0ABCDEF]
13 => BA, or 15 in base [0ABCDEF]
42 => FF, or 48 in base [0ABCDEF]
43 =>AAA, or 50 in base [0ABCDEF]
Here's some Perl code that shows what I'm trying to explain
(sorry, didn't see this is a Python request)
use strict;
use warnings;
my #Symbols=qw/0 A B C D E F/;
my $BaseSize=#Symbols ;
for my $NR ( 1 .. 45) {
printf ("Convert %3i => %s\n",$NR ,convert($NR));
}
sub convert {
my ($nr,$res)=#_;
return $res unless $nr>0;
$res="" unless defined($res);
#Adjust to skip '0'
$nr=$nr + int(($nr-1)/($BaseSize-1));
return convert(int($nr/$BaseSize),$Symbols[($nr % ($BaseSize))] . $res);
}
In perl you'd just convert your input i from base(10) to base(length of "ABCDEF"), then do a tr/012345/ABCDEF/ which is the same as y/0-5/A-F/. Surely Python has a similar feature set.
Oh, as pointed out by Yarichu the combinations are a tad different because if A represented 0, then there would be no combinations with leading A (though he said it a bit different). It seems I thought the problem to be more trivial than it is. You cannot just transliterate different base numbers, because numbers containing the equivalent of 0 would be
skipped in the sequence.
So what I suggested is actually only the last step of what starblue suggested, which is essentially what Laurence Gonsalves implemented ftw. Oh, and there is no transliteration (tr// or y//) operation in Python, what a shame.