Skip to content

Commit de45ecc

Browse files
authored
Add files via upload
1 parent e1783c6 commit de45ecc

8 files changed

+360
-0
lines changed
103 KB
Binary file not shown.

ProgrammingAssignment2.pdf

80 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
__author__ = 'Antonio Norelli'
2+
3+
#CORSO DI ALGORITMI E STRUTTURE DATI 2016
4+
#esPROG1
5+
#STABLE MARRIAGE
6+
7+
###############################################################################
8+
9+
import sys
10+
orig_stdout = sys.stdout #servira' per stampare su file
11+
12+
#acquisizione dati in due dizionari
13+
14+
men_pref = {}
15+
wmen_pref = {}
16+
men_status = {}
17+
wmen_status = {}
18+
19+
with open('men.txt') as f:
20+
n_men = int(f.readline())
21+
for man in range(n_men):
22+
rank_man = map(int, f.readline().split())
23+
id_m = rank_man.pop(0)
24+
men_pref[id_m] = rank_man
25+
men_status[id_m] = 0 #libero
26+
27+
with open('women.txt') as f:
28+
n_wmen = int(f.readline())
29+
for wman in range(n_wmen):
30+
rank_wman = map(int, f.readline().split())
31+
id_w = rank_wman.pop(0)
32+
wmen_pref[id_w] = rank_wman
33+
wmen_status[id_w] = 0
34+
35+
#algoritmo
36+
37+
38+
def matching(men_pref, men_status, wmen_pref, wmen_status):
39+
while 0 in men_status.values(): #finche' ci sono uomini liberi
40+
for m in men_pref: #scansione uomini
41+
if men_status[m] == 0: #se libero
42+
for w in men_pref[m]: #scansione della sua lista di preferenze
43+
if wmen_status[w] == 0: #se la donna e' libera
44+
men_status[m] = w #match
45+
wmen_status[w] = m
46+
break #smetti di scorrere la lista di preferenze
47+
else: #se la donna non e' libera
48+
if wmen_pref[w].index(wmen_status[w]) > wmen_pref[w].index(m): #se preferisce questo uomo a quello con cui sta
49+
men_status[wmen_status[w]] = 0 #l'uomo con cui sta torna libero
50+
wmen_status[w] = m #match
51+
men_status[m] = w
52+
break #smetti di scorrere la lista di preferenze
53+
return men_status
54+
55+
def output(dict_couples):
56+
f = file('marriage.txt', 'w')
57+
sys.stdout = f
58+
for i in dict_couples:
59+
print i, '\t', dict_couples[i]
60+
61+
62+
#esecuzione
63+
64+
65+
output(matching(men_pref, men_status, wmen_pref, wmen_status))
66+
67+
68+
69+
70+
71+
72+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
__author__ = 'Antonio Norelli'
2+
3+
#CORSO DI ALGORITMI E STRUTTURE DATI 2016
4+
#esPROG2
5+
#STRONGLY CONNECTED COMPONENTS
6+
7+
###############################################################################
8+
9+
10+
#acquisizione dati e costruzione del grafo inverso
11+
12+
13+
import sys
14+
orig_stdout = sys.stdout #servira' per stampare su file
15+
16+
graph = {}
17+
node_v = {} #valore nodo: 0 se non visitato 1 se visitato n<0 postnumber
18+
inv_graph = {} #grafo inverso
19+
inv_node_v = {}
20+
21+
with open('graph.txt') as f: #acquisizione grafo su dizionario
22+
n_nodes = int(f.readline())
23+
for node in range(n_nodes):
24+
reachable_nodes = map(int, f.readline().split())
25+
id_n = reachable_nodes.pop(0)
26+
graph[id_n] = set(reachable_nodes)
27+
inv_graph[id_n] = set() #inizializzazione grafo inverso, valore nodi grafo e grafo inverso
28+
node_v[id_n] = 0
29+
inv_node_v[id_n] = 0
30+
31+
for node in graph: #costruzione grafo inverso
32+
for reachable in graph[node]:
33+
inv_graph[reachable].add(node)
34+
35+
36+
#funzione depth first search
37+
38+
39+
def dfs(graph, start, node_v):
40+
global clock #variabile globale per il postnumber
41+
global stack #variabile globale con l'insieme dei nodi visitati in una dfs
42+
node_v[start] = 1 #marcato come visitato
43+
for node in graph[start]: #per ogni nodo raggiungibile
44+
if node_v[node] == 0: #se non visitato
45+
dfs(graph, node, node_v) #esegui una dfs
46+
node_v[start] = clock #postnumber quando si blocca la dfs
47+
stack.append(start)
48+
clock -= 1
49+
return node_v
50+
51+
52+
#dfs sul grafo inverso per ottenere la lista ordinata rev_rank su cui eseguire la seconda dfs
53+
54+
55+
clock = -1
56+
rev_rank = []
57+
for node in graph:
58+
if inv_node_v[node] == 0:
59+
stack = [] #inizializzazione stack
60+
inv_node_v = dfs(inv_graph, node, inv_node_v)
61+
rev_rank.extend(stack) #costruzione del rank (inverso)
62+
63+
clock = -1
64+
group = {} #componenti fortemente connesse
65+
rank_comp = 0 #rank componente = max of postnumbers = postnumber of start in the dfs
66+
component = [] #inizializzazione rank e componente
67+
68+
for node in reversed(rev_rank): #seconda dfs
69+
if node_v[node] == 0: #se non visitato
70+
stack = [] #inizializzazione variabile
71+
node_v = dfs(graph, node, node_v)
72+
rank_comp = node_v[node]
73+
group[-rank_comp] = stack #memorizzazione delle scc
74+
75+
76+
#output
77+
78+
79+
f = file('scc.txt', 'w')
80+
sys.stdout = f
81+
print len(group)
82+
for component in sorted(group, reverse=True):
83+
print str(group[component])[1:-1]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
__author__ = 'Antonio Norelli'
2+
3+
#I build a dictionary with the sorted strings (EX. hte -> eht) as keys
4+
#every key is associated to a list with all the anagrams in the input_string of the key
5+
#I scan the dictonary and I append every item of every list to the result
6+
7+
#COST n = number of strings, m = average lenght of a string
8+
#build the dictionary: O(n*m*log(m)) (sort letters of every string in alphabetical order)
9+
#value of a key is computable in O(1) because dict is implemented in python as hash table
10+
#assemble the result: O(n*log(n)) if alphabetical order is necessary (sort dict O(n*log(n)), scan dict O(n))
11+
# O(n) if alphabetical order is not necessary
12+
#total = O(n*m*log(m)) if alphabetical order is not necessary
13+
# O(MAX(n*m*log(m), n*log(n))) if alphabetical order is necessary
14+
15+
#................................................................................................................
16+
17+
#SAMPLE INPUT
18+
19+
input_strings = ['ab', 'ciao', 'the', 'iaoc', 'caio', 'ot', 'hte', 'ba', 'ab', 'go']
20+
21+
#PROGRAM
22+
23+
def sort_by_anagrams(list_of_strings):
24+
dict_of_anagrams = {}
25+
for string in list_of_strings:
26+
sorted_string = ''.join(sorted(string))
27+
if sorted_string in dict_of_anagrams:
28+
dict_of_anagrams[sorted_string].append(string)
29+
else:
30+
dict_of_anagrams[sorted_string] = [string]
31+
result = []
32+
for anagram in sorted(dict_of_anagrams): #if alphabetical order is not necessary delete this and next sorted call
33+
for string in sorted(dict_of_anagrams[anagram]):
34+
result.append(string)
35+
return result
36+
37+
print sort_by_anagrams(input_strings)
38+
39+
40+
41+
42+
43+
44+
45+
46+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
__author__ = 'Antonio Norelli'
2+
3+
#I create a new class using a list of lists and performing operations with built-in function append(item) and pop()
4+
#I have two values to use properly the SetOfStacks:
5+
#item_last_stack (# of item in the last stack) and stack (index of currently stack)
6+
7+
#COST all single operations are O(1),
8+
#I think python compiler memorizes the size of every list and do in O(1) also append(item) and len(list)
9+
10+
#................................................................................................................
11+
12+
#PROGRAM
13+
14+
class SetOfStacks(object):
15+
def __init__(self, threshold): #threshold included in the declaration
16+
self.threshold = threshold
17+
self.set = [[]]
18+
self.item_last_stack = 0
19+
self.stack = 0
20+
def push(self, item):
21+
if self.item_last_stack < self.threshold: #if last stack isn't full
22+
self.set[self.stack].append(item)
23+
self.item_last_stack += 1
24+
else:
25+
self.stack += 1
26+
self.set.append([]) #create a new stack
27+
self.set[self.stack].append(item)
28+
self.item_last_stack = 1
29+
def pop(self): #possible situation: [[], [0,1], [], []] before pop we have to delete the last two empty stacks
30+
while self.item_last_stack == 0: #while the last stack is empty
31+
del self.set[-1] #delete last stack
32+
self.stack -= 1
33+
self.item_last_stack = len(self.set[self.stack])
34+
self.item_last_stack -= 1
35+
return self.set[self.stack].pop()
36+
def popAt(self, index):
37+
if self.stack < index:
38+
print 'Sorry, but this stack does not exist'
39+
if len(self.set[index]) == 0:
40+
print 'This stack is empty'
41+
else:
42+
return self.set[index].pop()
43+
44+
#SAMPLE INPUT AND USE
45+
46+
sample = SetOfStacks(3)
47+
48+
for i in range(10):
49+
sample.push(i)
50+
print 'Sample SetOfStacks: ', sample.set, '\n'
51+
52+
print 'pop five times on sub-stack 1 \nrunning...'
53+
for i in range(5):
54+
sample.popAt(1)
55+
print '... \nresult: ', sample.set, '\n'
56+
57+
print 'push new item 42'
58+
sample.push(42)
59+
print 'result: ', sample.set, '\n'
60+
61+
print 'pop six times'
62+
for i in range(6):
63+
sample.pop()
64+
print 'result: ', sample.set
65+
66+
67+
68+
69+
70+
71+
72+
73+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
__author__ = 'Antonio Norelli'
2+
3+
#Assuming binary tree stored in an array where the father of array[i] is array[int((array[i]-1)/2))]:
4+
#EXAMPLE: array = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
5+
#indexes of array = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10]
6+
#A father of B, C; B father of D, E; C father of F, G...
7+
8+
#COST O(log(n)) where n is the lenght of the array
9+
10+
#................................................................................................................
11+
12+
#SAMPLE INPUT
13+
14+
input_alb_bin = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
15+
input_node_a = 'H'
16+
input_node_b = 'D'
17+
18+
#PROGRAM
19+
20+
def find_index(alb_bin, node_a, node_b): #find indexes of two nodes in input
21+
index_a = alb_bin.index(node_a)
22+
index_b = alb_bin.index(node_b)
23+
return [index_a, index_b]
24+
25+
def find_ancestor(indexes): #indexes = [index_a, index_b]
26+
while True:
27+
if indexes[0] < indexes[1]: #change deeper node with his father
28+
indexes[1] = int((indexes[1]-1)/2)
29+
elif indexes[1] < indexes[0]:
30+
indexes[0] = int((indexes[0]-1)/2)
31+
else: #if the two nodes are the same, return one of them
32+
return indexes[0]
33+
34+
print 'common ancestor is:', input_alb_bin[find_ancestor(find_index(input_alb_bin, input_node_a, input_node_b))]
35+
36+
37+
38+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
__author__ = 'Antonio Norelli'
2+
3+
#Take the total, you have at least one solution with:
4+
#0 coin of the largest size... i coins of the largest size... q coins of the largest size where q=int(total/(largest size))
5+
#now for every combination from 0 to q coins of the largest size, remaining are total-i*(largest size)=total'
6+
#and you have at least one solution with:
7+
#0 coin of the second largest size... i coins of the second largest size... q' coins of the second largest size
8+
# where q'=int(total'/(second largest size))
9+
#and so on
10+
#when your total' is 0 or you are working with the smallest size there is only one solution
11+
#and you add it to the global variable result
12+
13+
#COST there are at least k calls of the recursive function where k=result
14+
#An upperbound for the result is n*(n/5)*(n/10)*(n/25)
15+
#It's impossible to have a solution with more than n pennies, n/5 nikels, n/10 dimes, n/25 quarters...
16+
#So the cost is O(n^4)
17+
18+
#................................................................................................................
19+
20+
#SAMPLE INPUT
21+
22+
cents = 100
23+
24+
#PROGRAM
25+
26+
#cicli = 0 #use the commented lines if you want the number of calls of combination function
27+
28+
sizes = [1, 5, 10, 25]
29+
result = 0
30+
31+
def combinations(remaining, j): #j is the index of the actual coin size
32+
global sizes
33+
global result
34+
35+
#global cicli
36+
#cicli += 1
37+
38+
current_value = sizes[j]
39+
if remaining == 0 or j == 0: #if remaining is 0 or you are working with the smallest size there is only one solution
40+
result += 1
41+
return
42+
for i in range(int(remaining/current_value)+1): #at least one solution with i coins of the current value
43+
combinations(remaining-i*current_value, j-1) #recall the function with remaining and next smaller coin value
44+
45+
combinations(cents, len(sizes)-1)
46+
print 'number of ways of representing', cents, 'cents:', result
47+
48+
#print cicli

0 commit comments

Comments
 (0)