Find combinations that include required values - algorithm

I have a set of objects. I also have a set of required objects, containing between 0 and 3 objects. I'm trying to find all combinations of 3 objects from the initial set that include the required objects.
Edit: Example --
objects: {A,B,C,D,E}
required: {A}
output: {A,B,C}, {A,B,D}, {A,B,E}, {A,C,D}, {A,C,E}, {A,D,E}
objects: {A,B,C,D,E}
required: {A,B}
output: {A,B,C}, {A,B,D}, {A,B,E}
The obvious, but slow, solution is something like:
for(int i = 0; i < objects.size()-2 ; i++){
for(int j = i; j < objects.size()-1 ; j++){
for(int k = j; k < objects.size() ; k++){
if(required.contains(i) || required.contains (j) || required.contains(k)){
results.add(new Result(i,j,k));
}
}
}
}
This solution traverses the entire search space regardless of required objects.
Another approach I came up with was to write custom code for each number of required objects:
switch (required.size()){
case 3:
results.add(new Result(required));
break;
case 2:
Object a = requiredIngredients.toArray()[0];
Object b = requiredIngredients.toArray()[1];
for(Object o : objects){
if(!required.contains(i)){
results.add(new Result(EnumSet.of(o, a, b)));
}
}
break;
etc..
This works, but is obnoxious and not generalizable.
A third approach is to make three separate sets, shrinking sets to include only a required value if requirements are present, then iterate over them normally:
for(Object i : firstObjects){
for(Object j : secondObjects){
if(i == j) continue;
for(Object k : thirdObjects){
if(j == k) continue;
results.add(new Result(i,j,k));
}
}
}
This seems somewhat better, but produces duplicate combinations. Eg. It would return both ABC and ACB as two separate results. I could have the result set recognize duplicates, but I'd prefer not to calculate it to begin with.
Hopefully these examples make the problem clear. I feel like someone has figured out how to solve this kind of problem already, but I'm having a hard time identifying the generalized problem type.

Here is a simple and general way, but maybe not the most efficient (in python):
from itertools import combinations
def combinations_including(n,objects,required):
extra=objects-required
return sorted([sorted(tuple(required)+x) for x in combinations(extra,n-len(required))])
print combinations_including(3,set('ABCDE'),set('A'))
print combinations_including(3,set('ABCDE'),set('AB'))
outputs
[['A', 'B', 'C'], ['A', 'B', 'D'], ['A', 'B', 'E'], ['A', 'C', 'D'], ['A', 'C', 'E'], ['A', 'D', 'E']]
[['A', 'B', 'C'], ['A', 'B', 'D'], ['A', 'B', 'E']]
If the required set is small, then it is probably worse than brute force, but as the size of the required set increases, it will become much more efficient than brute force. For example, if the required set is the same as the input set, then it finds the answer in constant time.

Related

Compare two sorted arrays and find missing elements between them

I have two arrays that are lexically sorted:
Array1 is a kind of sorted superset of Array2 that is all the elements in Array2 will also be in Array1 but not vice versa.
Array1: [A,B,C,D,E,F,G]
Array2: [B,C,F]
Result: [A,D,E,G]
The result will have the missing elements not present in Array2 but in Array1.
I am looking for the best optimal solution.
One of my logic was to use a binary search but I am stuck thinking about how to implement it.
Any help on a correct algorithm would be great.
Edit: Duplicates are allowed.
This O(n) and can be achieved by iterating through the superset while keeping a pointer to the most recently matched element in the subset and noting which superset elements are absent from the subset.
An implementation in C#:
char[] superset = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
char[] subset = new char[] { 'B', 'C', 'F' };
List<char> missing = new List<char>();
int subIdx = 0;
foreach (var element in superset)
{
if (subIdx < subset.Length && subset[subIdx] == element)
subIdx++;
else
missing.Add(element);
}
var result = missing.ToArray(); // If you need an array rather than list

All ways to partition a string

I'm trying to find a efficient algorithm to get all ways to partition a string
eg for a given string 'abcd' =>
'a' 'bcd'
'a' 'b' 'cd'
'a' 'b' 'c' 'd'
'ab' 'cd'
'ab' 'c' 'd'
'abc' 'd'
'a', 'bc', 'd
any language would be appreciated
Thanks in advance !
Problem analysis
Between each pair of adjacent characters, you can decide whether to cut. For a string of size n, there are n-1 positions where you can cut or not, i.e. there are two possibilities. Therefore a string of size n can be partitioned in 2n-1 ways.
The output consists of 2n-1 partitions, each having n characters plus separators. So we can describe the output size as f(n) = 2n-1 * n + s(n) where s(n) ≥ 0 accounts for the partition separators and line separators.
So due to the output size alone, an algorithm solving this problem must have exponential runtime or worse: Ω(2n).
(0 ≤ c * 2n = ½ * 2n = 2n-1 ≤ 2n-1 * n ≤ f(n) for all n≥k with positive constants c=½, k=1)
Solution
I chose to represent a partition as integer. Each bit in cutpoints determines whether to cut between characters i and i+1. To iterate through all possible partitions, we just need to go trough all integers between 0 and 2^(n-1) - 1.
Example: For a string of length 4, we go through all integers between 0 and 2^3 - 1 or 0 and 7 or in binary: 000 and 111.
# (python 2 or 3)
def all_partitions(string):
for cutpoints in range(1 << (len(string)-1)):
result = []
lastcut = 0
for i in range(len(string)-1):
if (1<<i) & cutpoints != 0:
result.append(string[lastcut:(i+1)])
lastcut = i+1
result.append(string[lastcut:])
yield result
for partition in all_partitions("abcd"):
print(partition)
Memory usage:
I think my solution uses O(n) memory with Python 3. Only one partition is generated at a time, it's printed and not referenced anymore. This changes of course, if you keep all results, e.g. by storing them in a list.
In Python 2 replace range with xrange, otherwise all possible cutpoints will be stored in a list, therefore needing an exponential amount of memory.
JavaScript solution
// ES6 generator
function* all_partitions(string) {
for (var cutpoints = 0; cutpoints < (1 << (string.length - 1)); cutpoints++) {
var result = [];
var lastcut = 0;
for (var i = 0; i < string.length - 1; i++) {
if (((1 << i) & cutpoints) !== 0) {
result.push(string.slice(lastcut, i + 1));
lastcut = i + 1;
}
}
result.push(string.slice(lastcut));
yield result;
}
}
for (var partition of all_partitions("abcd")) {
console.log(partition);
}
Tested with NodeJS v4.4.3 (disclaimer: I have not used NodeJS before).
GeeksforGeeks has provided a well-explained solution to this problem:
For string abcd there will be 2^(n-1) i.e. 8 partitions.
(a)(b)(c)(d)
(a)(b)(cd)
(a)(bc)(d)
(a)(bcd)
(ab)(c)(d)
(ab)(cd)
(abc)(d)
(abcd)
The crux of the solution lies in the recursion to print all the permutations.
maintain two parameters – index of the next character to be processed and the output string so far. We start from index of next character to be processed, append substring formed by unprocessed string to the output string and recurse on remaining string until we process the whole string.
// Java program to find all combinations of Non-
// overlapping substrings formed from given
// string
class GFG
{
// find all combinations of non-overlapping
// substrings formed by input string str
static void findCombinations(String str, int index,
String out)
{
if (index == str.length())
System.out.println(out);
for (int i = index; i < str.length(); i++)
// append substring formed by str[index,
// i] to output string
findCombinations(str, i + 1, out +
"(" + str.substring(index, i+1) + ")" );
}
// driver program
public static void main (String[] args)
{
// input string
String str = "abcd";
findCombinations(str, 0, "");
}
}
Time Complexity is O(2^n)
Here's the link to the article: http://www.geeksforgeeks.org/print-ways-break-string-bracket-form/
I just wanted to post a simple recursive solution to this problem for anyone stumbling on this question. Probably not the best way, but this was way simpler for me to understand and implement. If I am wrong, please correct me.
def party(s:str, P:list, res:list) -> None :
"""Recursively generates all partitions of a given string"""
res.append(P+[s])
for i in range(1,len(s)):
party(s[i:],P+[s[:i]],res)
res = []
party("abcd",[],res)
print(res)
"""
[['abcd'], ['a', 'bcd'], ['a', 'b', 'cd'], ['a', 'b', 'c', 'd'],
['a', 'bc', 'd'], ['ab', 'cd'], ['ab', 'c', 'd'], ['abc', 'd']]
"""
It works as follows:
Given a string or a substring of it, we can split after each of its character creating two halves.
Say: "abc" can be partitioned into ["a","bc"], ["ab","c"]
We save the first part in a intermediate partition P and
recursively call party on the other half.
Because both halves together form a complete partition we save it to res.
Example:
initially: s = "abc" is a valid partition, save it to res.
recr call: s = "bc", P = ["a"] , so P +[s]= ["a","bc"] is also valid, save it to res.
Proceed with splitting "bc".
P = ["a","b"], s="c" so P + [s] is also valid. And so on..
recr call 3: s = "c", P = ["ab"], so P + [s] =["ab","c"] is also valid, save it to res
Working:
tests = ["abc","abcd","a"]
for t in tests:
res = []
party(t,[],res)
print(f'{t} -> {res} \n')
"""Output
abc -> [['abc'], ['a', 'bc'], ['a', 'b', 'c'], ['ab', 'c']]
abcd -> [['abcd'], ['a', 'bcd'], ['a', 'b', 'cd'], ['a', 'b', 'c', 'd'],
['a', 'bc', 'd'], ['ab', 'cd'], ['ab', 'c', 'd'], ['abc', 'd']]
a -> [['a']]
"""
This is a solution which minimizes developer time by taking advantage of a built-in iterator. It should be reasonably quick for problem sizes for which the answer itself is not infeasibly large.
There is a one-to-one correspondence between partitions of a string and subsets of potential cutpoints. If the length of the string is n then there are n-1 places where you could cut the string. A straightforward way would be to iterate through such subsets, and for each such subset, slice the string in that way. Here is a Python approach which uses the standard modules itertools:
import itertools
def multiSlice(s,cutpoints):
k = len(cutpoints)
if k == 0:
return [s]
else:
multislices = [s[:cutpoints[0]]]
multislices.extend(s[cutpoints[i]:cutpoints[i+1]] for i in range(k-1))
multislices.append(s[cutpoints[k-1]:])
return multislices
def allPartitions(s):
n = len(s)
cuts = list(range(1,n))
for k in range(n):
for cutpoints in itertools.combinations(cuts,k):
yield multiSlice(s,cutpoints)
For example:
>>> parts = allPartitions('World')
>>> for p in parts: print(p)
['World']
['W', 'orld']
['Wo', 'rld']
['Wor', 'ld']
['Worl', 'd']
['W', 'o', 'rld']
['W', 'or', 'ld']
['W', 'orl', 'd']
['Wo', 'r', 'ld']
['Wo', 'rl', 'd']
['Wor', 'l', 'd']
['W', 'o', 'r', 'ld']
['W', 'o', 'rl', 'd']
['W', 'or', 'l', 'd']
['Wo', 'r', 'l', 'd']
['W', 'o', 'r', 'l', 'd']
Note that this approach produces generates ['World'] as a partition of 'World'. This corresponds to slicing with an empty set of cut points. I regard that as a feature rather than a bug since the standard mathematical definition of partition allows for a partition of a set into one piece. If this in undesirable for your purposes, the fix is easy enough -- just iterate over the nonempty subsets of the cut points. In terms of the above code, this fix amounts to adding two characters to allPartitions: replace
for k in range(n):
by
for k in range(1,n):
Something along the lines of the following (untested and likely buggy VB.NET sample)
Function FindAllGroups(s As String) As List(Of List(Of String))
Dim ret As New List(Of List(Of String))
Dim l As New List(Of String)
l.Add(s) 'the whole string unbroken
ret.Add(l) 'first option we return is the whole unbroken string by itself
If s.Length > 1 Then
Dim tmp = FindAllGroups(s.Substring(1)) 'find all the groups for the rest of the string after the first character
For Each l2 in tmp
l = l2.ToList 'Copy it
l.Insert(s.SubString(0,1),0)'insert the first character from this string by itself before this combination for the rest of the string
ret.Add(l)
Next
For Each l2 in tmp
l = l2.ToList 'Copy it
l(0)= s.SubString(0,1) & l(0) 'insert the first character from this string as part of the first element in the list
ret.Add(l)
Next
End If
Return ret
End Function
This basically works by saying that we can take 'abcd' and split it into
'a', 1st option for 'bcd' split
'a', 2nd option for 'bcd' split
...
+
1st option for 'bcd' split with the first element prepended with 'a'
2nd option for 'bcd' split with the first element prepended with 'a'
...
then to calculate 'bcd', we just repeat the process as above, only with
'b', 1st option for 'cd' split
'b', 2nd option for 'cd' split
...
+
1st option for 'cd' split with the first element prepended with 'b'
2nd option for 'cd' split with the first element prepended with 'b'
...
etc. repeated recursively.
However, this code isn't particularly efficient at runtime. One thing that you could do to speed it up significantly would be to add a Dictionary(Of String, List(Of List(Of String)) outside the function which you can store a cache of the results in and if the item exists in there, you return from there, if not, calculate it and add it. Lists also might not be the most efficient, and the ToList function might not be the quickest way of cloning. However, I've simplified it to make it easier to understand and also to save me time working it out!
This is a fairly standard depth first search (backtracking) problem.
void dfs(int startIndex, const string& s, vector<string>& tmp,
vector<vector<string>>& res){
if (startIndex == s.size()) {
res.push_back(tmp);
return;
}
for (int i = 1; startIndex + i <= s.size(); ++i) {
tmp.push_back(s.substr(startIndex, i));
dfs(startIndex + i, s, tmp, res);
tmp.pop_back();
}
}
int main()
{
vector<vector<string>> res;
vector<string> tmp;
string s = "abcd";
dfs(0, s, tmp, res);
}
For its execution and result please refer to here.
#include <bits/stdc++.h>
using namespace std;
vector<string> ans;
string s;
void solve(int previouscut, int len)
{
if(previouscut == s.length()) // base case
{
for(auto str:ans)
cout << str << " " ;
cout << "\n";
return;
}
if(previouscut+len>s.length()) // boundary case
return;
//cut
ans.push_back(s.substr(previouscut,len));
solve(previouscut + len,1);
ans.pop_back(); //backtrack
// no cut
solve(previouscut, len+1);
}
int main()
{
cin >> s;
solve(0,1);
return 0;
}
https://www.geeksforgeeks.org/substring-in-cpp/#

printing the permutation using bfs or dfs

I am trying to print all the permutations of a string using recursion as below. But I was wondering if we can use bfs or dfs also to do this, am I thinking right?
If yes, then can you please give me an idea?
My idea is: if string = "abcd"
start node: 'a'
end node: 'd'
intermediate nodes: 'b' and 'c'
We can then change the start nodes to 'b','c' and 'd'.
I am having difficulty in visualizing it to put it in a algorithm.
#include <stdio.h>
void swap(char *s, int i, int j)
{
char temp = s[i];
s[i] = s[j];
s[j] = temp;
}
void foo(char *s, int j, int len)
{
int i;
if (j == len-1) {
printf("%s\n", s);
return;
}
for (i=j;i<len;i++) {
swap(s, i, j);
foo(s, j+1, len);
swap(s, i, j);
}
}
int main()
{
char s[] = "abc";
foo(s, 0, strlen(s));
}
Based on the logic given by Serge Rogatch, below problem can be solved:
def swap_two(s, i, j):
return s[:i] + s[j] + s[i+1:j] + s[i] + s[j+1:]
def swaps(s):
for i in range(1, len(s)):
yield swap_two(s, 0, i)
def print_permutations(input, q):
seen_list = []
q.enqueue(input)
while not q.isempty():
data = q.dequeue()
for i in swaps(data):
if i not in seen_list:
q.enqueue(i)
seen_list.append(i)
return seen_list
q = queue(512)
seen_list = print_permutations("abcd", q)
print(sorted(seen_list), len(seen_list))
queue implementation is here
Your algorithm seems to already implement backtracking, which is one of the correct things to do for permuting. There is also non-recursive algorithm based on tail inversion (can't find the link, I think I don't remember its name precisely) or QuickPerm algorithm: http://www.quickperm.org/quickperm.html
DFS and BFS visit every vertex exactly once. So if you really want to use them, then as vertices you should view permutations (whole strings like "abcd", "abdc", etc.) rather than separate characters like 'a', 'b', etc. Starting with some initial vertex like "abcd" you should try to swap each pair of characters and see if that vertex has been already visited. You can store the set of visited vertices in an unordered_set. So e.g. in "abcd" if you swap 'b' and 'c' you get "acbd" etc. This algorithm should produce each permutation because for Heap's algorithm it suffices to swap just one pair of vertices in each step: https://en.wikipedia.org/wiki/Heap%27s_algorithm
If you strictly want to emulate a graph traversal algorithm...Here's an intuitive(probably not the most graceful) approach:
Think of string as a graph, where each character is connected to every other character
Instead of trying to find a "path" from source to destination, frame the problem as follows: "find all paths of a specific length - from every source"
So start from the first character, use it as the "source"; then find all paths with length = length of the entire String... Then use the next character as the source...
Here's an implementation in python:
def permutations(s):
g = _str_to_graph(s) # {'a': ['b', 'c'], 'b': ['c', 'a'], 'c': ['a', 'b'] }
branch = []
visited = set()
for i in s: # use every character as a source
dfs_all_paths_of_certain_length(i, len(s), branch, visited, g)
def _str_to_graph(s):
from collections import defaultdict
g = defaultdict(list)
for i in range(len(s)):
for j in range(len(s)):
if i != j:
g[s[i]].append(s[j])
return g
def dfs_all_paths_of_certain_length(u, ll, branch, visited, g):
visited.add(u)
branch.append(u)
if len(branch) == ll: # if length of branch equals length of string, print the branch
print("".join(branch))
else:
for n in g[u]:
if n not in visited:
dfs_all_paths_of_certain_length(n, ll, branch, visited, g)
# backtrack
visited.remove(u)
branch.remove(u)
You can read this article:
http://en.cppreference.com/w/cpp/algorithm/next_permutation
AlTHOUGH this is C++ implementation, but you can easily transform it to a C version
By the way, your method can be called a dfs!

Greedy algorithm to find potential weighted activities in order?

For example, let's say there's a list of activities {a, b, c, d, e, f, g}
a & b are worth 9 points each.
c is worth 8 points.
d & e are worth 6 points each.
f is worth 5 points.
g is worth 4 points.
The list of activities is already sorted by points descending.
I want to find the highest points combination of three activities (let's call this combination X) that fulfills certain requirements (such that F(X) = true).
F(X) accepts only a combination of three activities, and cannot be modified.
How can I generate X without first having to calculate all possible combinations?
How can I iterate through all the possible combinations in decreasing total points?
I want to be able to find the highest point combination, test it. If it fails, generate second-highest point combination, etc.
The example list is only a few items. However, the actual list can get extremely large that and it would be impractical to generate all combinations.
How should I do this?
The following idea only solves an easier version of the problem, but maybe it can be extended to a more powerful solution.
Let [a(1)..a(N)] be the input array.
What I suggest here is a way to enumerate the top N^(1/3) triplets, out of the C(N,3)~N^3 ones in the complete enumeration. I know this is modest, but it guarantees O(N) time and space.
s = a(1) + a(2) + a(N^(1/3))
T = All triplets in [a(1),a(2), .. ,a(N^(1/3))] (takes O(N) time and space)
Sort T in descending triplet sum order (Time complexity: O(N^(1/3) * log N) = O(N) )
Iterate over T and return every triplet r while sum(r) >= s
Explanation:
In (1) we compute the highest score possible for a triplet that doesn't involve only items from T = [a(1)..a(N^(1/3))]. In other words, T already contains all triplets of score > s. Therefore we generate all triplets in T, sort them, and return only the ones we are sure about (i.e. the ones with score>=s). How many such triplets will be returned? well, this depends on the array values, but we can guarantee at least N^(1/3) - 2 triplets, since all triplets [a(1)+a(2)+a(i)] for 2<i<=N^(1/3) have a sum >=s. In practice the number of "good" triplets may be much higher, but again, this depends on the array numbers distribution.
Here is way to generate ordered combinations of three:-
for(int i=0;i<Set.size();i++) {
for(int j=i+1;j<Set.size();j++) {
for(int k=j+1;k<Set.size();k++) {
if(F(Set[i],Set[j],Set[k])) {
// your code to find max
}
}
}
}
I do not think there is a great solution for your requirement. Here is the best (and worst) solution I can think of: Generate all combinations put them in a vector then sort! Complexity is O(n^3 log(n^3)). Only little improvement I think can be achieve by assuming that there is no point of having same value in the same position multiple times as it will generate a combination already got generated.
Implementation in c++:
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
struct Combin {
int a, b, c, sum;
};
bool comp(Combin a, Combin b) {
return a.sum>b.sum;
}
int main() {
vector<int> act;
int n;
while(scanf("%d", &n)==1 && n) {
act.push_back(n);
}
vector<Combin>combs;
for (int i=0; i<act.size(); i++) {
if (i>0 && act[i-1]==act[i]) continue;
for (int j=i+1; j<act.size(); j++) {
if (j>i+1 && act[j-1]==act[j]) continue;
for (int k=j+1; k<act.size(); k++) {
if (k>j+1 && act[k-1]==act[k]) continue;
Combin comb;
comb.a=i; comb.b=j; comb.c=k;
comb.sum = act[i]+act[j]+act[k];
combs.push_back(comb);
}
}
}
sort(combs.begin(), combs.end(), comp);
for (int i=0; i<combs.size(); i++) {
printf("(%d,%d,%d)=%d\n", act[combs[i].a], act[combs[i].b], act[combs[i].c], combs[i].sum);
}
return 0;
}
I remembered that Pythons combinations generator tends to keep the LHS-to-RHS of its input varying from the least-to-most, and outputs the LHS terms first.
If you use Pythons method of generating combinations, which its docs states is the following:
def combinations(iterable, r):
# combinations('ABCD', 2) --> AB AC AD BC BD CD
# combinations(range(4), 3) --> 012 013 023 123
pool = tuple(iterable)
n = len(pool)
if r > n:
return
indices = range(r)
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):
if indices[i] != i + n - r:
break
else:
return
indices[i] += 1
for j in range(i+1, r):
indices[j] = indices[j-1] + 1
yield tuple(pool[i] for i in indices)
Then you can just give the function your items in decreasing weight order to generate items in decreasing weight order:
for x in combinations('abcdef', 3):
print(x)
('a', 'b', 'c')
('a', 'b', 'd')
('a', 'b', 'e')
('a', 'b', 'f')
('a', 'c', 'd')
('a', 'c', 'e')
('a', 'c', 'f')
('a', 'd', 'e')
('a', 'd', 'f')
('a', 'e', 'f')
('b', 'c', 'd')
('b', 'c', 'e')
('b', 'c', 'f')
('b', 'd', 'e')
('b', 'd', 'f')
('b', 'e', 'f')
('c', 'd', 'e')
('c', 'd', 'f')
('c', 'e', 'f')
('d', 'e', 'f')
Note: As Essam points out in the comments, combinations(data, 3) is equivalent to comb3(data) where:
def comb3(data):
lendata = len(data)
for i in range(lendata):
for j in range(i+1, lendata):
for k in range(j+1, lendata):
yield (data[i], data[j], data[k])
My other answer of just using generated combinations in a certain order doesn't give the fully sorted answer. In fact their will be 6 out of 35 occasions where the total for the next triple goes up rather than down.
If we use the combinations but put them in a heap of fixed maximum size then we can trade the maximum heap size for accuracy of sort like so:
from itertools import combinations
from heapq import heappush, heappop, heappushpop
BESTOFLAST = 10 # max heap size
item2points = dict(a=9, b=9, c=8, d=6, e=6, f=5, g=4)
def partially_ordered_triples(item2points, BESTOFLAST=BESTOFLAST):
ordereditems = sorted(item2points.keys(),
key=lambda item: item2points[item],
reverse=True)
#print(ordereditems) # ['a', 'b', 'c', 'e', 'd', 'f', 'g']
triples = combinations(ordereditems, 3)
heap = [] # Empty heap
# Preload heap
for i in range(BESTOFLAST):
triple = triples.next()
total = sum(item2points[item] for item in triple)
heappush(heap, (-total, triple)) # minheap so -total
# load/remove from heap in partially sorted order
for triple in triples:
total = sum(item2points[item] for item in triple)
thistotal, thistriple = heappushpop(heap, (-total, triple))
yield thistriple, -thistotal
# drain rest of heap
while heap:
thistotal, thistriple = heappop(heap)
yield thistriple, -thistotal
if __name__ == '__main__':
for heapsize in range(BESTOFLAST + 1):
print('Using a heap of size: %i and skipping:' % heapsize)
length = skipped = 0
previoustotal = sum(item2points.values()) # Starting high value
for triple, newtotal in partially_ordered_triples(item2points, heapsize):
if newtotal > previoustotal: skipped += 1
length += 1
previoustotal = newtotal
print(" of %i triples, %i were skipped to keep the total count decreasing" % (length, skipped))
If the size of the heap is large enough then there will be no deviations from the required order. If too small then the number of deviations increases:
The output:
Using a heap of size: 0 and skipping:
of 35 triples, 6 were skipped to keep the total count decreasing
Using a heap of size: 1 and skipping:
of 35 triples, 4 were skipped to keep the total count decreasing
Using a heap of size: 2 and skipping:
of 35 triples, 4 were skipped to keep the total count decreasing
Using a heap of size: 3 and skipping:
of 35 triples, 3 were skipped to keep the total count decreasing
Using a heap of size: 4 and skipping:
of 35 triples, 2 were skipped to keep the total count decreasing
Using a heap of size: 5 and skipping:
of 35 triples, 2 were skipped to keep the total count decreasing
Using a heap of size: 6 and skipping:
of 35 triples, 1 were skipped to keep the total count decreasing
Using a heap of size: 7 and skipping:
of 35 triples, 1 were skipped to keep the total count decreasing
Using a heap of size: 8 and skipping:
of 35 triples, 1 were skipped to keep the total count decreasing
Using a heap of size: 9 and skipping:
of 35 triples, 0 were skipped to keep the total count decreasing
Using a heap of size: 10 and skipping:
of 35 triples, 0 were skipped to keep the total count decreasing

Appending n elements to an array

I have an array and a hash
L = []
H = {3=>"a", 2=>"b", 1=>"c"}
And so I will iterate over the keys to get the number of times n the element occurs and append that element to an array n times
Result
L = ['a', 'a', 'a', 'b', 'b', 'c']
What's a nice way to write this with inject (or other methods that I often see in ruby code)?
array = hash.flat_map { |k,v| [v]*k }
#David's answer is spot-on for your needs. In general, however, you can add an object o to an existing array n times via one of:
# Modify the array in-place, or…
my_array.concat( [o]*n )
# …alternatively create a new modified array
new_array = my_array + [o]*n

Resources