-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathKBNumber.java
More file actions
278 lines (250 loc) · 8.43 KB
/
KBNumber.java
File metadata and controls
278 lines (250 loc) · 8.43 KB
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.LinkedList;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
public class KBNumber {
private HashSet<String> vertexSet = new HashSet<String>();
private HashMap<String, ArrayList<String>> edgeToMovies = new HashMap<String, ArrayList<String>>();
private HashMap<String, HashSet<String>> nbdVertices = new HashMap<String, HashSet<String>>();
private HashSet<String> marked = new HashSet<String>();
private HashMap<String, String> backTrace = new HashMap<String, String>();
/**
* Constructor
*
* @param fileName The name of the file (e.g. "movies.txt")
*/
public KBNumber(String fileName) {
BufferedReader r = null;
String line = "";
try {
r = new BufferedReader(new FileReader(fileName));
line = r.readLine();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String [] split;
HashSet<String> actorsByLine = new HashSet<String>();
while(line != null){
split = line.split("/");
//First adds all the actors into a set
//Index from 1, since split[0] is the movie name
for(int i = 1; i < split.length; i++){
actorsByLine.add(split[i]);
}
//Adds all of the actors in the same movie as split[j] as neighboring vertices of split[j]
for(int j = 1; j < split.length; j++){
actorsByLine.remove(split[j]);
vertexSet.add(split[j]);
for(String actor : actorsByLine){
addToNbrVert(actor, split[j]);
addToEdges(actor, split[j], split[0]);
}
actorsByLine.add(split[j]);
}
actorsByLine.clear();
try {
line = r.readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//Creates the hashmap of vertices to their neighbors
private void addToNbrVert(String toAdd, String actorKey){
if(nbdVertices.containsKey(actorKey)){
nbdVertices.get(actorKey).add(toAdd);
} else {
HashSet<String> nbd = new HashSet<String>();
nbd.add(toAdd);
nbdVertices.put(actorKey, nbd);
}
}
//Creates the hashmap of edges to their movies
private void addToEdges(String toAdd, String actorKey, String movie){
Edge ed = new Edge(actorKey, toAdd);
if(edgeToMovies.containsKey(ed.toString())){
edgeToMovies.get(ed.toString()).add(movie);
} else {
ArrayList<String> movies = new ArrayList<String>();
edgeToMovies.put(ed.toString(), movies);
movies.add(movie);
}
}
/**
* Find the pair(s) of actors that cooperate in most movies, return the
* number of movies they have collaborated in
*
* @return the number of movies they have collaborated in
*/
public int mostCollaboration() {
int collabCount = 0;
int max = 0;
for(String edActors : edgeToMovies.keySet()){
collabCount = edgeToMovies.get(edActors).size();
if(collabCount > max){
max = collabCount;
}
}
return max;
}
/**
* Given the name of an actor, output a list of all other actors that he/she
* has been in a movie with
*
* @param actor
* The name of the actor
* @return A list of UNIQUE actor names in any order that actor has been in
* a movie with. Do not include the actor himself. In the case that
* an actor is in all movies alone, return an empty list.
* @throws IllegalArgumentException
* If the name of the actor is null or not contained in the
* graph
*/
public List<String> findCostars(String actor) throws IllegalArgumentException {
if(actor == null || !vertexSet.contains(actor)){
throw new IllegalArgumentException();
}
List<String> coStars = new ArrayList<String>();
HashSet<String> tempStars = new HashSet<String>();
tempStars = nbdVertices.get(actor);
//null --> no neighboring vertices
if(tempStars != null){
for(String vStr : tempStars){
coStars.add(vStr);
}
}
return coStars;
}
/**
* Implement a BFS on your graph to calculate the Kevin Bacon number of a
* given actor
*
* @param actor
* The name of the actor
* @return If actor is bacon, return 0; if bacon cannot be found from graph,
* return -1; else return bacon number
* @throws IllegalArgumentException
* If the name of the actor is null or not contained in the
* graph
*/
public int findBaconNumber(String actor) throws IllegalArgumentException {
if(actor == null || !vertexSet.contains(actor)){
throw new IllegalArgumentException();
}
int bNum = 0;
LinkedList<String> graphQ = new LinkedList<String>();
LinkedList<String> childrenPerLvl = new LinkedList<String>();
//Adds the actor to the queue, marks the actor so it is not traversed again
graphQ.offer(actor);
marked.add(actor);
while (graphQ.size() > 0){
String deq = graphQ.remove();
HashSet<String> childrenVert = nbdVertices.get(deq);
if(deq.equals("Bacon, Kevin")){
marked.clear();
return bNum;
} else if(childrenVert == null){
marked.clear();
return -1;
}
addToMaps(childrenVert, graphQ, childrenPerLvl, deq);
//Determines if we have finished checking one "level" of the tree for Kevin Bacon
//I.e., counts the edge depths
if(childrenPerLvl.toString() != null && childrenPerLvl.toString().equals(graphQ.toString())){
childrenPerLvl.clear();
bNum++;
}
}
marked.clear();
return -1;
}
//Adds child in childrenVertices to various necessary maps
private void addToMaps(HashSet<String> childrenVert, LinkedList<String> graphQ, LinkedList<String>
childrenPerLvl, String deq){
for(String childVer : childrenVert){
if(!isMarked(childVer)){
marked.add(childVer);
graphQ.offer(childVer);
backTrace.put(childVer, deq);
childrenPerLvl.offer(childVer);
}
}
}
//checks if the vertex is marked;
private boolean isMarked(String actor){
return marked.contains(actor);
}
/**
* Given the name of an actor, return a list of strings representing the
* path along your BFS from the given actor to Kevin Bacon, starting from
* the actor and following an actor->movie->actor->movie pattern.
*
* If two actors have appeared in multiple movies together, it does not
* matter which of those movies links them in the list.
*
* If there are multiple paths in the BFS from a given actor to Kevin Bacon,
* it does not matter which path is returned as long as it is accurate and
* there is no shorter path (i.e. your path provides the correct Bacon number).
*
* If the actor is Kevin Bacon, the list should contain one string (Bacon, Kevin) only.
*
* If there is no path to Kevin Bacon from the given actor, return null.
*
* @param actor
* The name of the actor
* @return A list of strings showing the path from actor to Kevin Bacon as
* strings alternating between actor and movie, starting from the
* original actor and ending at Bacon.
*
* example List (NOT A TEST CASE) for actor = "Damon, Matt": (Bacon
* number = 2)
*
* Damon, Matt
* The Informant! (2009)
* Pistor, Ludger
* X-Men: First Class (2011)
* Bacon, Kevin
*
* @throws IllegalArgumentException
* If the name of the actor is null or not contained in the
* graph
*/
public List<String> findBaconPath (String actor) throws IllegalArgumentException {
if(actor == null || !vertexSet.contains(actor)){
throw new IllegalArgumentException();
}
int bN = findBaconNumber(actor);
List<String> bPath = new ArrayList<String>();
if(bN == -1){
return null;
} else if (bN == 0){
bPath.add("Bacon, Kevin");
return bPath;
}
return backTrack(actor);
}
//Method written given that there exists a bacon path (i.e. "Bacon, Kevin" will be in the list)
//Makes a "backTracking" hashmap starting with Kevin Bacon as the key and parent nodes as values
public LinkedList<String> backTrack(String root){
LinkedList<String> back = new LinkedList<String>();
String firstActor = backTrace.get("Bacon, Kevin");
back.add("Bacon, Kevin");
back.offerFirst(edgeToMovies.get("Bacon, Kevin" + " " + firstActor).get(0));
String sndActor = "";
while(!firstActor.equals(root)){
back.offerFirst(firstActor);
sndActor = backTrace.get(firstActor);
back.offerFirst(edgeToMovies.get(firstActor + " " + sndActor).get(0));
firstActor = sndActor;
}
back.offerFirst(root);
return back;
}
}