Bad Selection Sort in Python - python

I have a problem with a simple sort of a multidimensional array.
The Python code is:
SelectionSort.py
class SelectionSort(object):
#staticmethod
def sort(list):
for i in range(0, len(list)):
min = i;
for j in range (i+1, len(list)):
if j < list[min]:
min = j;
tmp = list[min];
list[min] = list[i];
list[i] = tmp;
return list;
MatriceSelectionSort.py
import sys;
import traceback;
import re;
from SelectionSort import SelectionSort;
class MatriceSelectionSort(object):
def run(self):
if len(sys.argv) < 2:
print("Missing fileName arg! Examplu de rulare: python MatriceSelectionSort C:\\wsmt\\matrice.txt\n");
sys.exit(1);
fileName = sys.argv[1];
try:
matrix = self.readMatrix(fileName);
for row in matrix:
SelectionSort.sort(row);
self.writeResult(fileName, matrix);
except Exception as e:
print("Nu pot citi/parsa fisierul\n");
traceback.print_exc();
def readMatrix(self, fileName):
matrix = [];
with open(fileName, "r") as file:
for line in file:
row = [];
tokens = re.split("\s+", line);
for token in tokens:
if token:
row.append(int(token));
matrix.append(row);
return matrix;
def writeResult(self, fileName, matrix):
with open(fileName, "a") as file:
file.write("\n\n"); # python will translate \n to os.linesep
for row in matrix:
for item in row:
file.write(str(item) + " ");
file.write("\n");
if __name__ == '__main__':
MatriceSelectionSort().run();
Matrice.txt
7 3 1 9 4
2 1 10 4 9
12 4 23
The problem is that the output of the file is:
(The sorted matrix should be at the end of the file, like this)
Matrice.txt
7 3 1 9 4
2 1 10 4 9
12 4 23
1 4 3 7 9
1 2 4 9 10
23 12 4
So, it's not like the best sort in the world..
I think the problem is in the SelectionSort.py file, I kind of messed up the "length[i]" and the "i" variables. I am a beginner, any help is appreciated!
Thank you!

sort method has a small bug in it, it's comparing loop counter j against minimum value. If you make the following change it will fix the issue:
def sort(list):
for i in range(0, len(list)):
min = i;
for j in range (i+1, len(list)):
if list[j] < list[min]: # Instead of if j < list[min]:
min = j
tmp = list[min]
list[min] = list[i]
list[i] = tmp
return list

Related

Which algorithms is enable to solve Tower Of Hanoi with 10 Disk

I've tried to use BFS to solve Tower of Hanoi (with smallest step) with 10 disks and you can put the disk wherever you want but it takes way too long and take so much memory. Do you guys have any suggestion?
Which algorithms should i use for this 10 disks cases and the disk are randomly initiated and you can put the disk wherever you want in the solving process?
My code:
class Node():
def __init__(self,matrix,parent):
self.matrix = matrix
self.parent = parent
def CreateNode(matrix,parent) -> Node:
new_mat = [nested[:] for nested in matrix]
newnode = Node(matrix,parent)
return newnode
def appender(matrix,i,query,gone,solution):
if matrix[i] != []:
for j in range(3):
if j != i:
temp = [nested[:] for nested in matrix]
temp[j].append(temp[i].pop(-1))
if ''.join(map(str,temp)) not in gone:
gone.add(''.join(map(str,temp)))
sub_solution = CreateNode(temp,solution)
query.append(sub_solution)
def printMatrix(mat):
for i in mat:
for j in i:
print(j,end=" ")
print()
print("#")
def PrintSolution(root):
if root == None:
return
PrintSolution(root.parent)
printMatrix(root.matrix)
def solver(A,list):
gone = set()
query = []
root = Node(A,None)
query.append(root)
while query:
solution = query.pop(0)
if solution.matrix[-1] == list:
PrintSolution(solution)
return
for i in range(3):
appender(solution.matrix,i,query,gone,solution)
A = []
for i in range(3):
arr = [int(i) for i in input().split()]
A.append(arr)
maxi = max(max(A))
list = []
for i in range(maxi,-1,-1):
list.append(i)
solver(A,list)
Example input :
6 9 0 1 2
4 7
3 5 8
Output:
6 9 0 1 2
4 7
3 5 8
#
6 9 0 1 2
4 7 8
3 5
#
6 9 0 1
4 7 8
3 5 2
#
etc until solved
I think this can quite help with your situation
def hanoi(n: int, fromPos: int, toPos: int, via: int) -> None:
if n == 1:
print("Move disk from pole %d to pole %d" % (fromPos, toPos)
else:
move(n - 1, fromPos, via, toPos)
move(1, fromPos, toPos, via)
move(n - 1, via, toPos, fromPos)

sequence of repeated values in a list

I have problems with a program, I hope someone can help me to fix this. Basically I have a random generated list with 20 values, and I want to place between brackets the values that are repeated (for example if the list is [1,2,2,4,5] it should display 1 ( 2 2 ) 4 5 )
Now here's my code that works only if there is no repeated value in the end, because the list index goes out of range. How can I fix this?
from random import randint
lanci = []
for i in range(20):
x = randint(1,6)
lanci.append(x)
print(lanci)
i=0
while i < len(lanci)-1):
if lanci[i] == lanci[i+1]:
print("(",end=" ")
print(lanci[i],end=" ")
while lanci[i]==lanci[i+1]:
i = i + 1
print(lanci[i],end=" ")
print(")",end=" ")
else:
print(lanci[i],end=" ")
i = i + 1
Alternatively to your more manual approach, you could use itertools.groupby to group equal values in the list and then enclose those in parens:
>>> import random, itertools
>>> lst = [random.randint(1, 5) for _ in range(20)]
>>> tmp = [list(map(str, g)) for k, g in itertools.groupby(lst)]
>>> ' '.join(g[0] if len(g) == 1 else "(" + " ".join(g) + ")" for g in tmp)
'5 4 1 2 1 4 (5 5) 4 5 1 5 4 3 (5 5) 3 (5 5 5)'
Not the pretiest but will do it:
from random import randint
from itertools import groupby
lanci = [randint(1,6) for _ in range(20)]
result = [tuple(v) for _, v in groupby(lanci)]
print(*[i[0] if len(i) == 1 else '('+' '.join(map(str, i))+')' for i in result], sep=' ')
#(2 2) 3 5 3 1 5 4 6 2 1 4 6 4 (5 5) 3 6 3 4
Just check for "last element" before your inner while loop.
from random import randint
lanci = []
for i in range(20):
x = randint(1,6)
lanci.append(x)
print(lanci)
i=0
while i < len(lanci)-1):
if lanci[i] == lanci[i+1]:
print("(",end=" ")
print(lanci[i],end=" ")
while (i+1 < len(lanci)) and (lanci[i]==lanci[i+1]):
i = i + 1
print(lanci[i],end=" ")
print(")",end=" ")
else:
print(lanci[i],end=" ")
i = i + 1
convert the list of number to a string then you can use this function.
split it if you need the list back again.
def add_brackets(string):
_character, _index = None, 0
_return_string = ''
for i, c in enumerate(string+ ' '):
if _character is None or _character != c :
if len(string[_index:i])>1:
_return_string+='(' + string[_index: i] + ')'
else:
_return_string+=string[_index: i]
_character, _index = c, i
return _return_string
This is another option using just basic list:
def group_consecutives(lst):
res, sub, memo = [None], [], None
lst.append(memo)
for x in lst:
if memo == x:
sub.append(memo)
if res[-1] != sub: res.append(sub)
else:
sub.append(memo)
if memo and not len(sub) > 1: res.append(memo)
memo, sub = x, []
return res[1:]
print(group_consecutives(lanci))

Write output of for loop in python

I am trying to write each iterated output of for loop for further operations.
Here is my code
#!/usr/bin/python
import io
from operator import itemgetter
with open('test.in') as f:
content = f.readlines()
content = [int(x) for x in content]
content = tuple(content)
nClus = input("Number of Clusters: ")
nEig = input("Number of eigen values: ")
j = 0
k = nClus + 1
content1 = ""
for i in range(1,k):
print content[j*(nEig+1):i*(nEig+1)]
j = j + 1
The file test.in looks like this (which is an example, actual test.in contains huge amount of data)
40
1
4
3
5
7
29
6
9
4
7
3
50
1
2
3
4
5
57
9
8
7
6
5
The values nClus = 4, nEig = 5.
Any suggestions on how to proceed?
Why not just save them to an array (mydata below)? I don't see where j stops (other_dimension, you can probably just delete it if you only have 1 dimension of results, I don't know your array size), but you can follow this format to get a numpy array to save data to:
import numpy as np
... [your code]
mydata = np.zeros([k,other_dimension]) // other_dimension only if you are saving a rectangular matrix of results instead of a vector
for i in range(1,k):
mydata[row, column] = content[j*(nEig+1):i*(nEig+1)] // put your iterators here for row, column if applicable (rectangular matrix), otherwise mydata[iterator]
print mydata[k, other_dimension] // other_dimension only if you are saving a rectangular matrix of results instead of a vector
j = j + 1

python 3*n + 1 - calculate longest cycle for a list of numbers

for a given list of numbers (input.txt) I'm trying to have an output.txt that prints out the numbers and the length of the cycle associated with each line.
So what i have till now:
/input.txt that looks kinda like this:
4 6
2 11
3 20
etc...
A function that calculates the length of the cycle:
def calc_cycle(number):
count = 1
while number != 1:
if number % 2 != 0:
number = number * 3 + 1
else:
number = number / 2
count = count + 1
return count
A function that calculates the maximum cycle:
def max_cycle(n, m):
max_value=1
for i in range(n, m+1):
x = calc_cycle(i)
if max_value < x:
max_value = x
return n, m, max_value
And a function that reads the input.txt file and parse the values:
def read_input(list_of_urls):
with open(list_of_urls) as f:
for line in f:
#n,m = [int(i) for i in line.split(' ')]
n,m = line.split(' ')
n=int(n)
m=int(m)
print n,m
Basically I'm stuck at this part, I don't see how to get an output.txt file that would look like this:
4 6 9 #9 being the max cycle for all the numbers between 4 and 9
2 11 20 #20 being the max cycle for all numbers between 2 and 11
3 20 21 #21 being the max cycle for numbers between 3 and 20
Any guidance please!?
string formating
def read_input(list_of_urls):
with open(list_of_urls) as f, open('output.txt', 'w+') as f2:
for line in f:
n,m = line.split(' ')
n=int(n)
m=int(m)
_,_,thisMaxCycle = max_cycle(n,m)
f2.write("{0} {1} {2} #{2} being the max cycle for all numbers between {0} and {1}\n".format(n,m,thisMaxCycle))

Efficient algorithm for counting unique elements in "suffixes" of an array

I was doing 368B on CodeForces with Python 3, which basically asks you to print the numbers of unique elements in a series of "suffixes" of a given array. Here's my solution (with some additional redirection code for testing):
import sys
if __name__ == "__main__":
f_in = open('b.in', 'r')
original_stdin = sys.stdin
sys.stdin = f_in
n, m = [int(i) for i in sys.stdin.readline().rstrip().split(' ')]
a = [int(i) for i in sys.stdin.readline().rstrip().split(' ')]
l = [None] * m
for i in range(m):
l[i] = int(sys.stdin.readline().rstrip())
l_sorted = sorted(l)
l_order = sorted(range(m), key=lambda k: l[k])
# the ranks of elements in l
l_rank = sorted(range(m), key=lambda k: l_order[k])
# unique_elem[i] = non-duplicated elements between l_sorted[i] and l_sorted[i+1]
unique_elem = [None] * m
for i in range(m):
unique_elem[i] = set(a[(l_sorted[i] - 1): (l_sorted[i + 1] - 1)]) if i < m - 1 else set(a[(l_sorted[i] - 1): n])
# unique_elem_cumulative[i] = non-duplicated elements between l_sorted[i] and a's end
unique_elem_cumulative = unique_elem[-1]
# unique_elem_cumulative_count[i] = #unique_elem_cumulative[i]
unique_elem_cumulative_count = [None] * m
unique_elem_cumulative_count[-1] = len(unique_elem[-1])
for i in range(m - 1):
i_rev = m - i - 2
unique_elem_cumulative = unique_elem[i_rev] | unique_elem_cumulative
unique_elem_cumulative_count[i_rev] = len(unique_elem_cumulative)
with open('b.out', 'w') as f_out:
for i in range(m):
idx = l_rank[i]
f_out.write('%d\n' % unique_elem_cumulative_count[idx])
sys.stdin = original_stdin
f_in.close()
The code shows correct results except for the possibly last big test, with n = 81220 and m = 48576 (a simulated input file is here, and an expected output created by a naive solution is here). The time limit is 1 sec, within which I can't solve the problem. So is it possible to solve it within 1 sec with Python 3? Thank you.
UPDATE: an "expected" output file is added, which is created by the following code:
import sys
if __name__ == "__main__":
f_in = open('b.in', 'r')
original_stdin = sys.stdin
sys.stdin = f_in
n, m = [int(i) for i in sys.stdin.readline().rstrip().split(' ')]
a = [int(i) for i in sys.stdin.readline().rstrip().split(' ')]
with open('b_naive.out', 'w') as f_out:
for i in range(m):
l_i = int(sys.stdin.readline().rstrip())
f_out.write('%d\n' % len(set(a[l_i - 1:])))
sys.stdin = original_stdin
f_in.close()
You'll be cutting it close, I think. On my admittedly rather old machine, the I/O alone takes 0.9 seconds per run.
An efficient algorithm, I think, will be to iterate backwards through the array, keeping track of which distinct elements you've found. When you find a new element, add its index to a list. This will therefore be a descending sorted list.
Then for each li, the index of li in this list will be the answer.
For the small sample dataset
10 10
1 2 3 4 1 2 3 4 100000 99999
1
2
3
4
5
6
7
8
9
10
The list would contain [10, 9, 8, 7, 6, 5] since when reading from the right, the first distinct value occurs at index 10, the second at index 9, and so on.
So then if li = 5, it has index 6 in the generated list, so 6 distinct values are found at indices >= li. Answer is 6
If li = 8, it has index 3 in the generated list, so 3 distinct values are found at indices >= li. Answer is 3
It's a little fiddly that the excercise numbers 1-indexed and python counts 0-indexed.
And to find this index quickly using existing library functions, I've reversed the list and then use bisect.
import timeit
from bisect import bisect_left
def doit():
f_in = open('b.in', 'r')
n, m = [int(i) for i in f_in.readline().rstrip().split(' ')]
a = [int(i) for i in f_in.readline().rstrip().split(' ')]
found = {}
indices = []
for i in range(n - 1, 0, -1):
if not a[i] in found:
indices.append(i+1)
found[a[i]] = True
indices.reverse()
length = len(indices)
for i in range(m):
l = int(f_in.readline().rstrip())
index = bisect_left(indices, l)
print length - index
if __name__ == "__main__":
print (timeit.timeit('doit()', setup="from bisect import bisect_left;from __main__ import doit", number=10))
On my machine outputs 12 seconds for 10 runs. Still too slow.

Categories

Resources