Related
Lets say that in Python I need to generate a 2d matrix that is n * n. My function get's a parameter "n" and it generates a n*n list, such as
for n = 3
[[1,2,3],[4,5,6],[7,8,9]]
That isn't the problem. My function needs to make a 2d list which is first filled left to right, then right to left, and so on... How do i do this?
Example;
for n = 3
it should generate:
[[1,2,3],[6,5,4],[7,8,9]]
and for n = 4:
[[1,2,3,4],[8,7,6,5],[9,10,11,12],[16,15,14,13]]
the simpler way is just to reverse the list every other step
m = []
for line in range(n):
if line%2 == 0:
m.append([*range(line*n,line*n+n)])
else:
m.append([*range(line*n+n,line*n,-1)])
Here I have used some cool python methods like list slicing and ternary operator to make it short and sweet.
n = 5
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]
matrix = [primes[i:i+n] if i%2==0 else primes[i:i+n][::-1] for i in
range(0,len(primes),n)]
print(matrix)
here a straightforward solution but probably not the best:
n = 5
matrix = []
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]
def fill_matrix(arr):
index = 0
for i in range(n):
holder = []
for _ in range(n):
holder.append(primes[index])
index += 1
if i%2 != 0:
arr.append(list(reversed(holder)))
else:
arr.append(holder)
fill_matrix(matrix)
print(matrix)
this will output for n=5: [[2, 3, 5, 7, 11], [29, 23, 19, 17, 13], [31, 37, 41, 43, 47], [71, 67, 61, 59, 53], [73, 79, 83, 89, 97]]
We can try this
[[k+n-x-1 if ((k-1)/n)%2 else k+x for x in range(n)] for k in range(1,n*n+1,n)]
which gives
[[1, 2, 3], [6, 5, 4], [7, 8, 9]]
from random import *
lotto_num = []
for j in range(7) :
for i in range(1, 8) :
number = randint(1, 46)
while number in lotto_num:
number = randint(1, 46)
lotto_num.append(number)
lotto_num.sort()
print("{0}".format(lotto_num))
This code makes lottery number
so, I want to get lists like
[1,2,3,4,5,6,7]
[2,3,4,5,6,7,8]
[3,4,5,6,7,8,9]
...
but my code only has shown like this
[1,2,3,4,5,6,7,8,9,10.......] ## <- just add number without make new lists!
how i can fix this?
You continually append to lotto_num without resetting it. So it needs to be reset after each print in order to make a new number.
Just move your lotto_num definition to inside the first for loop:
from random import *
for j in range(7) :
lotto_num = []
for i in range(1, 8) :
number = randint(1, 46)
while number in lotto_num:
number = randint(1, 46)
lotto_num.append(number)
lotto_num.sort()
print("{0}".format(lotto_num))
Output:
[7, 17, 29, 32, 34, 44, 45]
[9, 16, 22, 34, 36, 41, 43]
[5, 10, 14, 22, 23, 34, 46]
[2, 11, 18, 27, 32, 35, 37]
[8, 9, 25, 26, 37, 39, 40]
[3, 5, 8, 14, 19, 22, 33]
[4, 5, 14, 17, 18, 30, 34]
First of all, it is recommended to import specific functions instead of whole package. Since we need only randint we can import:
from random import randint
Than your problem can be re-worded as generating n lists of given length l, filled by random numbers from range 1-46.
from random import randint
# number of lotto
n = 5
# length of each lotto
l = 7
# result
lotto_numbers = []
# I am using _ since we do not need that value
for _ in range(n):
lotto = []
for _ in range(l):
number = randint(1, 46)
while number in lotto:
number = randint(1, 46)
lotto.append(number)
lotto.sort()
lotto_numbers.append(lotto)
print(lotto_numbers)
Later you can print generated lotto (or save them into file), that is better approach than printing each lotto right after generation.
...
for lotto in lotto_numbers:
print(lotto)
Probably the cleanest Pythonic solution which uses random.sample to simulate n times drawing random non-repeated numbers from range 1-46 follows:
from random import sample
# number of lotto
n = 5
# length of each lotto
l = 7
lotto_numbers = [sorted(sample(range(1, 46), l)) for _ in range(n)]
print(lotto_numbers)
from random import *
array=[]
for j in range(7) :
lotto_num = []
for i in range(1, 8) :
number = randint(1, 46)
while number in lotto_num:
number = randint(1, 46)
lotto_num.append(number)
lotto_num.sort()
array.append(lotto_num)
print("{0}".format(lotto_num))
I am starting on my Python journey and am doing some exercises to get the hang of it all. One question is really giving me troubles as I do not understand how to complete it.
Question:
Given a list of natural numbers, remove from it all multiples of 2 (but not 2), multiples of 3 (but not 3), and so on, up to the multiples of 100, and print the remaining values.
From this question I take it that I should first make a list with all prime numbers and after that append the values that correspond to a new list. This is what I have until know:
# Read list:
a = [5, 6, 7, 8, 9]
# First get a list with all primes
primes = []
for i in range(0, 101):
for j in range(2, int(i ** 0.5) + 1):
if i%j == 0:
break
else:
primes.append(i)
# Next append to new list
b = []
for num in a:
for prime in primes:
if num == prime and num % prime == 0:
b.append(num)
print(b)
Now this works for this simple example, but upon testing it on another set (one of which I do not know the input values of the test case), my output is:
[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]
Which is my original list with the prime numbers. So somewhere along the line I am making a mistake and I cannot see the logic behind it. Any help would be greatly appreciated.
To solve the task all you need to do is filter out the numbers by using a generator and a for loop, which by itself is already finding the prime numbers
a = [5,6,7,8,9]
for i in range(2,101):
a = [j for j in a if (j==i or j%i!=0)]
I have an array A
A = [5,2,8,14,6,13]
I want to get an array where each element is added to every other element, so the first five elements would be 5 + each element, then the next four would be 2 + each element etc.
So the result would be
B = [7,13,19,11,18, 10,16,8,15, 22,14,21, 20,27, 19]
What is the quickest way to do this without using for loops?
Note: The problem I am trying to solve involves large boolean arrays instead of integers and the actual operation is a boolean 'and', not merely addition. I have simplified the question for ease of explanation. I have been using for loops up to now, but I am looking for a faster alternative.
Use ` itertools.combinations
from itertools import combinations
a = [5,2,8,14,6,13]
print [sum(i) for i in list(combinations(a, 2))]
No need of list(). Thanks to #PeterWood
print [sum(i) for i in combinations(a, 2)]
Output:
[7, 13, 19, 11, 18, 10, 16, 8, 15, 22, 14, 21, 20, 27, 19]
Demo
You could do it recursively:
def add_value_to_rest(sequence):
if not sequence:
return []
else:
additional = sequence[0]
return ([additional + value for value in sequence] +
add_value_to_rest(sequence[1:]))
With generators, in Python 3:
def add_value_to_rest(sequence):
if sequence:
additional = sequence[0]
for value in sequence:
yield additional + value
yield from add_value_to_rest(sequence[1:])
Or with Python 2.7:
def add_value_to_rest(sequence):
if sequence:
additional = sequence[0]
for value in sequence:
yield additional + value
for value in add_value_to_rest(sequence[1:]):
yield value
A = [5,2,8,14,6,13]
B = []
for i, x in enumerate(A):
for l in range(len(A) - i - 1):
B.append(A[i] + A[i + l + 1])
print B
#[7, 13, 19, 11, 18, 10, 16, 8, 15, 22, 14, 21, 20, 27, 19]
I've got this piece of code:
numbers = list(range(1, 50))
for i in numbers:
if i < 20:
numbers.remove(i)
print(numbers)
but the result I'm getting is:
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
Of course, I'm expecting the numbers below 20 to not appear in the results. Looks like I'm doing something wrong with the remove.
You're modifying the list while you iterate over it. That means that the first time through the loop, i == 1, so 1 is removed from the list. Then the for loop goes to the second item in the list, which is not 2, but 3! Then that's removed from the list, and then the for loop goes on to the third item in the list, which is now 5. And so on. Perhaps it's easier to visualize like so, with a ^ pointing to the value of i:
[1, 2, 3, 4, 5, 6...]
^
That's the state of the list initially; then 1 is removed and the loop goes to the second item in the list:
[2, 3, 4, 5, 6...]
^
[2, 4, 5, 6...]
^
And so on.
There's no good way to alter a list's length while iterating over it. The best you can do is something like this:
numbers = [n for n in numbers if n >= 20]
or this, for in-place alteration (the thing in parens is a generator expression, which is implicitly converted into a tuple before slice-assignment):
numbers[:] = (n for in in numbers if n >= 20)
If you want to perform an operation on n before removing it, one trick you could try is this:
for i, n in enumerate(numbers):
if n < 20 :
print("do something")
numbers[i] = None
numbers = [n for n in numbers if n is not None]
Begin at the list's end and go backwards:
li = list(range(1, 15))
print(li)
for i in range(len(li) - 1, -1, -1):
if li[i] < 6:
del li[i]
print(li)
Result:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
[6, 7, 8, 9, 10, 11, 12, 13, 14]
#senderle's answer is the way to go!
Having said that to further illustrate even a bit more your problem, if you think about it, you will always want to remove the index 0 twenty times:
[1,2,3,4,5............50]
^
[2,3,4,5............50]
^
[3,4,5............50]
^
So you could actually go with something like this:
aList = list(range(50))
i = 0
while i < 20:
aList.pop(0)
i += 1
print(aList) #[21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
I hope it helps.
The ones below are not bad practices AFAIK.
EDIT (Some more):
lis = range(50)
lis = lis[20:]
Will do the job also.
EDIT2 (I'm bored):
functional = filter(lambda x: x> 20, range(50))
So I found a solution but it's really clumsy...
First of all you make an index array, where you list all the index' you want to delete like in the following
numbers = range(1, 50)
index_arr = []
for i in range(len(numbers):
if numbers[i] < 20:
index_arr.append(i)
after that you want to delete all the entries from the numbers list with the index saved in the index_arr. The problem you will encounter is the same as before. Therefore you have to subtract 1 from every index in the index_arr after you just removed a number from the numbers arr, like in the following:
numbers = range(1, 50)
index_arr = []
for i in range(len(numbers):
if numbers[i] < 20:
index_arr.append(i)
for del_index in index_list:
numbers.pop(del_index)
#the nasty part
for i in range(len(index_list)):
index_list[i] -= 1
It will work, but I guess it's not the intended way to do it
As an additional information to #Senderle's answer, just for records, I thought it's helpful to visualize the logic behind the scene when python sees for on a "Sequence type".
Let's say we have :
lst = [1, 2, 3, 4, 5]
for i in lst:
print(i ** 2)
It is actually going to be :
index = 0
while True:
try:
i = lst.__getitem__(index)
except IndexError:
break
print(i ** 2)
index += 1
That's what it is, there is a try-catch mechanism that for has when we use it on a Sequence types or Iterables(It's a little different though - calling next() and StopIteration Exception).
*All I'm trying to say is, python will keep track of an independent variable here called index, so no matter what happens to the list (removing or adding), python increments that variable and calls __getitem__() method with "this variable" and asks for item.
Building on and simplying the answer by #eyquem ...
The problem is that elements are being yanked out from under you as you iterate, skipping numbers as you progress to what was the next number.
If you start from the end and go backwards, removing items on-the-go won't matter, because when it steps to the "next" item (actually the prior item), the deletion does not affect the first half of the list.
Simply adding reversed() to your iterator solves the problem. A comment would be good form to preclude future developers from "tidying up" your code and breaking it mysteriously.
for i in reversed(numbers): # `reversed` so removing doesn't foobar iteration
if i < 20:
numbers.remove(i)
You could also use continue to ignore the values less than 20
mylist = []
for i in range(51):
if i<20:
continue
else:
mylist.append(i)
print(mylist)
Since Python 3.3 you may use the list copy() method as the iterator:
numbers = list(range(1, 50))
for i in numbers.copy():
if i < 20:
numbers.remove(i)
print(numbers)
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]