Related
I have to do an exercise that ask me to do a function that find the frequency of consecutive values on a list and return a list of tuples where I have to show how many times it was the repetition.
Input:
[1, 1, 1, 3, 5, 1, 1, 3, 3]
Output:
[(1,3) , (3,1) , (5,1) , (1,2) , (3,2)]
Code:
def empaquetar(l):
lista = []
for i in range(len(l)-1):
cont = 0
j = i + 1
while l[i] == l[j] and j<len(l)-1:
cont += 1
i += 1
j += 1
if cont > 0:
lista.append((l[i], cont + 1))
else:
lista.append((l[i],1))
return lista
Well, what I wrote does not quite exactly return what I want and I can't find a solution but I search a lot, for example the tool Counter from collection or something like. I need help, any suggestion?
Not thoroughly tested, but here is a try
prev_val = None
counter = 1
for curr_val in input_list:
if prev_val is not None:
if prev_val != curr_val:
output_list.append((prev_val, counter))
counter = 1
else:
counter += 1
prev_val = curr_val
output_list.append((prev_val, counter))
print (output_list)
from itertools import groupby
lista = [group[0], len(list(group[1])) for group in groupby(l)]
I have developed an algorithm with a time complexity of O(n) for this.
def consecutive(lst):
lst.append(0)
count = 1
result = []
for i, value in enumerate(lst):
if value == lst[min(len(lst) - 1, i + 1)]:
count += 1
else:
result.append((value, count))
count = 1
return result
Results
Let's try a few test cases for this function.
>>> lst = [1, 1, 1, 3, 5, 1, 1, 3, 3]
>>> consecutive(lst)
[(1, 3), (3, 1), (5, 1), (1, 2), (3, 2)]
Here is another test case to verify the code.
>>> lst = [1, 2, 5, 5, 3, 2, 2, 1]
>>> consecutive(lst)
[(1, 1), (2, 1), (5, 2), (3, 1), (2, 2), (1, 1)]
Use a second for loop to check how many times the number is there consecutively.
def empaquetar(l):
lista = []
for i in l:
cont = 1
for j in range(i+1, len(l)):
If l[j]==i:
cont += 1
else:
break
lista.append((i, cont))
return lista
I am stuck on a problem involving splitting up a list into different sized chunks. I want to have a list that is randomly split into either pairs of 2 or 3.
example:
L = [1,1,1,1,1,1,1,1,1,1,1,1]
and I want to get something out like:
L2 = [(1,1,1),(1,1),(1,1),(1,1,1),(1,1)]
but this I want to be random, so that the distribution of pairs and triplets changes everytime the code is ran.
As a more general approach you can use following function:
from itertools import count
import random
def my_split(lst, chunks):
def chunk_creator():
total = 0
while total <= len(lst):
x = random.choice(chunks)
yield L[total: x + total]
total += x
yield total - x
def chunk_finder():
for _ in count():
chunk = list(chunk_creator())
total = chunk.pop(-1)
if total == len(L):
return chunk[:-1]
if max(chunks) <= len(L):
return chunk_finder()
else:
return None
Demo :
>>> L = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
>>> my_split(L, (2, 3))
... [[1, 1], [1, 1], [1, 1], [1, 1, 1], [1, 1, 1]]
>>> my_split(L, (2, 3))
... [[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]]
Explanation:
This function is consist of to sub functions. First one is chunk_creator which it's job is creating the desire chunks based on the length of your list and return them as an iterator. Note that, the end value is the total variable which is the sum of preceding chunks.
The second function (chunk_finder) will find the desire chunks for us by goring through an in infinity loop (itertools.count()) and checking if the value of total is equal with the length of input list.
There are many ways to solve this, maybe you can write a generator that returns chunks of sizes based on a size function:
import random
def take_chunked(i, size):
idx = 0
while idx < len(i):
s = size(i[idx:])
yield i[idx:idx+s]
idx += s
def size_fun(i):
if len(i) == 4:
return 2
if len(i) <= 3:
return len(i)
return random.randint(2,3)
Output:
>>> list(take_chunked("helloworld", size_fun))
['he', 'll', 'owo', 'rld']
>>> list(take_chunked("helloworld", size_fun))
['hel', 'low', 'or', 'ld']
>>> list(take_chunked("a", size_fun))
['a']
>>> list(take_chunked("", size_fun))
[]
This version will guarantee that the chunk sizes are either 2 or 3, as long as there are enough items in the list.
Hope this helps.
step1: use random module to generate a random number
step2: use random number to decide if it should be pair or 2(for even random number)/3(if random is nt even).
step3: code it.
from random import random
def selector():
s = int(random() * 100 )
return (s/2) == 0
L = [1 for i in range(30)]
L2 = []
while L:
if selector():
tmp = 2
else:
tmp = 3
#print tmp
if tmp > 0 and len(L) >= tmp:
L2.append( [ L.pop() for i in range(tmp)] )
if len(L) < 3:
L2.append(set(L))
L = []
print L, L2
Factorize len(L) into chunks of 2s and 3s and then use a loop to divide the list.
import numpy as np
def rand23():
return np.random.randint(2,4)
def get_chunk(sz):
rem = sz
ch = []
while ( rem > 0 ):
if ( rem <= 3 ): #if <= 3 add what is left in the chunk (exit condition)
ch.append(rem)
rem = 0
break
elif ( rem == 4 ): #4 is the only edge case here
ch.append(2)
ch.append(2)
rem = 0
break
else:
ch.append(rand23())
rem -= ch[-1]
return ch
L = [1,1,1,1,1,1,1,1,1,1,1,1]
ch = get_chunk(len(L))
L2 = []
count = 0
#Divide the list into chunks based on ch
for c in ch:
L2.append(tuple(L[count:count+c]))
count += c
print L2
Results:( each line is output of an iteration )
[(1, 1, 1), (1, 1), (1, 1), (1, 1), (1, 1, 1)]
[(1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)]
[(1, 1, 1), (1, 1, 1), (1, 1, 1), (1, 1, 1)]
[(1, 1), (1, 1), (1, 1, 1), (1, 1, 1), (1, 1)]
[(1, 1, 1), (1, 1), (1, 1), (1, 1), (1, 1, 1)]
[(1, 1, 1), (1, 1, 1), (1, 1), (1, 1), (1, 1)]
[(1, 1), (1, 1), (1, 1, 1), (1, 1), (1, 1, 1)]
PS : You can also implement get_chunk() recursively.
This one is fairly simple and will do the trick :-)
import random
L = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
L2 = list()
i = 0
j = random.randint(2, 3)
while i < len(L):
chunk = L[i:j]
L2.append(chunk)
i = j
if len(L) - i == 4: # case: 4 elements left in L
j = i + 2
elif len(L) - i < 4: # case: 2 or 3 elements left in L
j = len(L)
else:
j = i + random.randint(2, 3)
print L
print L2
I'm trying to built a magic square:
A magic square is one divided in rows and columns, with a number in each position and which the sum of rows, columns and diagonals is the same.
Example (3x3 - numbers from 1 to 9):
8 3 4
1 5 9
6 7 2
I tried to use a matrix 3x3 and a vector with 9 indexes.
import random
#j(column)
matriz = [[1, 2, 3],#i(row)
[4, 5, 6],
[7, 8, 9]]
res = False
#DEFINE A FUNCTION TO CALCULATE ALL SUMS OF ALL SIDES
def magicsquare():
if matriz[0][0] + matriz[1][0] + matriz[2][0] == matriz[0][1] + matriz[1][1] + matriz[2][1] == matriz[0][2] + matriz[1][2] + matriz[2][2] == matriz[0][0] + matriz[0][1] + matriz[0][2] == matriz[1][0] + matriz[1][1] + matriz[1][2] == matriz[2][0] + matriz[2][1] + matriz[2][2] == matriz[0][0] + matriz[1][1] + matriz[2][2] == matriz[0][2] + matriz[1][1] + matriz[2][0]:
return res = True
else:
return res = False
#DEFINE A LOOP TO GENERATE RANDOM NUMBER UNTIL FIND THE ONES THAT
#SATISFY THE CONDITIONS OF A MAGIC SQUARE
seq = [1, 2, 3, 4, 5, 6, 7, 8, 9]
while res == False:
for i in range(2):
for j in range(2):
z = random.choice(seq)
matriz[i][j] = z
x = seq.index(z)
seq[x] = []
magicsquare()
print (matriz)
#---------------------------------------------------------------------------------------------------------------------------------------------------------------
res = False
def magicsquare():
if vetor[0] + vetor[1] + vetor[2] == vetor[3] + vetor[4] + vetor[5] == vetor[6] + vetor[7] + vetor[8] == vetor[0] + vetor[3] + vetor[6] == vetor[1] + vetor[4] + vetor[7] == vetor[2] + vetor[5] + vetor[8] == vetor[0] + vetor[4] + vetor[8] == vetor[2] + vetor[4] + vetor[6]:
return res == True
else:
return res == False
# 0 1 2 3 4 5 6 7 8
vetor = [1, 2, 3, 4, 5, 6, 7, 8, 9]
seq = [1, 2, 3, 4, 5, 6, 7, 8, 9]
if res == False:
for i in range(8):
w = random.choice(seq)
#Replace the value w in index i
vetor.insert(i, w)
#Eliminate the valyes already used
x = seq.index(w)
seq[x] =[]
magicsquare()
print (vetor)
The result is always: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Can anyone help me built a magic square and tell what's wrong with my code?
Using Python 3.5.0
Your randomizing code is wrong.
>>>
Traceback (most recent call last):
File "C:/Users/xiao/Desktop/ms.py", line 20, in <module>
magicsquare()
File "C:/Users/xiao/Desktop/ms.py", line 5, in magicsquare
if vetor[0] + vetor[1] + vetor[2] == vetor[3] + vetor[4] + vetor[5] == vetor[6] + vetor[7] + vetor[8] == vetor[0] + vetor[3] + vetor[6] == vetor[1] + vetor[4] + vetor[7] == vetor[2] + vetor[5] + vetor[8] == vetor[0] + vetor[4] + vetor[8] == vetor[2] + vetor[4] + vetor[6]:
TypeError: unsupported operand type(s) for +: 'int' and 'list'
>>> vetor
[9, 4, 8, 2, 3, [], [], [], 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
random module has a method called shuffle for shuffling a list. If you have no idea about your code, just use random.shuffle.
Plus, there are 2 ways to stop the while loop. The first way is to change the global variable res in function magicsquare:
def magicsquare():
global res
if ...:
res = True
else:
res = False
The other way is to return the condition in magicsquare:
import random
vetor = [1, 2, 3, 4, 5, 6, 7, 8, 9]
def magicsquare():
return vetor[0]+vetor[1]+vetor[2]==\
vetor[3]+vetor[4]+vetor[5]==\
vetor[6]+vetor[7]+vetor[8]==\
vetor[0]+vetor[3]+vetor[6]==\
vetor[1]+vetor[4]+vetor[7]==\
vetor[2]+vetor[5]+vetor[8]==\
vetor[0]+vetor[4]+vetor[8]==\
vetor[2]+vetor[4]+vetor[6]
while not magicsquare():
random.shuffle(vetor)
print (vetor)
def forEvenNumber(n):
arr = [[(n * y) + x + 1 for x in range(n)] for y in range(n)]
for i in range(0, n // 4):
for j in range(0, n // 4):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(0, n // 4):
for j in range(3 * (n // 4), n):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(3 * (n // 4), n):
for j in range(0, n // 4):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(3 * (n // 4), n):
for j in range(3 * (n // 4), n):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(n // 4, 3 * (n // 4)):
for j in range(n // 4, 3 * (n // 4)):
arr[i][j] = (n * n + 1) - arr[i][j];
print("\nSum of all row, column and diagonals = ",
n * (n * n + 1) // 2, "\n")
for i in range(n):
for j in range(n):
print('%2d ' % (arr[i][j]), end=" ")
print()
def forOddNumber(n):
mgsqr = [[0 for x in range(n)]
for y in range(n)]
r = n // 2
c = n - 1
num = 1
while num <= (n * n):
if r == -1 and c == n:
c = n - 2
r = 0
else:
if c == n:
c = 0
if r < 0:
r = n - 1
if mgsqr[int(r)][int(c)]:
c = c - 2
r = r + 1
continue
else:
mgsqr[int(r)][int(c)] = num
num = num + 1
c = c + 1
r = r - 1
print("\nSum of all row, column and diagonals = ",
n * (n * n + 1) // 2, "\n")
for i in range(0, n):
for j in range(0, n):
print('%2d ' % (mgsqr[i][j]), end='')
print()
print("\nWELCOME:)\n")
n = int(input("Please Enter Number of Rows and Column (n*n): "))
if n%2==0:
forEvenNumber(n)
else:
forOddNumber(n)
print("\nThank You :)")
try my code..
box = []
num = [1, 2, 3,
4, 5, 6,
7, 8, 9]
val = []
for i in num:
for j in num:
for k in num:
if ((i+j+k) == 15) and i != j and j != k and k != i:
val.append((i, j, k))
def check_sum(lst: list):
rtn = []
res = 0
lst = lst[0]
for c in range(3):
for r in range(3):
res += lst[r][c]
if res == 15:
rtn.append(True)
else:
rtn.append(False)
res = 0
res = 0
for x in range(3):
for y in range(3):
if x == y:
res += lst[x][y]
if res == 15:
rtn.append(True)
else:
rtn.append(False)
res = 0
for x in range(3):
for y in range(3):
if x+y == 2:
res += lst[x][y]
if res == 15:
rtn.append(True)
else:
rtn.append(False)
return all(rtn)
def is_unique(a, b, c):
st = set()
for x in a:
st.add(x)
for x in b:
st.add(x)
for x in c:
st.add(x)
if len(st) == 9:
return True
else:
return False
def print_box(b):
for row in b[0]:
print(row)
print()
for i in val:
for j in val:
for k in val:
if is_unique(i, j, k):
box.append([i, j, k])
if check_sum(box):
print_box(box)
if len(box) == 1:
box.clear()
output is:
(2, 7, 6)
(9, 5, 1)
(4, 3, 8)
(2, 9, 4)
(7, 5, 3)
(6, 1, 8)
(4, 3, 8)
(9, 5, 1)
(2, 7, 6)
(4, 9, 2)
(3, 5, 7)
(8, 1, 6)
(6, 1, 8)
(7, 5, 3)
(2, 9, 4)
(6, 7, 2)
(1, 5, 9)
(8, 3, 4)
(8, 1, 6)
(3, 5, 7)
(4, 9, 2)
(8, 3, 4)
(1, 5, 9)
(6, 7, 2)
I am trying to write a code that takes
m. a, a list of integers
n. b, an integer
and returns the number of pairs (m,n) with m,n in a such that |m-n|<=b.
So far, I've got this
def nearest_pairs(a, b):
m= []
n= int
num_pairs = 0
return num_pairs
def main():
# The nearest pairs are (1,2), (2,1), (2,5) and (5,2)
x = nearest_pairs( [1,2,5] , 3 )
print( "nearest_pairs([1, 2, 5], 3) = " , nearest_pairs([1, 2, 5], 3) )
# The nearest pairs are (1,2) and (2,1)
y = nearest_pairs( [1, 2, 5] , 2 )
print( "nearest_pairs([1, 2, 5], 2) = " , nearest_pairs([1, 2, 5], 2) )
if __name__ == '__main__':
main()
The desired output should look like
>>> nearest_pairs([1,2,5],3) = 4
where 4 is the number of close pairs according to the restrictions. However, I get an error. Could anyone lead me to the right direction?
Yours doesn't make sense. No idea what you're trying with len(a, b), but it's not even allowed, since len takes only one argument. And returning something just when you found the first counting pair? Here's a fix:
def close_pairs(l, d):
ctr = 0
for a,b in permutations(l, 2):
if (a - b) <= d and (b - a) <= d:
ctr += 1
return ctr
And here's how I'd do it:
def close_pairs(l, d):
return sum(abs(a-b) <= d for a, b in permutations(l, 2))
from itertools import permutations
def nearest_pairs(a, b):
for m, n in permutations(a, 2):
if abs(m - n) <= b:
yield (m, n)
>>> list(nearest_pairs([1, 2, 5], 3))
[(1, 2), (2, 1), (2, 5), (5, 2)]
>>> list(nearest_pairs([1, 2, 5], 2))
[(1, 2), (2, 1)]
If you just want the count:
def nearest_pairs_count(a, b):
c, l = 0, len(a)
for i in range(l):
for j in range(i + 1, l):
if abs(a[i] - a[j]) <= b:
c += 2
return c
The challenge was to find all possible combinations of numbers less than N whose sum equals N.
For instance, when N is equal to:
2
1+1 - 1 way
3
2+1
1+1+1 - 2 ways
4
3+1
2+2
2+1+1
1+1+1+1 - 4 ways
and so on...
Now creating it in python, to understand the pattern I drafted this code 1st:
N=5
for d in drange(0,N,1):
if N-d*4>=0:
for c in drange(0,N,1):
if N-d*4-c*3>=0:
for b in drange(0,N,1):
if N-d*4-c*3-b*2>=0:
for a in drange(0,N,1):
if N-d*4-c*3-b*2-a*1==0:
if sum([d,c,b,a])!=1:
print d,c,b,a
else: break
else:break
else:break
Then I changed the code to this where this worked for N = 6 and below:
N=6
for e in drange(0,N,1):
if N-e*5>=0:
C0 = N-e*5
for d in drange(0,N,1):
if C0-d*4>=0:
C1 = C0-d*4
for c in drange(0,N,1):
if C1-c*3>=0:
C2 = C1-c*3
for b in drange(0,N,1):
if C2-b*2>=0:
C3 = C2-b*2
for a in drange(0,N,1):
if C3-a*1==0:
if sum([e,d,c,b,a])!=1:
print e,d,c,b,a
else: break
else:break
else:break
else:break
Next Version incorporated arrays to keep track of numbers and save computation space:
N=6
Nums = drange2(6-1,-1,-1)
Vals = [0]*6
Vars = [0]*6
for Vars[0] in drange(0,N,1):
if N-Vars[0]*Nums[0]>=0:
Vals[0] = N-Vars[0]*Nums[0]
for Vars[1] in drange(0,N,1):
if Vals[0]-Vars[1]*Nums[1]>=0:
Vals[1] = Vals[0]-Vars[1]*Nums[1]
for Vars[2] in drange(0,N,1):
if Vals[1]-Vars[2]*Nums[2]>=0:
Vals[2] = Vals[1]-Vars[2]*Nums[2]
for Vars[3] in drange(0,N,1):
if Vals[2]-Vars[3]*Nums[3]>=0:
Vals[3] = Vals[2]-Vars[3]*Nums[3]
for Vars[4] in drange(0,N,1):
if Vals[3]-Vars[4]*Nums[4]==0:
if sum([Vars[0],Vars[1],Vars[2],Vars[3],Vars[4]])!=1:
print Vars
else: break
else:break
else:break
else:break
Then I thought to make this code functional where N is 100, I made it recursive...
N=48
Nums = drange2(N-1,-1,-1)
Vals = [0]*N
Vars = [0]*(N-1)
count=0
def sumCombos(Number,i):
if i==0:
global count
for Vars[i] in xrange(0,i+2,1):
z = Number-Vars[i]*Nums[i]
if z>=0:
Vals[i] = z
sumCombos(Number,i+1)
else: break
elif i<Number-2:
for Vars[i] in xrange(0,i+1,1):
z = Vals[i-1]-Vars[i]*Nums[i]
if z >=0:
Vals[i]=z
sumCombos(Number,i+1)
else: break
elif i==Number-2:
for Vars[i] in xrange(0,i+3,1):
if Vals[i-1]-Vars[i]*Nums[i]==0:
count+=1
sumCombos(N,0)
print count
PROBLEM: It takes too much time because of 1000000+ method calls, so is there a way I can make this iterative where it creates that previous cascade effect without me typing that all? I searched the website and others on how to make a recursive function involving for-loops and if statements iterative, but no luck with this particular one. Please offer any wisdom -- Shaha3
Why do you want it to be recursive?
>>> from itertools import chain, combinations_with_replacement
>>> n = 7
>>> [i for i in chain.from_iterable(
combinations_with_replacement(range(1, n), k)
for k in range(2, n+1))
if sum(i) == n]
[(1, 6), (2, 5), (3, 4), (1, 1, 5), (1, 2, 4), (1, 3, 3), (2, 2, 3), (1, 1, 1, 4), (1, 1, 2, 3), (1, 2, 2, 2), (1, 1, 1, 1, 3), (1, 1, 1, 2, 2), (1, 1, 1, 1, 1, 2), (1, 1, 1, 1, 1, 1, 1)]
This problem grows with n! so, it'll take a lot of time for big numbers.
I guess you are talking about integer partitioning problem (wiki: http://en.wikipedia.org/wiki/Partition_(number_theory) ) It can be done either an iterative way or a recursive way, though there could be a depth limit on the recursive method. Here are my implementations
def partitions(n):
def next(seq):
L = len(seq)
## start from L-2 element, must have at least one element in suffix
for i in range(L-2, -1, -1):
if seq[i-1] and seq[i-1] > seq[i]: break
remainder = n - sum(seq[:i+1]) - 1
return seq[:i] + [seq[i]+1] + [1 for _ in range(remainder)]
start, end = [1 for _ in range(n)], [n]
seq = start
while True:
yield seq
if seq >= end: break
seq = next(seq)
# test cases
if __name__ == '__main__':
## test partitions
assert list(partitions(4)) == [[1, 1, 1, 1], [2, 1, 1], [2, 2], [3, 1], [4]]
assert list(partitions(5)) == [
[1, 1, 1, 1, 1],
[2, 1, 1, 1], [2, 2, 1],
[3, 1, 1], [3, 2],
[4, 1],
[5]]
print 'all tests passed'