Say I have a list of images ['1.jpg', '2.jpg', '3.jpg'...]
and a corresponding list of vertical sizes [200, 400, 300...]
I am trying to return all permutations of the list of images where the size lies within 10% of neighbouring elements. This is proving to be quite challenging!
I firstly tried itertools.permutations
on the entire list and then iterated over each element and checked for validity. This worked, but when n > 12
it obviously becomes quite slow, and it seems inefficient to generate so many invalid permutations from the outset.
I then realised that the order is not especially important, as the images will be shown in a loop, so I fixed the first element in the list, but this still required me to permute every element, so again, inefficient.
I then went searching for another approach, and decided to try this:
images = ['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg']
v_size = [100, 125, 110, 120, 95]
pairs = list(itertools.permutations(images,2))
This yielded a list of all possible pairings of images, which I could then validate and filter down to only pairs which met the +/- 10% criteria, so I was ultimately left with the following set of valid pairings meeting my criteria:
[('1.jpg', '3.jpg'), ('1.jpg', '5.jpg'), ('2.jpg', '4.jpg'), ('3.jpg', '1.jpg'), ('3.jpg', '4.jpg'), ('4.jpg', '2.jpg'), ('4.jpg', '3.jpg'), ('5.jpg', '1.jpg')]
Inspecting it, it seems to make sense. So images 1 and 3 can sit next to each other, and so can 3 and 4, 4 and 2 etc. So what I am looking to generate is a recombination of these to find all (if any) valid permutations of the original images. So for example:
['5.jpg', '1.jpg', '3.jpg', '4.jpg', '2.jpg']
Would be a valid arrangement, whereas:
['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg']
Would not, as the images sizes lie outside of 10% size constraint of each other.
I have considered recursion, but I am quite new to this and am not sure where to start.
Would appreciate any advice on how to solve this problem, as I have been trying for days!
This is a graph problem. Each node has a bidirectional edge to any node whose size is within 10%. Finding all permutations with your restrictions is isomorphic to finding all Hamiltonian paths in this graph.
First, you need to build the graph; use your favorite graph package or simpler representation. This pre-processing is necessarily a O(n^2), as the quantity of edges may be n(n-1)/2
. However, in practical cases, you can sort the list by size first, which should give you an effective O(n log n) sort and O(n) graph building, as there will be only a handful of connections from each node to its neighbors. For instance, in your given mini-example, I'll add another file, so we have:
# Before sorting
images = ['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg', '6.jpg']
v_size = [100, 125, 110, 120, 95, 102]
# After sorting
images = ['5.jpg', '1.jpg', '6.jpg', '3.jpg', '4.jpg', '2.jpg']
v_size = [95, 100, 102, 110, 120, 125]
From here, keep an upper-bound marker, mark
mark = 1
(index of 100) mark = 3
mark
. Check against 120, which is too far.Then you get to look up the algorithms available for an exhaustive traversal of the graph, i.e. a Hamiltonian path.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With