Loop of List into a Tabbed New List - python

I am a high school student. By observing the inputted sequence, I want to create a program that creates general formulas on quadratic to a polynomial with nth power equations. This posted code will function as a means of validation for inputted sequences. If you have a better code, please help me. Thank You!
The same concept was shown below,
here is my code
def shrink(numbers):
n1 = [(x, numbers[i+1]) for i, x in enumerate(numbers)
if i < len(numbers)-1]
n2 = [x[1]-x[0] for x in n1]
print(n2)
if(len(n2) > 1):
return shrink(n2)
return n
#shrink([1, 8, 27, 64, 125, 216])
a = input()
b = a.split()
for i in range(len(b)):
b[i] = int(b[i])
shrink(b)
"""
The output will be:
[7, 19, 37, 61, 91]
[12, 18, 24, 30]
[6, 6, 6]
[0, 0]
[0]
"""
#I want the output from the top to be like this!
d = [
[7, 19, 37, 61, 91],
[12, 18, 24, 30],
[6, 6, 6],
[0, 0],
[0]
]
if d[2][0] == d[2][1]:
print('cubic sequence')

During the first call you initialize a list variable which you update and pass to the recursive call
def shrink(numbers,return_list = []):
n1 = [(x, numbers[i+1]) for i, x in enumerate(numbers) if i < len(numbers)-1]
n2 = [x[1]-x[0] for x in n1]
return_list.append(n2)
if(len(n2) > 1):
return shrink(n2,return_list)
else:
return return_list
print(shrink([1, 8, 27, 64, 125, 216]))
If you want the values of n1 as well :
def shrink(numbers,n1_list = [], n2_list = []):
n1 = [(x, numbers[i+1]) for i, x in enumerate(numbers) if i < len(numbers)-1]
n2 = [x[1]-x[0] for x in n1]
n1_list.append(n1)
n2_list.append(n2)
# print(n2)
if(len(n2) > 1):
return shrink(n2,n1_list,n2_list)
else:
return n1_list,n2_list
print(shrink([1, 8, 27, 64, 125, 216]))

Thank You Atharva Gundawar.
If you want the list to be inputted, this is the answer:
Take note that input list should be separated by space and not by a comma.
Sample input: 1 8 27 64 125 216
def shrink(numbers, return_list=[]):
n1 = [(x, numbers[i + 1]) for i, x in enumerate(numbers) if i < len(numbers) - 1]
n2 = [x[1] - x[0] for x in n1]
return_list.append(n2)
if (len(n2) > 1):
return shrink(n2, return_list)
else:
return return_list
a = input()
b = a.split()
for i in range(len(b)):
b[i] = int(b[i])
c = shrink(b)
print(shrink(b))
print(c[2][0])
print(c[2][1])
if c[2][0] == c[2][1]:
print('cubic sequence')
Input:
1 8 27 64 125 216
Output:
[[7, 19, 37, 61, 91], [12, 18, 24, 30], [6, 6, 6], [0, 0], [0], [7, 19, 37, 61, 91], [12, 18, 24, 30], [6, 6, 6], [0, 0], [0]]
6
6
cubic sequence

This is the correct answer to eradicate the loop:
https://stackoverflow.com/posts/70423499/revisions
def shrink(numbers, return_list=[]):
n1 = [(x, numbers[i + 1]) for i, x in enumerate(numbers) if i < len(numbers) - 1]
n2 = [x[1] - x[0] for x in n1]
return_list.append(n2)
if (len(n2) > 1):
return shrink(n2, return_list)
else:
return return_list
input_user = input("Enter data:")
b = input_user.split()
for num in range(len(b)):
b[num] = int(b[num])
c = shrink(b)
print(c)

Related

Find elements in list with difference of 1

Suppose I have a list like this:
lst = [1, 3, 4, 5, 8, 10, 14, 20, 21, 22, 23, 40, 47, 48]
I need to extract the elements which have a difference of one. I need final output to look like this:
[[3, 4, 5], [20, 21, 22, 23], [47, 48]]
Here is what I have tried so far for this particular problem which has yielded some progress but doesn't achieve 100% of what I need:
final_list = []
for i in range(len(lst)):
sub_list = []
for ii in range(i, len(lst)):
prev_num = lst[ii-1]
if lst[ii] - prev_num == 1:
# print(lst[ii], end=",")
sub_array.append(lst[ii])
else:
break
if sub_list:
final_list.append(sub_list)
print(final_list)
Output:
[[4, 5], [5], [21, 22, 23], [22, 23], [23], [48]]
You can use itertools.groupby to group the items with a key function that subtracts each item value with an incremental counter, which would result in a fixed value for each group of consecutive integers:
from itertools import groupby, count
lst = [1, 3, 4, 5, 8, 10, 14, 20, 21, 22, 23, 40, 47, 48]
c = count()
final_list = [g for _, [*g] in groupby(lst, lambda t: t - next(c)) if len(g) > 1]
final_list would become:
[[3, 4, 5], [20, 21, 22, 23], [47, 48]]
EDIT: If you'd rather have better performance than more concise code, you can look at #MadPhysicist's answer, which avoids overhead incurred from calling generator functions, and #don'ttalkjustcode's answer, which avoids creating lists until a pair of consecutive numbers are found. Combine the two answers and you get a solution that avoids both types of overhead:
out = []
prev = float('inf')
for i in lst:
if i - prev != 1:
current = None
elif current:
current.append(i)
else:
current = [prev, i]
out.append(current)
prev = i
Sample timing using #don'ttalkjustcode's benchmark code:
2716 μs Mad_Physicist
1554 μs dont_talk_just_code
1284 μs Mad_Physicist_x_dont_talk_just_code
Try it online!
You can step along the input list and start adding elements to an output list. Any time the difference is greater than 1, start a new output list. If the prior output is length 1, remove it:
out = []
current = []
prev = None
for i in lst:
if prev is None or i - prev != 1:
if len(current) > 1:
out.append(current)
current = []
current.append(i)
prev = i
if len(current) > 1:
out.append(current)
A zip solution that adds each first pair of a streak as an inner list and then appends further elements of the streak:
out = []
inner = None
for x, y in zip(lst, lst[1:]):
if y - x == 1:
if inner:
inner.append(y)
else:
inner = [x, y]
out.append(inner)
else:
inner = None
Benchmark with a random list 1000 as long as your example and with same density:
5172 μs blhsing
2697 μs Mad_Physicist
7667 μs Osman_Mamun
1571 μs dont_talk_just_code
Benchmark code (Try it online!):
from timeit import timeit
from itertools import groupby, count
from random import sample
def blhsing(lst):
c = count()
return [g for _, [*g] in groupby(lst, lambda t: t - next(c)) if len(g) > 1]
def Mad_Physicist(lst):
out = []
current = []
prev = None
for i in lst:
if prev is None or i - prev > 1:
if len(current) > 1:
out.append(current)
current = []
current.append(i)
prev = i
if len(current) > 1:
out.append(current)
return out
def Osman_Mamun(lst):
out = []
for k, g in groupby(enumerate(lst), key=lambda i: i[1]-i[0]):
temp = list(g)
if len(temp) > 1:
out.append([i[1] for i in temp])
return out
def dont_talk_just_code(lst):
out = []
inner = None
for x, y in zip(lst, lst[1:]):
if y - x == 1:
if inner:
inner.append(y)
else:
inner = [x, y]
out.append(inner)
else:
inner = None
return out
lst_example = [1, 3, 4, 5, 8, 10, 14, 20, 21, 22, 23, 40, 47, 48]
funcs = blhsing, Mad_Physicist, Osman_Mamun, dont_talk_just_code
for _ in range(3):
lst = sorted(sample(range(max(lst_example) * 1000), len(lst_example) * 1000))
# lst = lst_example
results = []
for func in funcs:
t = timeit(lambda: results.append(func(lst)), number=100) / 100
print('%d μs ' % (t * 1e6), func.__name__)
assert all(result == results[0] for result in results), (list(map(len, results)), results)
print()
Using itertools.groupby:
In [19]: out = []
In [20]: for k, g in groupby(enumerate(lst), key=lambda i: i[1]-i[0]):
...: temp = list(g)
...: if len(temp) > 1:
...: out.append([i[1] for i in temp])
...:
In [21]: out
Out[21]: [[3, 4, 5], [20, 21, 22, 23], [47, 48]]
You can go through the elements and either add them as a new group or add them to the last group depending on whether it is one more than the last one added. When done, remove the single element groups.
lst = [1, 3, 4, 5, 8, 10, 14, 20, 21, 22, 23, 40, 47, 48]
groups = []
for n in lst:
if groups and n-1 == groups[-1][-1]:
groups[-1].append(n) # +1 element, add to last group
else:
groups.append([n]) # add as a new group
groups = [g for g in groups if len(g)>1] # remove single element groups
print(groups)
[[3, 4, 5], [20, 21, 22, 23], [47, 48]]

Find bug in my Knight's Move Python Program

Code
I am trying to build a Knight's Move Program everything working fine but there is a hidden bug in this code that I cannot find. Can anybody spot the problem?
from itertools import product
def solution(src, dest):
A = [[0, 1, 2, 3, 4, 5, 6, 7],
[8, 9, 10, 11, 12, 13, 14, 15],
[16, 17, 18, 19, 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, 50, 51, 52, 53, 54, 55],
[56, 57, 58, 59, 60, 61, 62, 63]]
if (src not in range(0,64) or dest not in range(0,64)) :
raise Exception('out of range')
step = 1
r_s = 0
r_e = 7
str_r = 0
str_c = 0
while src:
if r_s <= src <= r_e:
for i in range(0, 8):
if A[str_r][i] == src:
str_c = i
break
break
str_r += 1
r_s += 8
r_e += 8
moves = list(product([str_r - 1, str_r + 1], [str_c - 2, str_c + 2])) + list(product([str_r - 2, str_r + 2],[str_c - 1, str_c + 1]))
m_s = [(x,y) for x,y in moves if x >= 0 and y >= 0 and x < 8 and y < 8]
for i, j in m_s:
if A[i][j] == dest:
move_counter = step
return move_counter
while True:
step += 1
List_steps = []
for i, j in m_s:
r_s = 0
r_e = 7
str_r = 0
str_c = 0
while True:
if r_s <= A[i][j] <= r_e:
for x in range(0, 8):
if A[str_r][x] == A[i][j]:
str_c = x
break
break
str_r += 1
r_s += 8
r_e += 8
moves = list(product([str_r - 1, str_r + 1], [str_c - 2, str_c + 2])) + list(product([str_r - 2, str_r + 2],[str_c - 1, str_c + 1]))
m_z = [(x,y) for x,y in moves if x >= 0 and y >= 0 and x < 8 and y < 8]
for m, n in m_z:
if A[m][n] == dest:
return step
move_counter = 'Not Found'
List_steps += m_z
if move_counter == 'Not Found':
m_s = list(set(List_steps))
continue
if __name__ == '__main__':
A = int(input())
B = int(input())
print(solution(A, B))
Bug Location
I think the bug is here:
moves = list(product([str_r - 1, str_r + 1], [str_c - 2, str_c + 2])) + list(product([str_r - 2, str_r + 2],[str_c - 1, str_c + 1]))
m_z = [(x,y) for x,y in moves if x >= 0 and y >= 0 and x < 8 and y < 8]

Python array logic

I am trying to create a list of lists with the input of m and n, where m is the number of lists within the main list and n is the number of elements within each given list. The grid should contain the integers from start to start + rows * cols - 1 and be ascending. But, every odd numbered row should be descending instead.
The code I've written is returning the expected results, but my automated tester is saying it's incorrect. Maybe my logic is messed up somewhere?
inputs:
start = 1, m = 3, n = 5
expected:
[[1,2,3,4,5],[10,9,8,7,6],[11,12,13,14,15]]
result = []
mylist = []
start = 1
for x in range(0, rows):
for x in range(0, cols):
result.append(start)
start += 1
for y in range(0, rows):
if y%2 != 0:
mylist.append(result[cols - 1::-1])
del result[cols - 1::-1]
else:
mylist.append(result[0:cols])
del result[0:cols]
return mylist
One possible solution, using itertools.count:
from itertools import count
def build(m, n, start=1):
lst, c = [], count(start)
for i in range(m):
lst.append([next(c) for j in range(n)][::-1] if i % 2 else [next(c) for j in range(n)])
return lst
print(build(3, 5, 1))
Prints:
[[1, 2, 3, 4, 5], [10, 9, 8, 7, 6], [11, 12, 13, 14, 15]]
print(build(3, 0, 1))
Prints:
[[], [], []]
just generate the list of numbers you need which will be n * m, in your case that would generate 0 to 14 in the python range function. However as we want to start at ` then we need to add the start offset too the range end.
Now we can generate all the numbers we need we just need to think about how to create them.
well we can add numbers to the list until the list reaches the size of n, then we need to start a new list, However if the list we just finished is an even numbered row then we need to reverse that list.
def build_lists(m, n, start=1):
data =[[]]
for i in range(start, n * m + start):
if len(data[-1]) < n:
data[-1].append(i)
else:
if len(data) % 2 == 0:
data[-1] = data[-1][::-1]
data.append([i])
if len(data) % 2 == 0:
data[-1] = data[-1][::-1]
return data
print(build_lists(3, 5))
print(build_lists(6, 3))
print(build_lists(6, 2, 100))
OUTPUT
[[1, 2, 3, 4, 5], [10, 9, 8, 7, 6], [11, 12, 13, 14, 15]]
[[1, 2, 3], [6, 5, 4], [7, 8, 9], [12, 11, 10], [13, 14, 15], [18, 17, 16]]
[[100, 101], [103, 102], [104, 105], [107, 106], [108, 109], [111, 110]]

Given two matrices, print the product of those matrices

I have to check if the given matrices can be multiplied, and if yes, return the product.
I cannot use numpy to calculate the product.
Example used:
A = [[1,2],[3,4]]
B = [[1,2,3,4,5],[5,6,7,8,9]]
Expected output: A*B = [[11,14,17,20,23],[23,30,37, 44,51]]
Here's my code and output:
def matrix_mult(A,B):
countA = 0
countB = 0
result = [[0]*len(B[0])]*len(A)
for i in range(len(A)):
if A[i][1]:
countA += 1
for i in range(len(B)):
if B:
countB += 1
if countA == countB:
for i in range(len(A)):
for j in range(len(B[0])):
for k in range(len(A)):
result[i][j] += A[i][k]*B[k][j]
return result
A = [[1,2],[3,4]]
B = [[1,2,3,4,5], [5,6,7,8,9]]
matrix_mult(A,B)
output:
[[34, 44, 54, 64, 74], [34, 44, 54, 64, 74]]
Is there something wrong with the code/logic?
The guilty is your result declaration. It's not a good way to declare a list by duplicating the elements (not creating a proper matrix). More details in this discussion.
Try:
result = [[0 for _ in range(len(B[0]))] for _ in range(len(A))]
Instead of:
result = [[0] * len(B[0]) ] * len(A)
And that should work fine !
Why make the code so long? You can try this -
def dot(A, B):
return [[sum(x*y for x, y in zip(A_row, B_column)) for B_column in zip(*B)] for A_row in A]
A = [[1,2],[3,4]]
B = [[1,2,3,4,5],[5,6,7,8,9]]
result = dot(A, B)
print(result)
#[[11, 14, 17, 20, 23], [23, 30, 37, 44, 51]]
See if this helps you.
I will recommend using numpy:
import numpy as np
A = np.array([[1,2],[3,4]])
B = np.array([[1,2,3,4,5],[5,6,7,8,9]])
np.matmul(A, B)
# output : array([[11, 14, 17, 20, 23],
# [23, 30, 37, 44, 51]])
with your code there are several issues, below I was trying to improve your code:
def matrix_mult(A,B):
num_col_a = len(A[0])
num_rows_b = len(B)
result = [[0 for _ in range(len(B[0]))] for _ in range(len(A))]
if num_col_a == num_rows_b:
for row_a_index, row_a in enumerate(A):
for col_index, col_b in enumerate(zip(*B)):
result[row_a_index][col_index] = sum(a * b for a, b in zip(row_a, col_b))
return result
A = [[1,2],[3,4]]
B = [[1,2,3,4,5], [5,6,7,8,9]]
print(matrix_mult(A,B))
# output: [[11, 14, 17, 20, 23], [23, 30, 37, 44, 51]]

select qualified element from 2D array into a new list

I have a 2D array of integer value:
[[26, 9, 24, 13],
[16, 14, 39, 29]]
I need to select the number >= 14, ends in 9 or 4, and not 39. It returns 1 if the criteria meets, otherwise return 0, i.e.
[[0, 0, 1,0],
[0,0,0,1]]
updated: code suggested by Tomothy32
result = result = [[int(x >= 14 and x % 10 in (4, 9) and x != 19) for x in sl] for sl in X]
another nested loop approach
def test(X):
out = [[0]*len(X[0]) for _ in range(len(X))]
for i in range(len(X)):
for j in range(len(X[i])):
check = X[i][j]
if check>=14 and check%5==4 and check!=39:
out[i][j] = 2
return out
You can use a list comprehension:
x = [[26, 9, 43, 13],
[16, 14, 39, 29]]
result = [[int(x >= 14 and x % 10 == 9 and x != 39) for x in sl] for sl in x]
print(result)
# [[0, 0, 0, 0], [0, 0, 0, 1]]
To get the last digit, use the remainder/modulo operator.
Change this statements:
if element >=14 and element !=39:
to
if element >=14 and element !=39 and element%10==9:

Categories