I want to write a function that takes an array of letters as an argument and a number of those letters to select.
Say you provide an array of 8 letters and want to select 3 letters from that. Then you should get:
8! / ((8 - 3)! * 3!) = 56
Arrays (or words) in return consisting of 3 letters each.
Art of Computer Programming Volume 4: Fascicle 3 has a ton of these that might fit your particular situation better than how I describe.
Gray Codes
An issue that you will come across is of course memory and pretty quickly, you'll have problems by 20 elements in your set -- 20C3 = 1140. And if you want to iterate over the set it's best to use a modified gray code algorithm so you aren't holding all of them in memory. These generate the next combination from the previous and avoid repetitions. There are many of these for different uses. Do we want to maximize the differences between successive combinations? minimize? et cetera.
Some of the original papers describing gray codes:
Some Hamilton Paths and a Minimal Change Algorithm
Adjacent Interchange Combination Generation Algorithm
Here are some other papers covering the topic:
An Efficient Implementation of the Eades, Hickey, Read Adjacent Interchange Combination Generation Algorithm (PDF, with code in Pascal)
Combination Generators
Survey of Combinatorial Gray Codes (PostScript)
An Algorithm for Gray Codes
Chase's Twiddle (algorithm)
Phillip J Chase, `Algorithm 382: Combinations of M out of N Objects' (1970)
The algorithm in C...
Index of Combinations in Lexicographical Order (Buckles Algorithm 515)
You can also reference a combination by its index (in lexicographical order). Realizing that the index should be some amount of change from right to left based on the index we can construct something that should recover a combination.
So, we have a set {1,2,3,4,5,6}... and we want three elements. Let's say {1,2,3} we can say that the difference between the elements is one and in order and minimal. {1,2,4} has one change and is lexicographically number 2. So the number of 'changes' in the last place accounts for one change in the lexicographical ordering. The second place, with one change {1,3,4} has one change but accounts for more change since it's in the second place (proportional to the number of elements in the original set).
The method I've described is a deconstruction, as it seems, from set to the index, we need to do the reverse – which is much trickier. This is how Buckles solves the problem. I wrote some C to compute them, with minor changes – I used the index of the sets rather than a number range to represent the set, so we are always working from 0...n.
Note:
Since combinations are unordered, {1,3,2} = {1,2,3} --we order them to be lexicographical.
This method has an implicit 0 to start the set for the first difference.
Index of Combinations in Lexicographical Order (McCaffrey)
There is another way:, its concept is easier to grasp and program but it's without the optimizations of Buckles. Fortunately, it also does not produce duplicate combinations:
The set that maximizes , where .
For an example: 27 = C(6,4) + C(5,3) + C(2,2) + C(1,1). So, the 27th lexicographical combination of four things is: {1,2,5,6}, those are the indexes of whatever set you want to look at. Example below (OCaml), requires choose function, left to reader:
(* this will find the [x] combination of a [set] list when taking [k] elements *)
let combination_maccaffery set k x =
(* maximize function -- maximize a that is aCb *)
(* return largest c where c < i and choose(c,i) <= z *)
let rec maximize a b x =
if (choose a b ) <= x then a else maximize (a-1) b x
in
let rec iterate n x i = match i with
| 0 -> []
| i ->
let max = maximize n i x in
max :: iterate n (x - (choose max i)) (i-1)
in
if x < 0 then failwith "errors" else
let idxs = iterate (List.length set) x k in
List.map (List.nth set) (List.sort (-) idxs)
A small and simple combinations iterator
The following two algorithms are provided for didactic purposes. They implement an iterator and (a more general) folder overall combinations.
They are as fast as possible, having the complexity O(nCk). The memory consumption is bound by k.
We will start with the iterator, which will call a user provided function for each combination
let iter_combs n k f =
let rec iter v s j =
if j = k then f v
else for i = s to n - 1 do iter (i::v) (i+1) (j+1) done in
iter [] 0 0
A more general version will call the user provided function along with the state variable, starting from the initial state. Since we need to pass the state between different states we won't use the for-loop, but instead, use recursion,
let fold_combs n k f x =
let rec loop i s c x =
if i < n then
loop (i+1) s c ##
let c = i::c and s = s + 1 and i = i + 1 in
if s < k then loop i s c x else f c x
else x in
loop 0 0 [] x
In C#:
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) =>
elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] {e}).Concat(c)));
}
Usage:
var result = Combinations(new[] { 1, 2, 3, 4, 5 }, 3);
Result:
123
124
125
134
135
145
234
235
245
345
Short java solution:
import java.util.Arrays;
public class Combination {
public static void main(String[] args){
String[] arr = {"A","B","C","D","E","F"};
combinations2(arr, 3, 0, new String[3]);
}
static void combinations2(String[] arr, int len, int startPosition, String[] result){
if (len == 0){
System.out.println(Arrays.toString(result));
return;
}
for (int i = startPosition; i <= arr.length-len; i++){
result[result.length - len] = arr[i];
combinations2(arr, len-1, i+1, result);
}
}
}
Result will be
[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]
May I present my recursive Python solution to this problem?
def choose_iter(elements, length):
for i in xrange(len(elements)):
if length == 1:
yield (elements[i],)
else:
for next in choose_iter(elements[i+1:], length-1):
yield (elements[i],) + next
def choose(l, k):
return list(choose_iter(l, k))
Example usage:
>>> len(list(choose_iter("abcdefgh",3)))
56
I like it for its simplicity.
Lets say your array of letters looks like this: "ABCDEFGH". You have three indices (i, j, k) indicating which letters you are going to use for the current word, You start with:
A B C D E F G H
^ ^ ^
i j k
First you vary k, so the next step looks like that:
A B C D E F G H
^ ^ ^
i j k
If you reached the end you go on and vary j and then k again.
A B C D E F G H
^ ^ ^
i j k
A B C D E F G H
^ ^ ^
i j k
Once you j reached G you start also to vary i.
A B C D E F G H
^ ^ ^
i j k
A B C D E F G H
^ ^ ^
i j k
...
Written in code this look something like that
void print_combinations(const char *string)
{
int i, j, k;
int len = strlen(string);
for (i = 0; i < len - 2; i++)
{
for (j = i + 1; j < len - 1; j++)
{
for (k = j + 1; k < len; k++)
printf("%c%c%c\n", string[i], string[j], string[k]);
}
}
}
The following recursive algorithm picks all of the k-element combinations from an ordered set:
choose the first element i of your combination
combine i with each of the combinations of k-1 elements chosen recursively from the set of elements larger than i.
Iterate the above for each i in the set.
It is essential that you pick the rest of the elements as larger than i, to avoid repetition. This way [3,5] will be picked only once, as [3] combined with [5], instead of twice (the condition eliminates [5] + [3]). Without this condition you get variations instead of combinations.
Short example in Python:
def comb(sofar, rest, n):
if n == 0:
print sofar
else:
for i in range(len(rest)):
comb(sofar + rest[i], rest[i+1:], n-1)
>>> comb("", "abcde", 3)
abc
abd
abe
acd
ace
ade
bcd
bce
bde
cde
For explanation, the recursive method is described with the following example:
Example: A B C D E
All combinations of 3 would be:
A with all combinations of 2 from the rest (B C D E)
B with all combinations of 2 from the rest (C D E)
C with all combinations of 2 from the rest (D E)
I found this thread useful and thought I would add a Javascript solution that you can pop into Firebug. Depending on your JS engine, it could take a little time if the starting string is large.
function string_recurse(active, rest) {
if (rest.length == 0) {
console.log(active);
} else {
string_recurse(active + rest.charAt(0), rest.substring(1, rest.length));
string_recurse(active, rest.substring(1, rest.length));
}
}
string_recurse("", "abc");
The output should be as follows:
abc
ab
ac
a
bc
b
c
In C++ the following routine will produce all combinations of length distance(first,k) between the range [first,last):
#include <algorithm>
template <typename Iterator>
bool next_combination(const Iterator first, Iterator k, const Iterator last)
{
/* Credits: Mark Nelson http://marknelson.us */
if ((first == last) || (first == k) || (last == k))
return false;
Iterator i1 = first;
Iterator i2 = last;
++i1;
if (last == i1)
return false;
i1 = last;
--i1;
i1 = k;
--i2;
while (first != i1)
{
if (*--i1 < *i2)
{
Iterator j = k;
while (!(*i1 < *j)) ++j;
std::iter_swap(i1,j);
++i1;
++j;
i2 = k;
std::rotate(i1,j,last);
while (last != j)
{
++j;
++i2;
}
std::rotate(k,i2,last);
return true;
}
}
std::rotate(first,k,last);
return false;
}
It can be used like this:
#include <string>
#include <iostream>
int main()
{
std::string s = "12345";
std::size_t comb_size = 3;
do
{
std::cout << std::string(s.begin(), s.begin() + comb_size) << std::endl;
} while (next_combination(s.begin(), s.begin() + comb_size, s.end()));
return 0;
}
This will print the following:
123
124
125
134
135
145
234
235
245
345
static IEnumerable<string> Combinations(List<string> characters, int length)
{
for (int i = 0; i < characters.Count; i++)
{
// only want 1 character, just return this one
if (length == 1)
yield return characters[i];
// want more than one character, return this one plus all combinations one shorter
// only use characters after the current one for the rest of the combinations
else
foreach (string next in Combinations(characters.GetRange(i + 1, characters.Count - (i + 1)), length - 1))
yield return characters[i] + next;
}
}
Simple recursive algorithm in Haskell
import Data.List
combinations 0 lst = [[]]
combinations n lst = do
(x:xs) <- tails lst
rest <- combinations (n-1) xs
return $ x : rest
We first define the special case, i.e. selecting zero elements. It produces a single result, which is an empty list (i.e. a list that contains an empty list).
For n > 0, x goes through every element of the list and xs is every element after x.
rest picks n - 1 elements from xs using a recursive call to combinations. The final result of the function is a list where each element is x : rest (i.e. a list which has x as head and rest as tail) for every different value of x and rest.
> combinations 3 "abcde"
["abc","abd","abe","acd","ace","ade","bcd","bce","bde","cde"]
And of course, since Haskell is lazy, the list is gradually generated as needed, so you can partially evaluate exponentially large combinations.
> let c = combinations 8 "abcdefghijklmnopqrstuvwxyz"
> take 10 c
["abcdefgh","abcdefgi","abcdefgj","abcdefgk","abcdefgl","abcdefgm","abcdefgn",
"abcdefgo","abcdefgp","abcdefgq"]
And here comes granddaddy COBOL, the much maligned language.
Let's assume an array of 34 elements of 8 bytes each (purely arbitrary selection.) The idea is to enumerate all possible 4-element combinations and load them into an array.
We use 4 indices, one each for each position in the group of 4
The array is processed like this:
idx1 = 1
idx2 = 2
idx3 = 3
idx4 = 4
We vary idx4 from 4 to the end. For each idx4 we get a unique combination
of groups of four. When idx4 comes to the end of the array, we increment idx3 by 1 and set idx4 to idx3+1. Then we run idx4 to the end again. We proceed in this manner, augmenting idx3,idx2, and idx1 respectively until the position of idx1 is less than 4 from the end of the array. That finishes the algorithm.
1 --- pos.1
2 --- pos 2
3 --- pos 3
4 --- pos 4
5
6
7
etc.
First iterations:
1234
1235
1236
1237
1245
1246
1247
1256
1257
1267
etc.
A COBOL example:
01 DATA_ARAY.
05 FILLER PIC X(8) VALUE "VALUE_01".
05 FILLER PIC X(8) VALUE "VALUE_02".
etc.
01 ARAY_DATA OCCURS 34.
05 ARAY_ITEM PIC X(8).
01 OUTPUT_ARAY OCCURS 50000 PIC X(32).
01 MAX_NUM PIC 99 COMP VALUE 34.
01 INDEXXES COMP.
05 IDX1 PIC 99.
05 IDX2 PIC 99.
05 IDX3 PIC 99.
05 IDX4 PIC 99.
05 OUT_IDX PIC 9(9).
01 WHERE_TO_STOP_SEARCH PIC 99 COMP.
* Stop the search when IDX1 is on the third last array element:
COMPUTE WHERE_TO_STOP_SEARCH = MAX_VALUE - 3
MOVE 1 TO IDX1
PERFORM UNTIL IDX1 > WHERE_TO_STOP_SEARCH
COMPUTE IDX2 = IDX1 + 1
PERFORM UNTIL IDX2 > MAX_NUM
COMPUTE IDX3 = IDX2 + 1
PERFORM UNTIL IDX3 > MAX_NUM
COMPUTE IDX4 = IDX3 + 1
PERFORM UNTIL IDX4 > MAX_NUM
ADD 1 TO OUT_IDX
STRING ARAY_ITEM(IDX1)
ARAY_ITEM(IDX2)
ARAY_ITEM(IDX3)
ARAY_ITEM(IDX4)
INTO OUTPUT_ARAY(OUT_IDX)
ADD 1 TO IDX4
END-PERFORM
ADD 1 TO IDX3
END-PERFORM
ADD 1 TO IDX2
END_PERFORM
ADD 1 TO IDX1
END-PERFORM.
Another C# version with lazy generation of the combination indices. This version maintains a single array of indices to define a mapping between the list of all values and the values for the current combination, i.e. constantly uses O(k) additional space during the entire runtime. The code generates individual combinations, including the first one, in O(k) time.
public static IEnumerable<T[]> Combinations<T>(this T[] values, int k)
{
if (k < 0 || values.Length < k)
yield break; // invalid parameters, no combinations possible
// generate the initial combination indices
var combIndices = new int[k];
for (var i = 0; i < k; i++)
{
combIndices[i] = i;
}
while (true)
{
// return next combination
var combination = new T[k];
for (var i = 0; i < k; i++)
{
combination[i] = values[combIndices[i]];
}
yield return combination;
// find first index to update
var indexToUpdate = k - 1;
while (indexToUpdate >= 0 && combIndices[indexToUpdate] >= values.Length - k + indexToUpdate)
{
indexToUpdate--;
}
if (indexToUpdate < 0)
yield break; // done
// update combination indices
for (var combIndex = combIndices[indexToUpdate] + 1; indexToUpdate < k; indexToUpdate++, combIndex++)
{
combIndices[indexToUpdate] = combIndex;
}
}
}
Test code:
foreach (var combination in new[] {'a', 'b', 'c', 'd', 'e'}.Combinations(3))
{
System.Console.WriteLine(String.Join(" ", combination));
}
Output:
a b c
a b d
a b e
a c d
a c e
a d e
b c d
b c e
b d e
c d e
Here is an elegant, generic implementation in Scala, as described on 99 Scala Problems.
object P26 {
def flatMapSublists[A,B](ls: List[A])(f: (List[A]) => List[B]): List[B] =
ls match {
case Nil => Nil
case sublist#(_ :: tail) => f(sublist) ::: flatMapSublists(tail)(f)
}
def combinations[A](n: Int, ls: List[A]): List[List[A]] =
if (n == 0) List(Nil)
else flatMapSublists(ls) { sl =>
combinations(n - 1, sl.tail) map {sl.head :: _}
}
}
If you can use SQL syntax - say, if you're using LINQ to access fields of an structure or array, or directly accessing a database that has a table called "Alphabet" with just one char field "Letter", you can adapt following code:
SELECT A.Letter, B.Letter, C.Letter
FROM Alphabet AS A, Alphabet AS B, Alphabet AS C
WHERE A.Letter<>B.Letter AND A.Letter<>C.Letter AND B.Letter<>C.Letter
AND A.Letter<B.Letter AND B.Letter<C.Letter
This will return all combinations of 3 letters, notwithstanding how many letters you have in table "Alphabet" (it can be 3, 8, 10, 27, etc.).
If what you want is all permutations, rather than combinations (i.e. you want "ACB" and "ABC" to count as different, rather than appear just once) just delete the last line (the AND one) and it's done.
Post-Edit: After re-reading the question, I realise what's needed is the general algorithm, not just a specific one for the case of selecting 3 items. Adam Hughes' answer is the complete one, unfortunately I cannot vote it up (yet). This answer's simple but works only for when you want exactly 3 items.
I had a permutation algorithm I used for project euler, in python:
def missing(miss,src):
"Returns the list of items in src not present in miss"
return [i for i in src if i not in miss]
def permutation_gen(n,l):
"Generates all the permutations of n items of the l list"
for i in l:
if n<=1: yield [i]
r = [i]
for j in permutation_gen(n-1,missing([i],l)): yield r+j
If
n<len(l)
you should have all combination you need without repetition, do you need it?
It is a generator, so you use it in something like this:
for comb in permutation_gen(3,list("ABCDEFGH")):
print comb
https://gist.github.com/3118596
There is an implementation for JavaScript. It has functions to get k-combinations and all combinations of an array of any objects. Examples:
k_combinations([1,2,3], 2)
-> [[1,2], [1,3], [2,3]]
combinations([1,2,3])
-> [[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
Lets say your array of letters looks like this: "ABCDEFGH". You have three indices (i, j, k) indicating which letters you are going to use for the current word, You start with:
A B C D E F G H
^ ^ ^
i j k
First you vary k, so the next step looks like that:
A B C D E F G H
^ ^ ^
i j k
If you reached the end you go on and vary j and then k again.
A B C D E F G H
^ ^ ^
i j k
A B C D E F G H
^ ^ ^
i j k
Once you j reached G you start also to vary i.
A B C D E F G H
^ ^ ^
i j k
A B C D E F G H
^ ^ ^
i j k
...
function initializePointers($cnt) {
$pointers = [];
for($i=0; $i<$cnt; $i++) {
$pointers[] = $i;
}
return $pointers;
}
function incrementPointers(&$pointers, &$arrLength) {
for($i=0; $i<count($pointers); $i++) {
$currentPointerIndex = count($pointers) - $i - 1;
$currentPointer = $pointers[$currentPointerIndex];
if($currentPointer < $arrLength - $i - 1) {
++$pointers[$currentPointerIndex];
for($j=1; ($currentPointerIndex+$j)<count($pointers); $j++) {
$pointers[$currentPointerIndex+$j] = $pointers[$currentPointerIndex]+$j;
}
return true;
}
}
return false;
}
function getDataByPointers(&$arr, &$pointers) {
$data = [];
for($i=0; $i<count($pointers); $i++) {
$data[] = $arr[$pointers[$i]];
}
return $data;
}
function getCombinations($arr, $cnt)
{
$len = count($arr);
$result = [];
$pointers = initializePointers($cnt);
do {
$result[] = getDataByPointers($arr, $pointers);
} while(incrementPointers($pointers, count($arr)));
return $result;
}
$result = getCombinations([0, 1, 2, 3, 4, 5], 3);
print_r($result);
Based on https://stackoverflow.com/a/127898/2628125, but more abstract, for any size of pointers.
Here you have a lazy evaluated version of that algorithm coded in C#:
static bool nextCombination(int[] num, int n, int k)
{
bool finished, changed;
changed = finished = false;
if (k > 0)
{
for (int i = k - 1; !finished && !changed; i--)
{
if (num[i] < (n - 1) - (k - 1) + i)
{
num[i]++;
if (i < k - 1)
{
for (int j = i + 1; j < k; j++)
{
num[j] = num[j - 1] + 1;
}
}
changed = true;
}
finished = (i == 0);
}
}
return changed;
}
static IEnumerable Combinations<T>(IEnumerable<T> elements, int k)
{
T[] elem = elements.ToArray();
int size = elem.Length;
if (k <= size)
{
int[] numbers = new int[k];
for (int i = 0; i < k; i++)
{
numbers[i] = i;
}
do
{
yield return numbers.Select(n => elem[n]);
}
while (nextCombination(numbers, size, k));
}
}
And test part:
static void Main(string[] args)
{
int k = 3;
var t = new[] { "dog", "cat", "mouse", "zebra"};
foreach (IEnumerable<string> i in Combinations(t, k))
{
Console.WriteLine(string.Join(",", i));
}
}
Hope this help you!
Another version, that forces all the first k to appear firstly, then all the first k+1 combinations, then all the first k+2 etc.. It means that if you have sorted array, the most important on the top, it would take them and expand gradually to the next ones - only when it is must do so.
private static bool NextCombinationFirstsAlwaysFirst(int[] num, int n, int k)
{
if (k > 1 && NextCombinationFirstsAlwaysFirst(num, num[k - 1], k - 1))
return true;
if (num[k - 1] + 1 == n)
return false;
++num[k - 1];
for (int i = 0; i < k - 1; ++i)
num[i] = i;
return true;
}
For instance, if you run the first method ("nextCombination") on k=3, n=5 you'll get:
0 1 2
0 1 3
0 1 4
0 2 3
0 2 4
0 3 4
1 2 3
1 2 4
1 3 4
2 3 4
But if you'll run
int[] nums = new int[k];
for (int i = 0; i < k; ++i)
nums[i] = i;
do
{
Console.WriteLine(string.Join(" ", nums));
}
while (NextCombinationFirstsAlwaysFirst(nums, n, k));
You'll get this (I added empty lines for clarity):
0 1 2
0 1 3
0 2 3
1 2 3
0 1 4
0 2 4
1 2 4
0 3 4
1 3 4
2 3 4
It's adding "4" only when must to, and also after "4" was added it adds "3" again only when it must to (after doing 01, 02, 12).
Array.prototype.combs = function(num) {
var str = this,
length = str.length,
of = Math.pow(2, length) - 1,
out, combinations = [];
while(of) {
out = [];
for(var i = 0, y; i < length; i++) {
y = (1 << i);
if(y & of && (y !== of))
out.push(str[i]);
}
if (out.length >= num) {
combinations.push(out);
}
of--;
}
return combinations;
}
Clojure version:
(defn comb [k l]
(if (= 1 k) (map vector l)
(apply concat
(map-indexed
#(map (fn [x] (conj x %2))
(comb (dec k) (drop (inc %1) l)))
l))))
Algorithm:
Count from 1 to 2^n.
Convert each digit to its binary representation.
Translate each 'on' bit to elements of your set, based on position.
In C#:
void Main()
{
var set = new [] {"A", "B", "C", "D" }; //, "E", "F", "G", "H", "I", "J" };
var kElement = 2;
for(var i = 1; i < Math.Pow(2, set.Length); i++) {
var result = Convert.ToString(i, 2).PadLeft(set.Length, '0');
var cnt = Regex.Matches(Regex.Escape(result), "1").Count;
if (cnt == kElement) {
for(int j = 0; j < set.Length; j++)
if ( Char.GetNumericValue(result[j]) == 1)
Console.Write(set[j]);
Console.WriteLine();
}
}
}
Why does it work?
There is a bijection between the subsets of an n-element set and n-bit sequences.
That means we can figure out how many subsets there are by counting sequences.
e.g., the four element set below can be represented by {0,1} X {0, 1} X {0, 1} X {0, 1} (or 2^4) different sequences.
So - all we have to do is count from 1 to 2^n to find all the combinations. (We ignore the empty set.) Next, translate the digits to their binary representation. Then substitute elements of your set for 'on' bits.
If you want only k element results, only print when k bits are 'on'.
(If you want all subsets instead of k length subsets, remove the cnt/kElement part.)
(For proof, see MIT free courseware Mathematics for Computer Science, Lehman et al, section 11.2.2. https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-042j-mathematics-for-computer-science-fall-2010/readings/ )
short python code, yielding index positions
def yield_combos(n,k):
# n is set size, k is combo size
i = 0
a = [0]*k
while i > -1:
for j in range(i+1, k):
a[j] = a[j-1]+1
i=j
yield a
while a[i] == i + n - k:
i -= 1
a[i] += 1
All said and and done here comes the O'caml code for that.
Algorithm is evident from the code..
let combi n lst =
let rec comb l c =
if( List.length c = n) then [c] else
match l with
[] -> []
| (h::t) -> (combi t (h::c))#(combi t c)
in
combi lst []
;;
Here is a method which gives you all combinations of specified size from a random length string. Similar to quinmars' solution, but works for varied input and k.
The code can be changed to wrap around, ie 'dab' from input 'abcd' w k=3.
public void run(String data, int howMany){
choose(data, howMany, new StringBuffer(), 0);
}
//n choose k
private void choose(String data, int k, StringBuffer result, int startIndex){
if (result.length()==k){
System.out.println(result.toString());
return;
}
for (int i=startIndex; i<data.length(); i++){
result.append(data.charAt(i));
choose(data,k,result, i+1);
result.setLength(result.length()-1);
}
}
Output for "abcde":
abc abd abe acd ace ade bcd bce bde cde
Short javascript version (ES 5)
let combine = (list, n) =>
n == 0 ?
[[]] :
list.flatMap((e, i) =>
combine(
list.slice(i + 1),
n - 1
).map(c => [e].concat(c))
);
let res = combine([1,2,3,4], 3);
res.forEach(e => console.log(e.join()));
Another python recusive solution.
def combination_indicies(n, k, j = 0, stack = []):
if len(stack) == k:
yield list(stack)
return
for i in range(j, n):
stack.append(i)
for x in combination_indicies(n, k, i + 1, stack):
yield x
stack.pop()
list(combination_indicies(5, 3))
Output:
[[0, 1, 2],
[0, 1, 3],
[0, 1, 4],
[0, 2, 3],
[0, 2, 4],
[0, 3, 4],
[1, 2, 3],
[1, 2, 4],
[1, 3, 4],
[2, 3, 4]]
I created a solution in SQL Server 2005 for this, and posted it on my website: http://www.jessemclain.com/downloads/code/sql/fn_GetMChooseNCombos.sql.htm
Here is an example to show usage:
SELECT * FROM dbo.fn_GetMChooseNCombos('ABCD', 2, '')
results:
Word
----
AB
AC
AD
BC
BD
CD
(6 row(s) affected)
Here is my proposition in C++
I tried to impose as little restriction on the iterator type as i could so this solution assumes just forward iterator, and it can be a const_iterator. This should work with any standard container. In cases where arguments don't make sense it throws std::invalid_argumnent
#include <vector>
#include <stdexcept>
template <typename Fci> // Fci - forward const iterator
std::vector<std::vector<Fci> >
enumerate_combinations(Fci begin, Fci end, unsigned int combination_size)
{
if(begin == end && combination_size > 0u)
throw std::invalid_argument("empty set and positive combination size!");
std::vector<std::vector<Fci> > result; // empty set of combinations
if(combination_size == 0u) return result; // there is exactly one combination of
// size 0 - emty set
std::vector<Fci> current_combination;
current_combination.reserve(combination_size + 1u); // I reserve one aditional slot
// in my vector to store
// the end sentinel there.
// The code is cleaner thanks to that
for(unsigned int i = 0u; i < combination_size && begin != end; ++i, ++begin)
{
current_combination.push_back(begin); // Construction of the first combination
}
// Since I assume the itarators support only incrementing, I have to iterate over
// the set to get its size, which is expensive. Here I had to itrate anyway to
// produce the first cobination, so I use the loop to also check the size.
if(current_combination.size() < combination_size)
throw std::invalid_argument("combination size > set size!");
result.push_back(current_combination); // Store the first combination in the results set
current_combination.push_back(end); // Here I add mentioned earlier sentinel to
// simplyfy rest of the code. If I did it
// earlier, previous statement would get ugly.
while(true)
{
unsigned int i = combination_size;
Fci tmp; // Thanks to the sentinel I can find first
do // iterator to change, simply by scaning
{ // from right to left and looking for the
tmp = current_combination[--i]; // first "bubble". The fact, that it's
++tmp; // a forward iterator makes it ugly but I
} // can't help it.
while(i > 0u && tmp == current_combination[i + 1u]);
// Here is probably my most obfuscated expression.
// Loop above looks for a "bubble". If there is no "bubble", that means, that
// current_combination is the last combination, Expression in the if statement
// below evaluates to true and the function exits returning result.
// If the "bubble" is found however, the ststement below has a sideeffect of
// incrementing the first iterator to the left of the "bubble".
if(++current_combination[i] == current_combination[i + 1u])
return result;
// Rest of the code sets posiotons of the rest of the iterstors
// (if there are any), that are to the right of the incremented one,
// to form next combination
while(++i < combination_size)
{
current_combination[i] = current_combination[i - 1u];
++current_combination[i];
}
// Below is the ugly side of using the sentinel. Well it had to haave some
// disadvantage. Try without it.
result.push_back(std::vector<Fci>(current_combination.begin(),
current_combination.end() - 1));
}
}
Here is a code I recently wrote in Java, which calculates and returns all the combination of "num" elements from "outOf" elements.
// author: Sourabh Bhat (heySourabh#gmail.com)
public class Testing
{
public static void main(String[] args)
{
// Test case num = 5, outOf = 8.
int num = 5;
int outOf = 8;
int[][] combinations = getCombinations(num, outOf);
for (int i = 0; i < combinations.length; i++)
{
for (int j = 0; j < combinations[i].length; j++)
{
System.out.print(combinations[i][j] + " ");
}
System.out.println();
}
}
private static int[][] getCombinations(int num, int outOf)
{
int possibilities = get_nCr(outOf, num);
int[][] combinations = new int[possibilities][num];
int arrayPointer = 0;
int[] counter = new int[num];
for (int i = 0; i < num; i++)
{
counter[i] = i;
}
breakLoop: while (true)
{
// Initializing part
for (int i = 1; i < num; i++)
{
if (counter[i] >= outOf - (num - 1 - i))
counter[i] = counter[i - 1] + 1;
}
// Testing part
for (int i = 0; i < num; i++)
{
if (counter[i] < outOf)
{
continue;
} else
{
break breakLoop;
}
}
// Innermost part
combinations[arrayPointer] = counter.clone();
arrayPointer++;
// Incrementing part
counter[num - 1]++;
for (int i = num - 1; i >= 1; i--)
{
if (counter[i] >= outOf - (num - 1 - i))
counter[i - 1]++;
}
}
return combinations;
}
private static int get_nCr(int n, int r)
{
if(r > n)
{
throw new ArithmeticException("r is greater then n");
}
long numerator = 1;
long denominator = 1;
for (int i = n; i >= r + 1; i--)
{
numerator *= i;
}
for (int i = 2; i <= n - r; i++)
{
denominator *= i;
}
return (int) (numerator / denominator);
}
}
I need help with making an algorithm.
I am currently designing something for a class I am taking.
Given 4 numbers, I need to find all (or at least the first) combination of the 4 numbers using basic operations (+-*/) to make a certain answer.
For example, if given numbers [1,2,3,4].
and I have to make the answer 12.
I can see (without a program) that (2-1)*3*4 = 12
But for more complex numbers, it may be harder to solve just by thinking about it. So I require a program to help me find at least one possible combination to solve the problem.
Note that, in the given 4 numbers, the numbers may repeat, but each number can only used once.
For example, the set of 4 can be [2,3,3,4]. But in that set, 2 and 4 cannot be used more than once.
I originally had a plan to brute force find all the possible combinations/orders of each 4 numbers, then iterating through all the operations. I later realized that this won't work as it doesn't take into account an operations like (1-2)*(3+4).
So I was wondering if anyone had an idea of how I can approach solving this problem?
Please keep in mind, that I am still fairly new to programming, so I may not understand some of the more advanced terms and functions. But I can keep up pretty well with things like loops and arrays.
There aren't actually that many combinations to check, because the number of precedence cases is limited to 5:
((a:b):c):d
(a:b):(c:d)
(a:(b:c)):d
a:((b:c):d)
a:(b:(c:d))
so with 24 permutations and 3 choices from 4 possible operators, that gives 7680 combinations. And many of these combinations are really identical, because the precedence is unimportant in cases like:
a+b+c+d
a+b+c-d
a*b*c*d
a*b*c/d
Run the code snippet to see a simple loop-based algorithm which checks these 7680 combinations in action. There are a surprising number of solutions for the case 1:2:3:4=12.
function findArithmetic(target, numbers) {
// PUT THE ARITHMETIC FUNCTIONS IN AN ARRAY, SO WE CAN ITERATE OVER THEM
function sum(a, b) {return a + b}
function dif(a, b) {return a - b}
function prd(a, b) {return a * b}
function div(a, b) {return a / b}
var func = [sum, dif, prd, div];
// DEFINE THE ORDER OF THE CALCULATIONS FOR THE 5 PRECEDENCE CASES
var prec = [[0, 1, 4, 2, 5, 3], // 0,1,2,3 are the four numbers
[0, 1, 2, 3, 4, 5], // 4 is the result of the 1st calculation
[1, 2, 0, 4, 5, 3], // 5 is the result of the 2nd calculation
[1, 2, 4, 3, 0, 5], // so here, do 1:2, then result1:3, then 0:result2
[2, 3, 1, 4, 0, 5]]; // and here, do 2:3, then 1:result1, then 0:result2
// FIND ALL PERMUTATIONS OF THE NUMBERS AND STORE THEM IN ARRAY "NUMS"
var nums = [];
for (var a = 0; a < 4; a++) {
for (var b = 0; b < 4; b++) {
if (a == b) continue;
for (var c = 0; c < 4; c++) {
if (a == c || b == c) continue;
for (var d = 0; d < 4; d++) {
if (a == d || b == d || c == d) continue;
nums.push([numbers[a], numbers[b], numbers[c], numbers[d]]);
}
}
}
}
// NOW GET DOWN TO BUSINESS
var solutions = [];
// ITERATE OVER ALL 24 PERMUTATIONS
for (var n = 0; n < nums.length; n++) {
// ITERATE OVER ALL 5 PRECEDENCE CASES
for (var p = 0; p < 5; p++) {
// ITERATE OVER THE 4 OPERATORS FOR THE FIRST CALCULATION
for (var i = 0; i < 4; i++) {
// ITERATE OVER THE 4 OPERATORS FOR THE SECOND CALCULATION
for (var j = 0; j < 4; j++) {
// ITERATE OVER THE 4 OPERATORS FOR THE THIRD CALCULATION
for (var k = 0; k < 4; k++) {
// DO THE CALCULATIONS
nums[n][4] = func[i](nums[n][prec[p][0]], nums[n][prec[p][1]]);
nums[n][5] = func[j](nums[n][prec[p][2]], nums[n][prec[p][3]]);
var result = func[k](nums[n][prec[p][4]], nums[n][prec[p][5]]);
// IF THE RESULT IS CORRECT, MAKE A STRING AND ADD TO SOLUTIONS
if (result == target) {
solutions.push(makeString(n, p, i, j, k));
}
}
}
}
}
}
return solutions;
// TURN THE RESULT INTO A PRESENTABLE STRING
// this is a bit fiddly, because in each precedence case, the calculations are done in a different order
function makeString(n, p, i, j, k) {
// CHOOSE THE RIGHT STRING TEMPLATE, BASED ON THE PREFERENCE CASE
var str = ["((aAb)Bc)Cd", "(aAb)B(cCd)", "(aA(bBc))Cd", "aA((bBc)Cd)", "aA(bB(cCd))"][p];
// REPLACE "a", "b", "c", AND "d" WITH THE NUMBERS
for (var c = 0; c < 4; c++) str = str.replace(["a","b","c","d"][c], nums[n][c]);
// REPLACE "A", "B" AND "C" WITH THE OPERATORS, BASED ON EXECUTION ORDER IN PREFERENCE CASE
var order = [["A","B","C"], ["A","C","B"], ["B","A","C"], ["B","C","A"], ["C","B","A"]];
for (var c = 0; c < 3; c++) str = str.replace(order[p][c], ["+","-","*","/"][[i,j,k][c]]);
return str + "=" + target;
}
}
// RUN THE FUNCTION AND DISPLAY THE RESULTS IN THE CONSOLE
var sol = findArithmetic(12, [1,2,3,4]);
document.write(sol.length + " solutions found:<BR><PRE>");
for (var s in sol) document.write(sol[s] + "<BR>");
This is a simpler solution, without the precedence array. It has the calculations for the five precedence cases written out seperately. Usually programmers would consider this an unelegant solution, because it breaks the "don't repeat yourself" rule; however, in this case it makes the code much easier to understand, and it greatly simplifies the displaying of the results, so for once I think it makes sense to do it this way.
This version only returns one solution per permutation of the numbers and combination of operators, because solutions with different bracket placement, like (a*b)+(c-d) and ((a*b)+c)-d, are really just duplicates. (That's what the continue statement after each calculation is for.)
function findArithmetic(target, numbers) {
// PUT THE ARITHMETIC FUNCTIONS IN AN ARRAY, SO WE CAN ITERATE OVER THEM
function sum(a, b) {return a + b}
function dif(a, b) {return a - b}
function prd(a, b) {return a * b}
function div(a, b) {return a / b}
var func = [sum, dif, prd, div];
// FIND ALL PERMUTATIONS OF THE NUMBERS AND STORE THEM IN ARRAY "NUMS"
var nums = [];
for (var a = 0; a < 4; a++) {
for (var b = 0; b < 4; b++) {
if (a == b) continue;
for (var c = 0; c < 4; c++) {
if (a == c || b == c) continue;
for (var d = 0; d < 4; d++) {
if (a == d || b == d || c == d) continue;
nums.push([numbers[a], numbers[b], numbers[c], numbers[d]]);
}
}
}
}
// NOW GET DOWN TO BUSINESS
var solutions = [];
var op = ["+","-","*","/"];
// ITERATE OVER ALL 24 PERMUTATIONS
for (var n = 0; n < nums.length; n++) {
var a = nums[n][0], b = nums[n][1], c = nums[n][2], d = nums[n][3];
// ITERATE OVER THE 4 OPERATORS FOR THE FIRST CALCULATION
for (var i = 0; i < 4; i++) {
// ITERATE OVER THE 4 OPERATORS FOR THE SECOND CALCULATION
for (var j = 0; j < 4; j++) {
// ITERATE OVER THE 4 OPERATORS FOR THE THIRD CALCULATION
for (var k = 0; k < 4; k++) {
// CHECK PRECEDENCE CASE 1: ((a:b):c):d
if (target == func[k](func[j](func[i](a, b), c), d)) {
solutions.push("((" + a + op[i] + b + ")" + op[j] + c + ")" + op[k] + d + "=" + target);
continue;
}
// CHECK PRECEDENCE CASE 2: (a:b):(c:d)
if (target == func[j](func[i](a, b), func[k](c, d))) {
solutions.push("(" + a + op[i] + b + ")" + op[j] + "(" + c + op[k] + d + ")=" + target);
continue;
}
// CHECK PRECEDENCE CASE 3: (a:(b:c)):d
if (target == func[k](func[i](a, func[j](b, c)), d)) {
solutions.push("(" + a + op[i] + "(" + b + op[j] + c + "))" + op[k] + d + "=" + target);
continue;
}
// CHECK PRECEDENCE CASE 4: a:((b:c):d)
if (target == func[i](a, func[k](func[j](b, c), d))) {
solutions.push(a + op[i] + "((" + b + op[j] + c + ")" + op[k] + d + ")=" + target);
continue;
}
// CHECK PRECEDENCE CASE 5: a:(b:(c:d))
if (target == func[i](a, func[j](b, func[k](c, d)))) {
solutions.push(a + op[i] + "(" + b + op[j] + "(" + c + op[k] + d + "))=" + target);
}
}
}
}
}
return solutions;
}
// RUN THE FUNCTION AND DISPLAY THE RESULTS IN THE CONSOLE
var sol = findArithmetic(2, [4,5,6,12]);
document.write(sol.length + " solutions found:<BR><PRE>");
for (var s in sol) document.write(sol[s] + "<BR>");
You are looking for binary expression trees with 4 leafs. There is always a top-level node (+,*,-,/ in your case). For a given top level node, organize your search by the number of leafs to the left of the top-level node, which must be a number in the range 1 to 3. There is a natural recursive solution since, for example, if the left side has three leafs then it itself is a binary expression tree with three leafs. You really don't need to use tree data structures -- you can use fully parenthesized strings (e.g. like "(((1 + 2) * 3) / 4)" for the tree whose top node is "/" and whose left side is the tree "((1 + 2)*3)" and whose right side is the leaf 4).
So I want to solve a problem in C
We have 10 numbers {1,1,8,1,1,3,4,9,5,2} in an array. We break the array into 3 pecies A, B, C.
And wemake the bellow procedure (I prefered to create a small diagram so you can undertand me better). Diagram here
As you see this isn't all the procedure just the start of it.
I created a code but I getting false results. What have I missed?
#define N 10
int sum_array(int* array, int first, int last) {
int res = 0;
for (int i = first ; i <= last ; i++) {
res += array[i];
}
return res;
}
int main(){
int array[N] = {1,1,8,1,1,3,4,9,5,2};
int Min = 0;
for (int A = 1; A < N - 2; A++) {
int ProfitA = sum_array(array, 0 , A-1);
int ProfitB = array[A];
int ProfitC = sum_array(array,A+1,N-1);
for (int B = 1; B < N - 1; B++) {
//here the values are "current" - valid
int temp = (ProfitA < ProfitB) ? ProfitA : ProfitB;
Min = (ProfitC < temp) ? ProfitC : temp;
//Min = std::min(std::min(ProfitA,ProfitB),ProfitC);
if (Min > INT_MAX){
Min = INT_MAX;
}
//and here they are being prepared for the next iteration
ProfitB = ProfitB + array[A+B-1];
ProfitC = ProfitC - array[A+B];
}
}
printf("%d", Min);
return 0;
}
Complexity of program is Ο(n (n+n))=O(n^2 )
To find the number of permutations here is the function : 1+0.5*N*(N-3) where N is the number of elements in the array.*
Here is the first though of the program in pseudocode. Complexity O(n^3)
//initialization, fills salary array
n:= length of salary array
best_min_maximum:=infinity
current_min_maximum:=infinity
best_bound_pos1 :=0
best_bound_pos2 :=0
for i = 0 .. (n-2):
>> for j = (i+1) .. (n-1)
>>>> current_min_maximum = max_bros_profit(salary, i, j)
>>>> if current_min_maximum < best_min_maximum:
>>>>>> best_min_maximum:=current_min_maximum
>>>>>> best_bound_pos1 :=i
>>>>>> best_bound_pos2 :=j
max_bros_profit(profit_array, position_of_bound_1, position_of_bound_2)
so max_bros_profit([8 5 7 9 6 2 1 5], 1(==1st space between days, counted from 0) , 3) is interpreted as:
8 . 5 | 7 . 9 | 6 .2 . 1 . 5 - which returns max sum of [8 5] [7 9] [6 2 1 5] => 14
> ^ - ^ - ^ - ^ - ^ - ^ - ^
> 0 , 1 , 2 , 3 , 4 , 5 , 6
This is my take. It is a greedy algorithm that starts with a maximal B range and then starts chopping off values one after another until the result cannot be improved. It hast complexity O(n).
#include <iostream>
#include <utility>
#include <array>
#include <algorithm>
#include <cassert>
// Splits an array `arr` into three sections A,B,C.
// Returns the indices to the first element of B and C.
// (the first element of A obviously has index 0)
template <typename T, ::std::size_t len>
::std::pair<::std::size_t,::std::size_t> split(T const (& arr)[len]) {
assert(len > 2);
// initialise the starting indices of section A, B, and C
// such that A: {0}, B: {1,...,len-2}, C: {len-1}
::std::array<::std::size_t,3> idx = {0,1,len-1};
// initialise the preliminary sum of all sections
::std::array<T,3> sum = {arr[0],arr[1],arr[len-1]};
for (::std::size_t i = 2; i < len-1; ++i)
sum[1] += arr[i];
// the preliminary maximum
T max = ::std::max({ sum[0], sum[1], sum[2] });
// now we iterate until section B is not empty
while ((idx[1]+1) < idx[2]) {
// in our effort to shrink B, we must decide whether to cut of the
// left-most element to A or the right-most element to C.
// So we figure out what the new sum of A and C would be if we
// did so.
T const left = (sum[0] + arr[idx[1]]);
T const right = (sum[2] + arr[idx[2]-1]);
// We always fill the smaller section first, so if A would be
// smaller than C, we slice an element off to A.
if (left <= right && left <= max) {
// We only have to update the sums to the newly computed value.
// Also we have to move the starting index of B one
// element to the right
sum[0] = left;
sum[1] -= arr[idx[1]++];
// update the maximum section sum
max = ::std::max(sum[1],sum[2]); // left cannot be greater
} else if (right < left && right <= max) {
// Similar to the other case, but here we move the starting
// index of C one to the left, effectively shrinking B.
sum[2] = right;
sum[1] -= arr[--idx[2]];
// update the maximum section sum
max = ::std::max(sum[1],sum[0]); // right cannot be greater
} else break;
}
// Finally, once we're done, we return the first index to
// B and to C, so the caller knows how our partitioning looks like.
return ::std::make_pair(idx[1],idx[2]);
}
It returns the index to the start of the B range and the index to the start of the C range.
This is your pseudocode in C (just for reference because you tagged your problem with C++ yet want a C only solution). Still, the greedy solution that bitmask provided above is a better O(N) solution; you should try to implement that algorithm instead.
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#define N 10
int sum_array(int* array, int cnt)
{
int res = 0;
int i;
for ( i = 0; i < cnt ; ++i)
res += array[i];
return res;
}
int main()
{
int array[N] = {1,1,8,1,1,3,4,9,5,2};
int Min = 0;
int bestA = 0, bestB = 0, bestMin = INT_MAX;
int A, B;
int i;
for ( A = 0; A < N - 2; ++A)
{
for ( B = A + 1; B < N - 1; ++B)
{
int ProfitA = sum_array(array, A + 1);
int ProfitB = sum_array(array + A + 1, B - A );
int ProfitC = sum_array(array + B + 1, N - 1 - B );
//here the values are "current" - valid
Min = (ProfitA > ProfitB) ? ProfitA : ProfitB;
Min = (ProfitC > Min) ? ProfitC : Min;
if( Min < bestMin )
bestA = A, bestB = B, bestMin = Min;
#if 0
printf( "%2d,%2d or (%3d,%3d,%3d) ", A, B, ProfitA, ProfitB, ProfitC );
for( i = 0; i < N; ++i )
printf( "%d%c", array[i], ( ( i == A ) || ( i == B ) ) ? '|' : ' ' );
printf( " ==> %d\n", Min);
#endif
}
}
printf("%d # %d, %d\n", bestMin, bestA, bestB);
return 0;
}
I made this solution before you removed the [C++] tag so I thought I'd go ahead and post it.
It runs in O(n*n):
const vector<int> foo{ 1, 1, 8, 1, 1, 3, 4, 9, 5, 2 }; // Assumed to be of at least size 3 For pretty printing each element is assumed to be less than 10
map<vector<int>::const_iterator, pair<int, string>> bar; // A map with key: the beginning of the C partition and value: the sum and string of that partition of C
auto mapSum = accumulate(next(foo.cbegin(), 2), foo.cend(), 0); // Find the largest possible C partition sum
auto mapString = accumulate(next(foo.cbegin(), 2), foo.cend(), string(), [](const string& init, int i){return init + to_string(i) + ' ';}); // Find the largest possible C partiont string
for (auto i = next(foo.cbegin(), 2); i < foo.cend(); mapSum -= *i++, mapString.erase(0, 2)){ // Fill the map with all possible C partitions
bar[i] = make_pair(mapSum, mapString);
}
mapSum = foo.front(); // mapSum will be reused for the current A partition sum
mapString = to_string(mapSum); // mapString will be reused for the current A partition string
cout << left;
for (auto aEnd = next(foo.cbegin()); aEnd < foo.cend(); ++aEnd){ // Iterate through all B partition beginings
auto internalSum = *aEnd; // The B partition sum
auto internalString = to_string(internalSum); // The B partition string
for (auto bEnd = next(aEnd); bEnd < foo.cend(); ++bEnd){ // Iterate through all B partition endings.
// print current partitioning
cout << "A: " << setw(foo.size() * 2 - 5) << mapString << " B: " << setw(foo.size() * 2 - 5) << internalString << " C: " << setw(foo.size() * 2 - 4) << bar[bEnd].second << "Max Sum: " << max({ mapSum, internalSum, bar[bEnd].first }) << endl;
internalSum += *bEnd; // Update B partition sum
internalString += ' ' + to_string(*bEnd); // Update B partition string
}
mapSum += *aEnd; // Update A partition sum
mapString += ' ' + to_string(*aEnd); // Update A partition string
}
In combinatorial mathematics, a Langford pairing, also called a Langford sequence, is a permutation of the sequence of 2n numbers 1, 1, 2, 2, ..., n,n in which the two ones are one unit apart, the two twos are two units apart, and more generally the two copies of each number k are k units apart.
For example:
Langford pairing for n = 3 is given by the sequence 2,3,1,2,1,3.
What is a good method to solve this in haskell or C
Can you suggest an algorithm to solve it (Do not want to use brute force)?
--------------------------EDIT----------------------
How could we define the mathematical rules to put #Rafe's code in haskell
You want to find an assignment to the variables {p1, p2, ..., pn} (where pi is the position of the first occurrence of 'i') with the following constraints holding for each pi:
pi in 1..(1+n-i)
if pi = k then forall pj where j != i
pj != k
pj != k + i
pj != k - j
pj != k + i - j
You need a sensible search strategy here. A good choice is to at each choice point choose the pi with the smallest remaining set of possible values.
Cheers!
[EDIT: second addendum.]
This is a "mostly functional" version of the imperative version I first wrote (see first addendum below). It's mostly functional in the sense that the state associated with each vertex in the search tree is independent of all other state, hence there's no need for a trail or machinery of that kind. However, I have used imperative code to implement the construction of each new domain set from a copy of the parent domain set.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MostlyFunctionalLangford
{
class Program
{
// An (effectively functional) program to compute Langford sequences.
static void Main(string[] args)
{
var n = 7;
var DInit = InitLangford(n);
var DSoln = Search(DInit);
if (DSoln != null)
{
Console.WriteLine();
Console.WriteLine("Solution for n = {0}:", n);
WriteSolution(DSoln);
}
else
{
Console.WriteLine();
Console.WriteLine("No solution for n = {0}.", n);
}
Console.Read();
}
// The largest integer in the Langford sequence we are looking for.
// [I could infer N from the size of the domain array, but this is neater.]
static int N;
// ---- Integer domain manipulation. ----
// Find the least bit in a domain; return 0 if the domain is empty.
private static long LeastBitInDomain(long d)
{
return d & ~(d - 1);
}
// Remove a bit from a domain.
private static long RemoveBitFromDomain(long d, long b)
{
return d & ~b;
}
private static bool DomainIsEmpty(long d)
{
return d == 0;
}
private static bool DomainIsSingleton(long d)
{
return (d == LeastBitInDomain(d));
}
// Return the size of a domain.
private static int DomainSize(long d)
{
var size = 0;
while (!DomainIsEmpty(d))
{
d = RemoveBitFromDomain(d, LeastBitInDomain(d));
size++;
}
return size;
}
// Find the k with the smallest non-singleton domain D[k].
// Returns zero if none exists.
private static int SmallestUndecidedDomainIndex(long[] D)
{
var bestK = 0;
var bestKSize = int.MaxValue;
for (var k = 1; k <= N && 2 < bestKSize; k++)
{
var kSize = DomainSize(D[k]);
if (2 <= kSize && kSize < bestKSize)
{
bestK = k;
bestKSize = kSize;
}
}
return bestK;
}
// Obtain a copy of a domain.
private static long[] CopyOfDomain(long[] D)
{
var DCopy = new long[N + 1];
for (var i = 1; i <= N; i++) DCopy[i] = D[i];
return DCopy;
}
// Destructively prune a domain by setting D[k] = {b}.
// Returns false iff this exhausts some domain.
private static bool Prune(long[] D, int k, long b)
{
for (var j = 1; j <= N; j++)
{
if (j == k)
{
D[j] = b;
}
else
{
var dj = D[j];
dj = RemoveBitFromDomain(dj, b);
dj = RemoveBitFromDomain(dj, b << (k + 1));
dj = RemoveBitFromDomain(dj, b >> (j + 1));
dj = RemoveBitFromDomain(dj, (b << (k + 1)) >> (j + 1));
if (DomainIsEmpty(dj)) return false;
if (dj != D[j] && DomainIsSingleton(dj) && !Prune(D, j, dj)) return false;
}
}
return true;
}
// Search for a solution from a given set of domains.
// Returns the solution domain on success.
// Returns null on failure.
private static long[] Search(long[] D)
{
var k = SmallestUndecidedDomainIndex(D);
if (k == 0) return D;
// Branch on k, trying each possible assignment.
var dk = D[k];
while (!DomainIsEmpty(dk))
{
var b = LeastBitInDomain(dk);
dk = RemoveBitFromDomain(dk, b);
var DKeqB = CopyOfDomain(D);
if (Prune(DKeqB, k, b))
{
var DSoln = Search(DKeqB);
if (DSoln != null) return DSoln;
}
}
// Search failed.
return null;
}
// Set up the problem.
private static long[] InitLangford(int n)
{
N = n;
var D = new long[N + 1];
var bs = (1L << (N + N - 1)) - 1;
for (var k = 1; k <= N; k++)
{
D[k] = bs & ~1;
bs >>= 1;
}
return D;
}
// Print out a solution.
private static void WriteSolution(long[] D)
{
var l = new int[N + N + 1];
for (var k = 1; k <= N; k++)
{
for (var i = 1; i <= N + N; i++)
{
if (D[k] == 1L << i)
{
l[i] = k;
l[i + k + 1] = k;
}
}
}
for (var i = 1; i < l.Length; i++)
{
Console.Write("{0} ", l[i]);
}
Console.WriteLine();
}
}
}
[EDIT: first addendum.]
I decided to write a C# program to solve Langford problems. It runs very quickly up to n = 16, but thereafter you need to change it to use longs since it represents domains as bit patterns.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Langford
{
// Compute Langford sequences. A Langford sequence L(n) is a permutation of [1, 1, 2, 2, ..., n, n] such
// that the pair of 1s is separated by 1 place, the pair of 2s is separated by 2 places, and so forth.
//
class Program
{
static void Main(string[] args)
{
var n = 16;
InitLangford(n);
WriteDomains();
if (FindSolution())
{
Console.WriteLine();
Console.WriteLine("Solution for n = {0}:", n);
WriteDomains();
}
else
{
Console.WriteLine();
Console.WriteLine("No solution for n = {0}.", n);
}
Console.Read();
}
// The n in L(n).
private static int N;
// D[k] is the set of unexcluded possible positions in the solution of the first k for each pair of ks.
// Each domain is represented as a bit pattern, where bit i is set iff i is in D[k].
private static int[] D;
// The trail records domain changes to undo on backtracking. T[2k] gives the element in D to undo;
// T[2k+1] gives the value to which it must be restored.
private static List<int> T = new List<int> { };
// This is the index of the next unused entry in the trail.
private static int TTop;
// Extend the trail to restore D[k] on backtracking.
private static void TrailDomainValue(int k)
{
if (TTop == T.Count)
{
T.Add(0);
T.Add(0);
}
T[TTop++] = k;
T[TTop++] = D[k];
}
// Undo the trail to some earlier point.
private static void UntrailTo(int checkPoint)
{
//Console.WriteLine("Backtracking...");
while (TTop != checkPoint)
{
var d = T[--TTop];
var k = T[--TTop];
D[k] = d;
}
}
// Find the least bit in a domain; return 0 if the domain is empty.
private static int LeastBitInDomain(int d)
{
return d & ~(d - 1);
}
// Remove a bit from a domain.
private static int RemoveBitFromDomain(int d, int b)
{
return d & ~b;
}
private static bool DomainIsEmpty(int d)
{
return d == 0;
}
private static bool DomainIsSingleton(int d)
{
return (d == LeastBitInDomain(d));
}
// Return the size of a domain.
private static int DomainSize(int d)
{
var size = 0;
while (!DomainIsEmpty(d))
{
d = RemoveBitFromDomain(d, LeastBitInDomain(d));
size++;
}
return size;
}
// Find the k with the smallest non-singleton domain D[k].
// Returns zero if none exists.
private static int SmallestUndecidedDomainIndex()
{
var bestK = 0;
var bestKSize = int.MaxValue;
for (var k = 1; k <= N && 2 < bestKSize; k++)
{
var kSize = DomainSize(D[k]);
if (2 <= kSize && kSize < bestKSize)
{
bestK = k;
bestKSize = kSize;
}
}
return bestK;
}
// Prune the other domains when domain k is reduced to a singleton.
// Return false iff this exhausts some domain.
private static bool Prune(int k)
{
var newSingletons = new Queue<int>();
newSingletons.Enqueue(k);
while (newSingletons.Count != 0)
{
k = newSingletons.Dequeue();
//Console.WriteLine("Pruning from domain {0}.", k);
var b = D[k];
for (var j = 1; j <= N; j++)
{
if (j == k) continue;
var dOrig = D[j];
var d = dOrig;
d = RemoveBitFromDomain(d, b);
d = RemoveBitFromDomain(d, b << (k + 1));
d = RemoveBitFromDomain(d, b >> (j + 1));
d = RemoveBitFromDomain(d, (b << (k + 1)) >> (j + 1));
if (DomainIsEmpty(d)) return false;
if (d != dOrig)
{
TrailDomainValue(j);
D[j] = d;
if (DomainIsSingleton(d)) newSingletons.Enqueue(j);
}
}
//WriteDomains();
}
return true;
}
// Search for a solution. Return false iff one is not found.
private static bool FindSolution() {
var k = SmallestUndecidedDomainIndex();
if (k == 0) return true;
// Branch on k, trying each possible assignment.
var dOrig = D[k];
var d = dOrig;
var checkPoint = TTop;
while (!DomainIsEmpty(d))
{
var b = LeastBitInDomain(d);
d = RemoveBitFromDomain(d, b);
D[k] = b;
//Console.WriteLine();
//Console.WriteLine("Branching on domain {0}.", k);
if (Prune(k) && FindSolution()) return true;
UntrailTo(checkPoint);
}
D[k] = dOrig;
return false;
}
// Print out a representation of the domains.
private static void WriteDomains()
{
for (var k = 1; k <= N; k++)
{
Console.Write("D[{0,3}] = {{", k);
for (var i = 1; i <= N + N; i++)
{
Console.Write("{0, 3}", ( (1 << i) & D[k]) != 0 ? i.ToString()
: DomainIsSingleton(D[k]) && (1 << i) == (D[k] << (k + 1)) ? "x"
: "");
}
Console.WriteLine(" }");
}
}
// Set up the problem.
private static void InitLangford(int n)
{
N = n;
D = new int[N + 1];
var bs = (1 << (N + N - 1)) - 1;
for (var k = 1; k <= N; k++)
{
D[k] = bs & ~1;
bs >>= 1;
}
}
}
}
I couldn't resist. Here's my port of Rafe's code to Haskell:
module Langford where
import Control.Applicative
import Control.Monad
import Data.Array
import Data.List
import Data.Ord
import Data.Tuple
import qualified Data.IntSet as S
langford :: Int -> [[Int]]
langford n
| mod n 4 `elem` [0, 3] = map (pairingToList n) . search $ initial n
| otherwise = []
type Variable = (Int, S.IntSet)
type Assignment = (Int, Int)
type Pairing = [Assignment]
initial :: Int -> [Variable]
initial n = [(i, S.fromList [1..(2*n-i-1)]) | i <- [1..n]]
search :: [Variable] -> [Pairing]
search [] = return []
search vs = do
let (v, vs') = choose vs
a <- assignments v
case prune a vs' of
Just vs'' -> (a :) <$> search vs''
Nothing -> mzero
choose :: [Variable] -> (Variable, [Variable])
choose vs = (v, filter (\(j, _) -> i /= j) vs)
where v#(i, _) = minimumBy (comparing (S.size . snd)) vs
assignments :: Variable -> [Assignment]
assignments (i, d) = [(i, k) | k <- S.toList d]
prune :: Assignment -> [Variable] -> Maybe [Variable]
prune a = mapM (prune' a)
prune' :: Assignment -> Variable -> Maybe Variable
prune' (i, k) (j, d)
| S.null d' = Nothing
| otherwise = Just (j, d')
where d' = S.filter (`notElem` [k, k+i+1, k-j-1, k+i-j]) d
pairingToList :: Int -> Pairing -> [Int]
pairingToList n = elems . array (1, 2*n) . concatMap positions
where positions (i, k) = [(k, i), (k+i+1, i)]
It seems to work quite well. Here are some timings from GHCi:
Prelude Langford> :set +s
Prelude Langford> head $ langford 4
[4,1,3,1,2,4,3,2]
(0.03 secs, 6857080 bytes)
Prelude Langford> head $ langford 32
[32,28,31,23,26,29,22,24,27,15,17,11,25,10,30,5,20,2,21,19,2,5,18,11,10, ...]
(0.05 secs, 15795632 bytes)
Prelude Langford> head $ langford 100
[100,96,99,91,94,97,90,92,95,83,85,82,93,78,76,73,88,70,89,87,69,64,86, ...]
(0.57 secs, 626084984 bytes)
Since the Langford sequences are usually generated for a small integer n, I use bogosort for this program and include a check everytime it is bogosorted. When the check completes, I'm done.
For example, with n=3:
Create an array for 2n numbers. The array would be something like this: 1 2 3 1 2 3
Employ a simple loop for bogosort and include a check every time which is quite easy.
If the check is successful, the array would give you the Langford sequence.
This will work fast for small integers only since the number of permutaions possible is n!, here: 3*2*1=6.