I am trying to get multiple lines of the alphabet but it isn't working. At the moment I have 1 row but it won't work.
What I'm after is once the alphabet gets from a to z, it will add another letter on until aa to zz and on and on.
As Requested, the code I currently have is as follows:
import string
alphabets = string.ascii_lowercase
for i in alphabets:
print(i)
alphabets = string.ascii_lowercase
if i == 'z':
for b in alphabets:
print('{}{}'.format(b, b))
print('{}{}'.format(b, b))
I would recommend using nested for loops. The outer for loop will iterate through the alphabet, while the outer defines the number of times you want to add a given letter. Note that some string s times some integer i duplicates that string i times. This gives us:
for i in range(...) #However many instances of the alphabet you want
for j in range(26)
print(chr(ord('a')+j)*i)
EDIT: The answer above gives 'a'-'z', followed by 'aa', 'bb', ..., 'zz', etc, which is not what was being looked for.
Instead, we will construct an array and iterate through it in reverse. The code I came up with is kind of ugly, but it works. Apologies for the last line in particular.
def checkArr(arr):
for i in arr:
if i != 25:
return True
return False
arr = []
for i in range(5):
arr = []
for j in range(i+1):
arr.append(0)
while(checkArr(arr)):
s = ""
for j in arr:
s += chr(j + ord("a"))
print(s)
index = len(arr)-1
while (index > 0 and arr[index] == 25):
arr[index] = 0
index -= 1
arr[index] += 1
print("z"*(i+1))
Related
Looking for a "pythonish" and simple way to achieve the generation of all possible numbers following different ranges of digits.
Example: Generate strings (representing number) with digits '01234567' ranging from [0-4] occurrences and '8' ranging from [0-10] occurrences and '9' from [0-100]
Example of numbers generated: {'11337899999999', '33567899999999', '245678999999999999999',...}
(all generated numbers should be with sequential digits... so '88119' isn't valid)
So far I came up with a very simple and clean code but that doesn't do exactly what I need:
from itertools import combinations_with_replacement
length = 50
for x in combinations_with_replacement('0123456789', length):
print("".join(x), end=', ')
This will generate the numbers I need but as well a bunch of unnecessary ones, which will delay significantly the execution.
Thought on generating the digits one by one according to the rules and concatenating... but believe this will be a "dirty" solution and as well inefficient.
Anyone knows a nice clean way of doing this? (Itertools, or any other library is welcome)
I am not sure I fully undersand you problem, but i think i have a solution :
import random
def generate(string = ""):
for i in range(9):
i += 1
if i <= 7:
occurrence = 4
elif i == 8:
occurrence = 10
else:
occurrence = 100
string = string + str(i)* random.randint(0, occurrence)
return string
a = generate()
print(a)
if you want it to be lenght 50 use:
a = a[:50]
So, I ended up picking the itertools.combinations_with_replacement and alter it to accept an array containing maximum usage of digits...
Pretty simple, but it's working.
If anyone has any hints on how to look at it differently or adapt anything to speed up, I will be happy with it.
def combinations_with_replacement2(iterable, m_digits, r):
pool = tuple(iterable)
n = len(pool)
if not n and r: return
count = [0] * n
indices = [0] * r
d = 0
for i in range(r):
if count[d] == m_digits[d]: d += 1
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):
if indices[i] != n - 1: break
else: return
count = [0] * n
d = indices[i] + 1
for f in range(i, r):
indices[f] = d
count[d] += 1
if count[d] == m_digits[d]: d += 1
yield tuple(pool[i] for i in indices)
I would like to iterate through a list of integers, calculate the sum of the lowest numbers that belongs to an arithmetic sequence with common difference 1 + the numbers that are not part of a sequence:
mylist = [2,3,4,10,12,13]
So, from mylist it would be 2 (from 2,3,4) + 10 (not part of a sequence) + 12 (from 12,13)
I've managed to make something work, but I could only figure out how to do it, if the list is reversed. And I am sure there is a better/cleaner solution that mine:
mylist = [13,12,10,4,3,2]
result = mylist[-1] #if I don't do this, I don't know how to grab the last item in the list
for i in range(len(mylist)-1):
if mylist[i] - mylist[i+1] == 1:
continue
else:
result += mylist[i]
Hope someone will help me out, and that I get a little wiser in my coding journey. Thanks.
#KennethRasch - earlier post would work. Alternatively, you can do this as well:
Try to find each possible subsequence's starting numbers as starts then just sum them to get answer.
L = [13,12,10,4,3,2]
L.sort()
starts = [x for x in L if x-1 not in L]
print(starts)
result = sum(starts)
print(result) # 24
Alternatively, you can put this into a function for future re-use it:
def sum_lowests(L):
'''L is a numbers sequence '''
L.sort()
starts = [x for x in L if x-1 not in L]
#ans = sum(starts) # can skip this step; just to make it clear
return sum(starts)
if __name__ == '__main__':
L = [13,12,10,4,3,2]
A = [1, 2, 3, 5,6, 9,10,11, 16]
print(sum_lowests(L))
print(sum_lowests(A)) # 31
Keep a running sum, a running index, and iterate while it's still a sequence:
mylist = [13,12,10,4,3,2]
mylist.sort() # this way sequences will be contiguous in the list
cur_index = 0
cur_sum = 0
while cur_index < len(mylist):
# add the current element to the sum
cur_sum += mylist[cur_index]
# now iterate through while it's a contiguous sequence
cur_index += 1
while cur_index < len(mylist) and mylist[cur_index] == mylist[cur_index - 1] + 1:
cur_index += 1
print(cur_sum)
Here is the explanation of what I'm trying to say:-
Input:- 5 1 3 2 7
Output:- 3
Explanation:
In first move, we move 3 to the end. Our list becomes 5,1,2,7,3
In second move, we move 5 to the end. Our list becomes 1,2,7,3,5
In third move, we move 7 to the end. Our final list = 1,2,3,5,7
So, total moves are:- 3.
Here is what I tried to do, but failed.
a = [int(i) for i in input().split()]
count = 0
n = 0
while (n < len(a) - 1):
for i in range(0,n+1):
while (a[i] > a[i + 1]):
temp = a[i]
a.pop(i)
a.append(temp)
count += 1
n += 1
print(count, end='')
I'd like to request your assistance in helping in solving this question.
jdehesa's answer is basically right, but not optimal for cases, when there is more element of same value. Maybe more complex solution?
def min_moves(a):
c = 0
while(1):
tmp = None
for i in range(0, len(a)):
if a[i] != min(a[i:]) and (tmp is None or a[i] < a[tmp]):
tmp = i
if tmp is None:
return c
else:
a.append(a.pop(tmp))
c += 1
Edit:
Or if you don't need ordered list, there's much more easier solution just to count items that are out of order for the reason from jdehesa's solution :-D
def min_moves(a):
c = 0
for i in range(0, len(a)):
if a[i] != min(a[i:]):
c += 1
return c
Edit 2:
Or if you like jdehesa's answer more, small fix is to reduce lst to set, so it will get smallest index
sorted_index = {elem: i for i, elem in enumerate(sorted(set(lst)))}
I cannot comment yet.
I don't know if it can be done better, but I think the following algorithm gives the right answer:
def num_move_end_sort(lst):
# dict that maps each list element to its index in the sorted list
sorted_index = {elem: i for i, elem in enumerate(sorted(lst))}
moves = 0
for idx, elem in enumerate(lst):
if idx != sorted_index[elem] + moves:
moves += 1
return moves
print(num_move_end_sort([5, 1, 3, 2, 7]))
# 3
The idea is as follows. Each element of the list would have to be moved to the end at most once (it should be easy to see that a solution that moves the same element to the end more than once can be simplified). So each element in the list may or may not need to be moved once to the end. If an element does not need to be moved is because it ended up in the right position after all the moves. So, if an element is currently at position i and should end up in position j, then the element will not need to be moved if the number of previous elements that need to be moved, n, satisfies j == i + n (because, after those n moves, the element will indeed be at position j).
So in order to compute that, I sorted the list and took the indices of each element in the sorted list. Then you just count the number of elements that are not in the right position.
Note this algorithm does not tell you the actual sequence of steps you would need to take (the order in which the elements would have to be moved), only the count. The complexity is O(n·log(n)) (due to the sorting).
I think you can simplify your problem,
Counting elements that need to be pushed at the end is equivalent to counting the length of the elements that are not in sorted order.
l = [5, 1, 3, 2, 7]
sorted_l = sorted(l)
current_element = sorted_l[0]
current_index = 0
ans = 0
for element in l:
if current_element == element:
current_index += 1
if current_index < len(l):
current_element = sorted_l[current_index]
else:
ans += 1
print(ans)
Here the answer is 3
In the following code, I am trying to extract numbers from a list in which all digits are divisible by 2. The following code works.
l = range(100,401)
n=[]
for i in l:
s =str(i)
if all([int(s[0])%2==0,int(s[1])%2==0,int(s[2])%2==0]):
n.append(s)
print(",".join(n))
I was trying to insert a for loop to avoid writing all three conditions explicitly.
l = range(100,401)
n=[]
ss=[]
for i in l:
s =str(i)
ss.append(s)
for element in ss:
for j in range(3):
if int(element[j])%2==0:
n.append(element)
print(n)
I can't get the desired output. Not only that, the elements of output list 'n' at even index are printed twice. I am unable to figure out WHY?
Thanks.
Generator expression checking if all() elements evaluate to True comes to your rescue:
l = range(100,401)
n=[]
for i in l:
s = str(i)
if all(int(ch) % 2 == 0 for ch in s):
n.append(s)
print(",".join(n))
Now it also works even if you work with more digits.
Thanks for #jpp's advice on generator expression!
And here a faster alternative where you evaluate if any() is not divisable with 2.
l = range(100,401)
n=[]
for i in l:
s = str(i)
if any(int(ch) % 2 != 0 for ch in s):
continue
else:
n.append(s)
print(",".join(n))
You can do this:
l = range(100, 401)
n = []
for i in l:
v = 0
for j in str(i):
if int(j) % 2 == 0:
v += 1
if v == len(str(i)):
n.append(str(i))
print(",".join(n))
Or with some list comprehension:
l = range(100, 401)
n = []
for i in l:
if all(int(j) % 2 == 0 for j in str(i)):
n.append(str(i))
print(",".join(n))
Or with even more list comprehension:
l = range(100, 401)
n = [str(i) for i in l if all(int(j) % 2 == 0 for j in str(i))]
print(",".join(n))
Or with a ridiculous minimizing:
print(",".join([str(i) for i in range(100, 401) if all(int(j) % 2 == 0 for j in str(i))]))
Explaining
OP asked me to explain why his code doesn't work. I'll make it in some steps, also optimizing it:
l = range(100,401)
n = []
ss = []
for i in l: # You don't need this loop, you are just making a new list with string values instead of integers. You could make that on the fly.
s = str(i)
ss.append(s)
for element in ss:
for j in range(3):
if int(element[j]) % 2 == 0: # This only check if the current digit is pair and it append the whole number to the list. You have to check if the 3 numbers are pair AND then append it.
n.append(element)
print(n)
Your code check each digit and if that is true, the number is appended to the result list (n). But you don't want that, you want to check if the 3 digits that make the number are pair, so you have to check the whole group.
For example you could do this:
for element in l:
pairs = 0
for j in range(3):
if int(str(element)[j]) % 2 == 0:
pairs += 1 # Each time a digit of the number is pair, `pairs` variable increase in one
if pairs == 3: # If the 3 digits are true it append your number
n.append(str(element))
That is my first idea of how to improve your code, but instead of element and pairs I use j and v, (also I don't use range(3), I just iterate over the stringed number).
If you are looking for something "better" you could try to use a list comprehension like all(int(j) % 2 == 0 for j in str(i)). That iterate over all the digits to check if the are pair, if all the checks are true (like 222, or 284) it returns true.
Let me know if I should explain something more.
Try this method. You don't need to check all the numbers.
You just need to change the range statement from range(100, 401) to range (100, 401, 2) and add some checks as the Numbers which have first digit as Odd you can skip all the 100 numbers and then in next 10 series you can skip 10 if the tenth digit is odd. It reduces the complexity and decreases your processing time.
l = range(100, 401, 2)
n = []
for i in l:
s = str(i)
if int(s[0]) % 2 == 1:
remainder = i % 100
i = i - remainder + 100 - 1
continue
elif int(s[1])%2 == 1:
remainder = i % 10
i = i - remainder + 10 - 1
continue
n.append(s)
print(",".join(n))
I want to run this loop over a list basically it searches for a number in my a range till it finds it search for the next number in the following iterations but instead it starts over again
This is my code
z = [30,84,126,135,137,179,242,342,426]
c=[]
for m in z:
for i in range(1,1002, 7):
if m in range(i, i+7):
c.append(m%7)
break
elif m not in range(i, i+7):
c.append(0)
print len(c) # outputs 246
but len(c) should be equal to 143, how do I fix this?
while a generator seemed to answer the question, there is a better tool for the programming problem: itertools.groupby
from itertools import groupby
z = [1,2,3, 30,84,126,135,136,137,140,141,179,242,342,426]
g = dict([[k, [*g]] for k, g in groupby(z, key=lambda x: (x-1)//7)])
d = [((tuple(g[i]) if len(g[i]) > 1 else g[i][0]) if (i in g) else 0)
for i in range(0, 143)]
ran against my 1st answer's code: (do use the same z, it has been changed)
c == d
Out[278]: True
see how well matched itertools.groupby is look at the dict wrapped groupby result:
g
Out[279]:
{0: [1, 2, 3],
4: [30],
11: [84],
17: [126],
19: [135, 136, 137, 140],
20: [141],
25: [179],
34: [242],
48: [342],
60: [426]}
(the above works in 3.6, the [*g] and dictionary key test (i in g) may be different in 2.7)
I think I figured out what you're trying to do, and your best bet is to change how you're incrementing your search range.
z = [30,84,126,135,137,179,242,342,426]
c=[] # initialize results array
i = 1 # initialize i
for m in z: # for each item in list
while 1: # perform this action until loop breaks
if m in range(i, i+7): #if m is in range
c.append(m%7)
break #break the while loop, moving on to the next item
elif m not in range(i, i+7):
c.append(0)
i = i+7 #increment the search range, but do not break the loop
#Display results
print len(c)
print c
So in your original code, you reset the search range i for each element in the array z. This is why your len(c) values are getting so much higher than expected. In my code, I only iterate i from 1 to 1002 a single time as I go through the array of values.
Please let me know if this doesn't solve your issue, I was able to match the functionality you described but not the expected output for len(c). If you want to get the expected value, you can change the code to match this:
z = [30,84,126,135,137,179,242,342,426]
c=[] # initialize results array
i = 1 # initialize i
for m in z: # for each item in list
while i<1002: # perform this action until loop breaks
if m in range(i, i+7): #if m is in range
c.append(m%7)
i = i+7
break # break the while loop, moving on to the next item
elif m in range(i-7, i):
break
else:
c.append(0)
i = i+7 # increment the search range, but do not break the loop
while i<1002: # finish iterating i all the way up to 1002
c.append(0)
i = i+7
#Display results
print len(c)
print c
Which gets a len(c) of 143.
perhaps what you want is a generator https://docs.python.org/2/howto/functional.html#generator-expressions-and-list-comprehensions
z = [30,84,126,135,136,137,179,242,342,426]
c = []
def counter(maximum, inc): # resetable generator from doc example
i = 1
while i < maximum:
val = (yield i)
# If value provided, change counter
if val is not None:
i = val
else:
i += inc
ig = counter(1002, 7)
for m in z:
for i in ig:
# catch multiple nums in same range
if m < i:
clast = c.pop()
# inline if-else inside append converts int to tuple to add m to
c.append((clast if type(clast) == tuple else (clast,)) + (m,))
# reset ig count
ig.send(i - 7)
break
if i <= m < i+7:
c.append(m)
break
else:
c.append(0)
# exhaust ig if you really want full count = 143
for i in ig:
c.append(0)
print(len(c))
added catching nums in same interval, needed the resettable generator
fixed up the last 2 issues I know of:
now makes a flat tuple for multiple nums in a single range
counts correctly by resetting ig to i - 7