Sorting a text document python 3 - python-3.x

Here's the text document: The first string is the type of metal, the second is the amount of the metal bars, the third is the weight, and the fourth is the value.
Gold 1 5 750
Silver 1 1 400
Rhodium 1 4 500
Platinum 1 6 1000
I have to sort this list by value using insertion sort. Here's what I have so far
def sortMetalsByValuePerBar(metals):
for i in range(1,len(metals)):
j = i
while j > 0 and metals[j-1] > metals[j]:
metals[j - 1], metals[j] = metals[j], metals[j - 1]
j -= 1
return metals
Is this correct?

Try to learn from this solution.
data="""
Gold 1 5 750
Silver 1 1 400
Rhodium 1 4 500
Platinum 1 6 1000
"""
data = filter(None, data.splitlines())
data = [l.split() for l in data]
data = [ (l[0], int(l[1]), int(l[2]), int(l[3])) for l in data ]
def insertion_sort(l, keyfunc=lambda i:i):
for i in range(1, len(l)):
j = i-1
key = l[i]
while keyfunc(l[j]) > keyfunc(key) and (j >= 0):
l[j+1] = l[j]
j -= 1
l[j+1] = key
insertion_sort(data, keyfunc=lambda l: l[3])
for l in data:
print(l)
# Output:
# ('Silver', 1, 1, 400)
# ('Rhodium', 1, 4, 500)
# ('Gold', 1, 5, 750)
# ('Platinum', 1, 6, 1000)

Related

Python(AI Constraint satisfaction problem) Fitting square and/or rectangular (2d) tiles onto a rectangular ground

I have to arrange and/or fit 2d tiles into a 2d square or rectangular plane with AI algorithm using python program. Each tile has a length and width. For example if a plane is 4x3 and set of tiles is
S={(2,3),(1,2),(2,2)}
these tiles can be rotated 90 degrees in order to fit the matrix.
input
first line contains length and width of the plane
second line number of tiles
and then the length,width of the subsequent tiles
but the inputs should be tab seperated
for eg
4 3
3
2 3
1 2
2 2
output
for eg
1 1 2 2
1 1 3 3
1 1 3 3
I have trouble solving this as i have to use only standard libraries in python no NumPy and no CSP library
~Edit 2`
my code so far I cant figure out how to add algorithm without csp library or to generate grid
from sys import stdin
a = stdin.readline()
x = a.split()
rectangular_plane = [[0] * int(x[0]) for i in range(int(x[1]))]
num_of_rectangles = stdin.readline()
r_widths = []
r_lengths= []
for l in range(int(num_of_rectangles)):
b = stdin.readline()
y = b.split()
r_lengths.insert(l,y[0])
r_widths.insert(l,y[1])
I've solved task with backtracking approach and without any non-standard modules.
Try it online!
import sys
nums = list(map(int, sys.stdin.read().split()))
pw, ph = nums[0:2]
ts = list(zip(nums[3::2], nums[4::2]))
assert len(ts) == nums[2]
if sum([e[0] * e[1] for e in ts]) != pw * ph:
print('Not possible!')
else:
def Solve(*, it = 0, p = None):
if p is None:
p = [[0] * pw for i in range(ph)]
if it >= len(ts):
for e0 in p:
for e1 in e0:
print(e1, end = ' ')
print()
return True
for tw, th in [(ts[it][0], ts[it][1]), (ts[it][1], ts[it][0])]:
zw = [0] * tw
ow = [it + 1] * tw
for i in range(ph - th + 1):
for j in range(pw - tw + 1):
if all(p[k][j : j + tw] == zw for k in range(i, i + th)):
for k in range(i, i + th):
p[k][j : j + tw] = ow
if Solve(it = it + 1, p = p):
return True
for k in range(i, i + th):
p[k][j : j + tw] = zw
return False
if not Solve():
print('Not possible!')
Example input:
4 3
3
2 3
1 2
2 2
Output:
1 1 2 2
1 1 3 3
1 1 3 3

Max Points on a Line with python 3

algorithm question:
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
Example 1:
Input: [[1,1],[2,2],[3,3]]
Output: 3
Explanation:
^
|
| o
| o
| o
+------------->
0 1 2 3 4
Example 2:
Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
Output: 4
the working python 3 code is below:
wondering
snippet 1 d[slope] = d.get(slope, 1) + 1 is working
but why this snippet 2 is not working correctly for example 2 even though snippet 1 and 2 are the same
if slope in d:
d[slope] += 1
else:
d[slope] = 1
def gcd(self, a, b):
if b == 0:
return a
return self.gcd(b, a%b)
def get_slope(self, p1, p2):
dx = p1[0] - p2[0]
dy = p1[1] - p2[1]
c = self.gcd(dx, dy)
dx /= c
dy /= c
return str(dy) + "/" + str(dx)
def is_same_points(self, p1:List[int], p2:List[int]):
return p1[0] == p2[0] and p1[1] == p2[1]
def maxPoints(self, points: List[List[int]]) -> int:
if not points:
return 0
n = len(points)
count = 1
for i in range(0, n):
d = {}
duped = 0
localmax = 1
p1 = points[i]
for j in range(i+1, n):
p2 = points[j]
if self.is_same_points(p1, p2):
duped += 1
else:
slope = self.get_slope(p1, p2)
# 1) not work: output is 3 in example 2
# if slope in d:
# d[slope] += 1
# else:
# d[slope] = 1
# 2) works: correct output 4 for example 2
d[slope] = d.get(slope, 1) + 1
localmax = max(localmax, d[slope]);
count = max(count, localmax + duped)
return count
Interesting problem and nice solution.
The reason why the commented out code doesn't work is because of that:
else:
d[slope] = 1 ## correct would be d[slope] = 2
Every 2 points are on the same line, you are counting only one point for the first two p1 p2, thus you get one less in the final answer.

How to compare the elements of a nested list?

I have some kind of matrix:
[[1,2,3],[1,2,3],[0,2,1],[1,2,3]] and I would like to be able to determine how many times I have the sequence 1,2,3 diagonally, vertically and horizontally but I have problems of index out of range for the last two loops. Thank you in advance for your answers!!
lista = [[1,2,3],[1,2,3],[0,2,1],[1,2,3]]
compteur_horizontal = 0
for i in range(len(lista)):
for c in range(len(lista[i])-2):
if lista[i][c] == 1 and lista[i][c+1] == 2 and lista[i][c+2] == 3:
compteur_horizontal += 1
print("ok")
compteur_vertical = 0
for c in range(len(lista)):
for j in range(len(lista[c])):
print(lista[j][c])
compteur_diagonale = 0
for j in range(len(lista)):
print(lista[i][i])
For the first counter, I would like it to be 3 since we have 3 times the sequence 1,2,3 horizontally. For the second counter, I would like it to be 0 because vertically there is no 1,2,3 sequence. And I'm waiting for a counter with 0 also since there's no 1,2,3 sequence in diagonal
Your code will not work even if you correct the current error. You need to change j and c in the second loop to resolve the error.
For horizontal and vertical here's the code. I'll add how to count diagonal ones later.
#lista = [[1, 2, 3],[1, 2, 3],[0, 2, 1],[1, 2, 3]]
lista = [[1,2,2],
[1,2,4],
[4,2,3],
[5,6,3]]
ptrn = [1, 2, 3]
# returns True is lst (1d array) has ptrn (1d array).
# e.g. lst[1,2,4,6,1,2,3,7], ptrn=[1,2,3] return True
# e.g. lst[1,2,4,6,1,4,3,7], ptrn=[1,2,3] return False
def is_pattern_in_a_list(lst, ptrn):
if ptrn[0] in lst:
idx = lst.index(ptrn[0])
for i in range(1, len(ptrn)):
if idx + i < len(lst):
if ptrn[i] != lst[idx+i]:
return False
else:
return False
return True
else:
return False
# counting horizontal occurances
count_h = 0
for row in lista:
if is_pattern_in_a_list(row, ptrn):
count_h += 1
# counting vertical occurances
# we first transpose the 2d array and use the same
# method of counting horizontal occurances.
def transpose_2d_array(a):
return [[a[j][i] for j in range(len(a))] for i in range(len(a[0]))]
lista_transpose = transpose_2d_array(lista)
count_v = 0
for row in lista_transpose:
if is_pattern_in_a_list(row, ptrn):
count_v += 1
# for diagonal occurances first we need to extract the diagonals
# with len >= len(ptrn).
# diagonals for the upper right triangle of the matrix:
count_d = 0
for i in range(len(lista[0])):
diag = []
j = 0
k = i
while j < len(lista)-i and k < len(lista[0]):
diag.append(lista[j][k])
j += 1
k += 1
if is_pattern_in_a_list(diag, ptrn):
count_d += 1
# diagonals for the lower left triangle of the matrix
i = len(lista) - 1
while i >= 1:
j = i
k = 0
diag = []
while j < len(lista) and k <= len(lista)+1-i:
diag.append(lista[j][k])
j += 1
k += 1
i -= 1
if is_pattern_in_a_list(diag, ptrn):
count_d += 1
print(diag)
print("Horizontal %d" % count_h)
print("Vertical %d" % count_v)
print("Diagonal %d" % count_d)

Path finding: A star not same length from A to B than from B to A

I am implementing the A star algorithm with the Manhattan distance for the 8 puzzle. [ The solution is in spiral form]
1 2 3
8 0 4
7 6 5
In some case, going from A to B will not take the same number of steps as going from B to A.
I think this is because it does not pick the same state on the open list, when they have the same cost, thus, not expanding the same nodes.
From
7 6 4
1 0 8
2 3 5
(A -> B)
7 6 4
1 8 0
2 3 5
(B -> A)
7 6 4
1 3 8
2 0 5
Which both have the same value using Manhattan distance.
Should I explore all path with the same value?
Or should I change the heuristic to have some kind of tie-breaker?
Here is the relevant part of the code
def solve(self):
cost = 0
priority = 0
self.parents[str(self.start)] = (None, 0, 0)
open = p.pr() #priority queue
open.add(0, self.start, cost)
while open:
current = open.get()
if current == self.goal:
return self.print_solution(current)
parent = self.parents[str(current)]
cost = self.parents[str(current)][2] + 1
for new_state in self.get_next_states(current):
if str(new_state[0]) not in self.parents or cost < self.parents[str(new_state[0])][2]:
priority = self.f(new_state) + cost
open.add(priority, new_state[0], cost)
self.parents[str(new_state[0])] = (current, priority, cost)
After wasting so much time re-writing my "solve" function many different ways, for nothing,
I finally found the problem.
def get_next_states(self, mtx, direction):
n = self.n
pos = mtx.index(0)
if direction != 1 and pos < self.length and (pos + 1) % n:
yield (self.swap(pos, pos + 1, mtx),pos, 3)
if direction != 2 and pos < self.length - self.n:
yield (self.swap(pos, pos + n, mtx),pos, 4)
if direction != 3 and pos > 0 and pos % n:
yield (self.swap(pos, pos - 1, mtx),pos, 1)
if direction != 4 and pos > n - 1:
yield (self.swap(pos, pos - n, mtx),pos, 2)
It was in this function. The last if used to be "if 4 and pos > n:"
So there were unexplored states..
2 days for a "-1"
It will teach me to do more unit testing

Need to decrease each list element by 1 from an existing list and append it to a new list

Here is the code I need help with:
import random
def GetUserInput():
numStacks = int(input("Enter an integer between 1 and 45 (inclusive): "))
while numStacks < 1 or numStacks > 45:
print("Number is invalid.")
return numStacks
createInitialStacks(numStacks)
def createInitialStacks(numStacks):
print("Number of stacks:", numStacks)
stacks = []
cards = 45
for card in range(numStacks - 1):
value = random.randint(1, (cards + 1) - numStacks)
stacks.append(value)
numStacks -= 1
cards -= value
stacks.append(cards + 1 - numStacks)
print("Stack =",stacks)
def playRound(stacks):
stacksResult = []
stacksResult = [x-1 for x in stacks if x > 1]
print("New Stack =",stacksResult)
Here is my output:
Enter an integer between 1 and 45 (inclusive): 4
Number of stacks: 4
Stack = [6, 30, 4, 5]
The output should look like this:
Enter an integer between 1 and 45 (inclusive): 4
Number of stacks: 4
Stack = [6, 30, 4, 5]
New Stack = [5, 29, 3, 4]
Also, if there are any zeros in the new stack, they need to be removed.
stacksResult = [x-1 for x in stacks if x > 1]

Resources