We've been given standard beginner's python problem as a homework exercise, but my research into it shows people always use Networkx to solve these graph type node problems, whereas we're not allowed to use the Networkx built-in to solve it. I'm hoping for advice on a nice way to tackle this please.
There are five nodes (named 1,2,3,4,5) and the order is this:
1 goes nowhere
2 only goes to 1
3 goes to 1 and 5 (but 5 is closer which makes the 3 to 1 path redundant)
4 goes to 1 and 2 (but 2 is closer so 4-1 is redundant)
5 goes to 2
This is the example data to read in (note this is just one data set - it has to work with other pairs too):
['R(3,5)', 'R(4,2)', 'R(5,2)', 'R(2,1)', 'R(3,1)', 'R(4,1)']
This is the non-redundant pair output:
['R(3,5)', 'R(4,2)', 'R(5,2)', 'R(2,1)']
My attempt so far has been to split into two lists for start node and end node:
start_value = []
end_value = []
for i in range(len(partial_order)):
start_value.append(int(partial_order[i][2]))
for i in range(len(partial_order)):
end_value.append(int(partial_order[i][4]))
dictionary = dict(zip(start_value, end_value))
Output:
[3, 4, 5, 2, 3, 4]
[5, 2, 2, 1, 1, 1]
{3: 1, 4: 1, 5: 2, 2: 1}
I thought if I put it into a dictionary, I can try something from there, but my dictionary only shows 3:1 instead of 3:[1,5]. It is the 3-5 pair that I need to keep since it is closer, so 3-1 is redundant. Thanks for any tips on how to progress without Networkx.
This is one of pages I was reading - I'm trying to set up graph dictionary like that so I can try out their find_shortest_path function, to see if that gives me a solution.
https://www.python.org/doc/essays/graphs/
UPDATE:
I ended up abandoning the dictionary idea and zipping the two lists together then performed a whole bunch of if statements to get it working.
But I really would like to hear anyone's solution for something more Pythonic (so long as it doesn't use packages like Networkx). Happy coding.
Related
I have some problems with this task:
write in recursive functions which (NOTE: you can't use loops.):
3.1 Will display on the screen the common part of two sorted arrays
3.2 Will write the back of the word/array on the screen
Right now I have rest of the exercise:
firstArray = [1, 2, 3, 4, 5]
secondArray = [4, 5, 6, 7, 8]
#1 function - print first element
def printFirstElement():
firstElemenet = firstArray[0]
print(firstElemenet)
printFirstElement()
#2 function - print all without first element
def printAllWithouthFirstElemenet():
arrayWithoutFirstElement = firstArray[1:]
print(arrayWithoutFirstElement)
printAllWithouthFirstElemenet()
#3 functin - return information if array is empty
def checkArrayEmptiness():
if firstArray:
print("Array has somehting")
else:
print("Array is empty")
checkArrayEmptiness()
##rest code should be here
I really don't have idea what I could write more, someone could help me?
Edit 1
Without ready-made solutions
You can use python set.
Something like:
print(set(firstArray).intersection(secondArray))
In most cases it will be smart to use Python built in solutions, as they are more efficient for the general case.
But, in case you do need it, try looking at this duplicate question: Finding List Intersection using Python List Slices & recursion
I was playing around in python. I used the following code in IDLE:
p = [1, 2]
p[1:1] = [p]
print p
The output was:
[1, [...], 2]
What is this […]? Interestingly I could now use this as a list of list of list up to infinity i.e.
p[1][1][1]....
I could write the above as long as I wanted and it would still work.
EDIT:
How is it represented in memory?
What's its use? Examples of some cases where it is useful would be helpful.
Any link to official documentation would be really useful.
This is what your code created
It's a list where the first and last elements are pointing to two numbers (1 and 2) and where the middle element is pointing to the list itself.
In Common Lisp when printing circular structures is enabled such an object would be printed as
#1=#(1 #1# 2)
meaning that there is an object (labelled 1 with #1=) that is a vector with three elements, the second being the object itself (back-referenced with #1#).
In Python instead you just get the information that the structure is circular with [...].
In this specific case the description is not ambiguous (it's backward pointing to a list but there is only one list so it must be that one). In other cases may be however ambiguous... for example in
[1, [2, [...], 3]]
the backward reference could either point to the outer or to the inner list.
These two different structures printed in the same way can be created with
x = [1, [2, 3]]
x[1][1:1] = [x[1]]
y = [1, [2, 3]]
y[1][1:1] = [y]
print(x)
print(y)
and they would be in memory as
It means that you created an infinite list nested inside itself, which can not be printed. p contains p which contains p ... and so on. The [...] notation is a way to let you know this, and to inform that it can't be represented! Take a look at #6502's answer to see a nice picture showing what's happening.
Now, regarding the three new items after your edit:
This answer seems to cover it
Ignacio's link describes some possible uses
This is more a topic of data structure design than programming languages, so it's unlikely that any reference is found in Python's official documentation
To the question "What's its use", here is a concrete example.
Graph reduction is an evaluation strategy sometime used in order to interpret a computer language. This is a common strategy for lazy evaluation, notably of functional languages.
The starting point is to build a graph representing the sequence of "steps" the program will take. Depending on the control structures used in that program, this might lead to a cyclic graph (because the program contains some kind of "forever" loop -- or use recursion whose "depth" will be known at evaluation time, but not at graph-creation time)...
In order to represent such graph, you need infinite "data structures" (sometime called recursive data structures), like the one you noticed. Usually, a little bit more complex though.
If you are interested in that topic, here is (among many others) a lecture on that subject: http://undergraduate.csse.uwa.edu.au/units/CITS3211/lectureNotes/14.pdf
We do this all the time in object-oriented programming. If any two objects refer to each other, directly or indirectly, they are both infinitely recursive structures (or both part of the same infinitely recursive structure, depending on how you look at it). That's why you don't see this much in something as primitive as a list -- because we're usually better off describing the concept as interconnected "objects" than an "infinite list".
You can also get ... with an infinitely recursive dictionary. Let's say you want a dictionary of the corners of a triangle, where each value is a dictionary of the other corners connected to that corner. You could set it up like this:
a = {}
b = {}
c = {}
triangle = {"a": a, "b": b, "c": c}
a["b"] = b
a["c"] = c
b["a"] = a
b["c"] = c
c["a"] = a
c["b"] = b
Now if you print triangle (or a or b or c for that matter), you'll see it's full of {...} because any two corners are referring to back to each other.
As I understood, this is an example of fixed point
p = [1, 2]
p[1:1] = [p]
f = lambda x:x[1]
f(p)==p
f(f(p))==p
I'm a beginner in python coding and am trying to figure out how to test the stability of the Gale-Shapley Algorithm. I understand that for a stable pairing to be made, this means that there's no situation whereby there's 2 people who prefers each other over their assigned partner.
The data of participants' preferences is as follows:
preference = [["boy1",1,3,2,4], ["boy2",1,2,4,3],["boy3",1,2,3,4],["boy4",2,3,1,4],["girl1",2,1,3,4],["girl2",4,3,2,1],["girl3",1,2,3,4],["girl4",3,4,2,1]]
For example, for preference[0], boy1's ranking for girl1 is 1, girl2 is 3, girl3 is 2, girl 4 is 4. This means that the list goes: ["boy1", (ranking of girl1), (ranking of girl2), (ranking of girl3), (ranking of girl 4)].
An example of a solution of pairings is as follows:
solution1 = [["boy1","girl1"],["boy2","girl3"],["boy3","girl2"],["boy4","girl4"]
I'm trying to come up with a function that produces true if solution is stable and false if the solution isn't stable, given the preference, solution and number of couples.
I've tried using pandas and numpy but I keep getting stuck with many for loops and if and problems with indexing as I'm not very familiar with any of these python libraries. I'm now trying to go back to basic and see if it's possible to do it. However, as I'm doing it, I realize that I kept using for loops and it won't be as efficient. Below is my incomplete code, please do advise on what I should do to improve the efficiency of this incomplete code - and if it's possible to execute my current incomplete code once it's complete. Please do suggest any python libraries that I can use too, any suggestions are greatly appreciated!
def teststability(n, preference, solution):
for i in solution[i]:
fpo = solution[i][1][1]
for j in preference[j]:
if solution[i][0] == preference[j][0]:
rank = preference[j][fpo]
if rank == 1:
continue
else:
for k in pref[j][k]:
if pref[j][k] < rank:
lst.append("girl"+str(k))
else:
continue
You don't Pandas or Numpy for this, as it's a classic algorithmic SAT problem, and not one of data. (If you need to apply a given solution algorithm to a large array of pairs, then Pandas might be useful.)
The algorithm is implemented in the QuantEcon/MatchingMarkets package.
Lastly, I'd note that it's a little confusing that you're using lists made of strings and integers. I'd suggest dict of male-to-female and female-to-male preferences, eg:
female_prefs = {1: [2, 1, 3, 4], 2: [4, 3, 2, 1], 3: [1, 2, 3, 4], 4: [3, 4, 2, 1]}
I was given a sample challenge question by one of my friends. I would like to hear some advice on how to best approach finding a solution.
The problem involves calculating all possible patterns of traversing a series of points on a grid-like scale. I will simply be given a number 'n' that represents how many times I must move, and I must determine the number of ways I can traverse the grid moving n times. The starting point can be any of the points so I must run my calculation on every starting point with my answer being the sum of the results of each starting point.
I am still a bit of a beginner is some regards to programming, and my best guess as to how to approach this problem is to use graph theory. I have started by creating a graph to represent the nodes as well as their neighbors. I am leaving this problem intentionally vague because I want to learn how to approach these kinds of problems rather than having some expert swoop in and simply solve the entire thing for me. Here is an example representation of my graph in Python 3 (a dictionary).
graph = {'a':['b','c']
'b':['a','e','f']
'c':['a','d']
'd':['c']
'e':['b','g'] and etc.
My real graph is significantly bigger with each node typically having at least 3-4 neighbors. Let's pretend the 'n' given is 6, meaning I need to return all possible valid paths that involve moving 6 times. I am allowed to revisit nodes, so a valid path could simply be a-b-a-b-a-b. Another example of a 'valid' path is a-b-a-c-d-c or e-b-a-c-a-b since we can start from any starting point.
I am at a bit of a loss as to how to best approach this problem. Recursion has crossed my mind as a possible solution where I traverse all possible paths and increment a counter each time I hit the 'end' of a path. Another possible solution I have considered is at each node, calculate the possible moves and multiply it with a running tally. For example, starting at 'a', I have two moves. If I navigate to 'b', I have 3 moves. If I navigate to 'c', I have 2 moves. At this point, I have 1*3*2 moves. This could be a completely wrong approach...just an idea I had.
The actual problem is a lot more complex with constraints for certain nodes (how many times you can visit it, rules against visiting it if a certain sequence of nodes were hit prior, etc.) but I will omit the details for now. What I will say is that given these constraints, my algorithm must know what the previous pattern of visited nodes was. At the 5th move, for example, I must be able to refer to the previous 4 moves at any time.
I would love to hear advice on how you would best approach solving the 'simpler' problem I outlined above.
Check out Depth First Search (DFS). Just off the top of my head: Use recursive DFS, use a counter for saving each node found after making 'n' moves. You would need to build an undirected graph representation of the given data, so that you could run the DFS algorithm on the graph.
Here's the simplest answer for the case you gave. Once you have you graph in the form of a "transition map" (which can just be a dictionary, like you've shown), then the following code will work:
def myDFS(trans_dict,start,length,paths,path=[]):
path=path+[start]
if len(path)==length:
paths.append(path)
else:
for node in trans_dict[start]:
myDFS(trans_dict,node,length,paths,path)
If you want the number of ways you can traverse the map with a path of a given length, then that would just be len(paths).
Example:
trans_dict = {0:[1,2],1:[2,3],2:[0,3],3:[3]}
paths = []
length = 3
for a in trans_dict:
myDFS(trans_dict,a,length,paths)
print paths # [[0, 1, 2], [0, 1, 3], [0, 2, 0], [0, 2, 3], [1, 2, 0], [1, 2, 3], [1, 3, 3], [2, 0, 1], [2, 0, 2], [2, 3, 3], [3, 3, 3]]
print len(paths) # 11
Answer was inspired by this Q&A: trying to find all the path in a graph using DFS recursive in Python
I was playing around in python. I used the following code in IDLE:
p = [1, 2]
p[1:1] = [p]
print p
The output was:
[1, [...], 2]
What is this […]? Interestingly I could now use this as a list of list of list up to infinity i.e.
p[1][1][1]....
I could write the above as long as I wanted and it would still work.
EDIT:
How is it represented in memory?
What's its use? Examples of some cases where it is useful would be helpful.
Any link to official documentation would be really useful.
This is what your code created
It's a list where the first and last elements are pointing to two numbers (1 and 2) and where the middle element is pointing to the list itself.
In Common Lisp when printing circular structures is enabled such an object would be printed as
#1=#(1 #1# 2)
meaning that there is an object (labelled 1 with #1=) that is a vector with three elements, the second being the object itself (back-referenced with #1#).
In Python instead you just get the information that the structure is circular with [...].
In this specific case the description is not ambiguous (it's backward pointing to a list but there is only one list so it must be that one). In other cases may be however ambiguous... for example in
[1, [2, [...], 3]]
the backward reference could either point to the outer or to the inner list.
These two different structures printed in the same way can be created with
x = [1, [2, 3]]
x[1][1:1] = [x[1]]
y = [1, [2, 3]]
y[1][1:1] = [y]
print(x)
print(y)
and they would be in memory as
It means that you created an infinite list nested inside itself, which can not be printed. p contains p which contains p ... and so on. The [...] notation is a way to let you know this, and to inform that it can't be represented! Take a look at #6502's answer to see a nice picture showing what's happening.
Now, regarding the three new items after your edit:
This answer seems to cover it
Ignacio's link describes some possible uses
This is more a topic of data structure design than programming languages, so it's unlikely that any reference is found in Python's official documentation
To the question "What's its use", here is a concrete example.
Graph reduction is an evaluation strategy sometime used in order to interpret a computer language. This is a common strategy for lazy evaluation, notably of functional languages.
The starting point is to build a graph representing the sequence of "steps" the program will take. Depending on the control structures used in that program, this might lead to a cyclic graph (because the program contains some kind of "forever" loop -- or use recursion whose "depth" will be known at evaluation time, but not at graph-creation time)...
In order to represent such graph, you need infinite "data structures" (sometime called recursive data structures), like the one you noticed. Usually, a little bit more complex though.
If you are interested in that topic, here is (among many others) a lecture on that subject: http://undergraduate.csse.uwa.edu.au/units/CITS3211/lectureNotes/14.pdf
We do this all the time in object-oriented programming. If any two objects refer to each other, directly or indirectly, they are both infinitely recursive structures (or both part of the same infinitely recursive structure, depending on how you look at it). That's why you don't see this much in something as primitive as a list -- because we're usually better off describing the concept as interconnected "objects" than an "infinite list".
You can also get ... with an infinitely recursive dictionary. Let's say you want a dictionary of the corners of a triangle, where each value is a dictionary of the other corners connected to that corner. You could set it up like this:
a = {}
b = {}
c = {}
triangle = {"a": a, "b": b, "c": c}
a["b"] = b
a["c"] = c
b["a"] = a
b["c"] = c
c["a"] = a
c["b"] = b
Now if you print triangle (or a or b or c for that matter), you'll see it's full of {...} because any two corners are referring to back to each other.
As I understood, this is an example of fixed point
p = [1, 2]
p[1:1] = [p]
f = lambda x:x[1]
f(p)==p
f(f(p))==p