How to split a range into N parts - ruby

I am wondering how to split a range into N parts in ruby, While adding them to a hash with a zero based value for each range generated.
For example:
range = 1..60
p split(range, 4)
#=> {1..15 => 0, 16..30 => 1, 31..45 => 2, 46..60 => 3}
I've read How to return a part of an array in Ruby? for how to slice a range into an array, and a few others on how to convert the slices back into ranges, but I can't quite seem to piece all the pieces together to create the method I want.
Thanks for the help

range = 1..60
range.each_slice(range.last/4).with_index.with_object({}) { |(a,i),h|
h[a.first..a.last]=i }
#=> {1..15=>0, 16..30=>1, 31..45=>2, 46..60=>3}
The steps are as follows:
enum0 = range.each_slice(range.last/4)
#=> range.each_slice(60/4)
# #<Enumerator: 1..60:each_slice(15)>
You can convert this enumerator to an array to see the (4) elements it will generate and pass to each_with_index:
enum0.to_a
#=> [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
# [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
# [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45],
# [46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]]
enum1 = enum0.with_index
#=> #<Enumerator: #<Enumerator: 1..60:each_slice(15)>:with_index>
enum1.to_a
#=> [[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 0],
# [[16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], 1],
# [[31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], 2],
# [[46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60], 3]]
enum2 = enum1.with_object({})
#=> #<Enumerator: #<Enumerator: #<Enumerator: 1..60:each_slice(15)>
# :with_index>:with_object({})>
enum2.to_a
#=> [[[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 0], {}],
# [[[16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], 1], {}],
# [[[31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], 2], {}],
# [[[46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60], 3], {}]]
Carefully examine the return values for the calculations of enum1 and enum2. You might want to think of them as "compound" enumerators. The second and last element of each of enum2's four arrays is the empty hash that is represented by the block variable h. That hash will be constructed in subsequent calculations.
enum2.each { |(a,i),h| h[a.first..a.last]=i }
#=> {1..15=>0, 16..30=>1, 31..45=>2, 46..60=>3}
The first element of enum2 that is passed by each to the block (before enum.each... is executed) is
arr = enum2.next
#=>[[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 0], {}]
The block variables are assigned to the elements of arr using parallel assignment (sometimes called multiple assignment)
(a,i),h = arr
#=> [[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 0], {}]
a #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
i #=> 0
h #=> {}
The block calculation is therefore
h[a.first..a.last]=i
#=> h[1..15] = 0
Now
h #=> {1..15=>0}
The calculations are similar for each of the other 3 elements generated by enum2.
The expression
enum2.each { |(a,i),h| h[(a.first..a.last)]=i }
could alternatively be written
enum2.each { |((f,*_,l),i),h| h[(f..l)]=i }

Related

Algorithm - longest wiggle subsequence

Algorithm:
A sequence of numbers is called a wiggle sequence if the differences
between successive numbers strictly alternate between positive and
negative. The first difference (if one exists) may be either positive
or negative. A sequence with fewer than two elements is trivially a
wiggle sequence.
For example, [1,7,4,9,2,5] is a wiggle sequence because the
differences (6,-3,5,-7,3) are alternately positive and negative. In
contrast, [1,4,7,2,5] and [1,7,4,5,5] are not wiggle sequences, the
first because its first two differences are positive and the second
because its last difference is zero.
Given a sequence of integers, return the length of the longest
subsequence that is a wiggle sequence. A subsequence is obtained by
deleting some number of elements (eventually, also zero) from the
original sequence, leaving the remaining elements in their original
order.
Examples:
Input: [1,7,4,9,2,5]
Output: 6
The entire sequence is a wiggle sequence.
Input: [1,17,5,10,13,15,10,5,16,8]
Output: 7
There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8].
Input: [1,2,3,4,5,6,7,8,9]
Output: 2
My soln:
def wiggle_max_length(nums)
[ build_seq(nums, 0, 0, true, -1.0/0.0),
build_seq(nums, 0, 0, false, 1.0/0.0)
].max
end
def build_seq(nums, index, len, wiggle_up, prev)
return len if index >= nums.length
if wiggle_up && nums[index] - prev > 0 || !wiggle_up && nums[index] - prev < 0
build_seq(nums, index + 1, len + 1, !wiggle_up, nums[index])
else
build_seq(nums, index + 1, len, wiggle_up, prev)
end
end
This is working for smaller inputs (e.g [1,1,1,3,2,4,1,6,3,10,8] and for all the sample inputs, but its failing for very large inputs (which is harder to debug) like:
[33,53,12,64,50,41,45,21,97,35,47,92,39,0,93,55,40,46,69,42,6,95,51,68,72,9,32,84,34,64,6,2,26,98,3,43,30,60,3,68,82,9,97,19,27,98,99,4,30,96,37,9,78,43,64,4,65,30,84,90,87,64,18,50,60,1,40,32,48,50,76,100,57,29,63,53,46,57,93,98,42,80,82,9,41,55,69,84,82,79,30,79,18,97,67,23,52,38,74,15]
which should have output: 67 but my soln outputs 57. Does anyone know what is wrong here?
The approach tried is a greedy solution (because it always uses the current element if it satisfies the wiggle condition), but this does not always work.
I will try illustrating this with this simpler counter-example: 1 100 99 6 7 4 5 2 3.
One best sub-sequence is: 1 100 6 7 4 5 2 3, but the two build_seq calls from the algorithm will produce these sequences:
1 100 99
1
Edit: A slightly modified greedy approach does work -- see this link, thanks Peter de Rivaz.
Dynamic Programming can be used to obtain an optimal solution.
Note: I wrote this before seeing the article mentioned by #PeterdeRivaz. While dynamic programming (O(n2)) works, the article presents a superior (O(n)) "greedy" algorithm ("Approach #5"), which is also far easier to code than a dynamic programming solution. I have added a second answer that implements that method.
Code
def longest_wiggle(arr)
best = [{ pos_diff: { length: 0, prev_ndx: nil },
neg_diff: { length: 0, prev_ndx: nil } }]
(1..arr.size-1).each do |i|
calc_best(arr, i, :pos_diff, best)
calc_best(arr, i, :neg_diff, best)
end
unpack_best(best)
end
def calc_best(arr, i, diff, best)
curr = arr[i]
prev_indices = (0..i-1).select { |j|
(diff==:pos_diff) ? (arr[j] < curr) : (arr[j] > curr) }
best[i] = {} if best.size == i
best[i][diff] =
if prev_indices.empty?
{ length: 0, prev_ndx: nil }
else
prev_diff = previous_diff(diff)
j = prev_indices.max_by { |j| best[j][prev_diff][:length] }
{ length: (1 + best[j][prev_diff][:length]), prev_ndx: j }
end
end
def previous_diff(diff)
diff==:pos_diff ? :neg_diff : :pos_diff·
end
def unpack_best(best)
last_idx, last_diff =
best.size.times.to_a.product([:pos_diff, :neg_diff]).
max_by { |i,diff| best[i][diff][:length] }
return [0, []] if best[last_idx][last_diff][:length].zero?
best_path = []
loop do
best_path.unshift(last_idx)
prev_index = best[last_idx][last_diff][:prev_ndx]
break if prev_index.nil?
last_idx = prev_index·
last_diff = previous_diff(last_diff)
end
best_path
end
Examples
longest_wiggle([1, 4, 2, 6, 8, 3, 2, 5])
#=> [0, 1, 2, 3, 5, 7]]
The length of the longest wiggle is 6 and consists of the elements at indices 0, 1, 2, 3, 5 and 7, that is, [1, 4, 2, 6, 3, 5].
A second example uses the larger array given in the question.
arr = [33, 53, 12, 64, 50, 41, 45, 21, 97, 35, 47, 92, 39, 0, 93, 55, 40, 46,
69, 42, 6, 95, 51, 68, 72, 9, 32, 84, 34, 64, 6, 2, 26, 98, 3, 43, 30,
60, 3, 68, 82, 9, 97, 19, 27, 98, 99, 4, 30, 96, 37, 9, 78, 43, 64, 4,
65, 30, 84, 90, 87, 64, 18, 50, 60, 1, 40, 32, 48, 50, 76, 100, 57, 29,
arr.size 63, 53, 46, 57, 93, 98, 42, 80, 82, 9, 41, 55, 69, 84, 82, 79, 30, 79,
18, 97, 67, 23, 52, 38, 74, 15]
#=> 100
longest_wiggle(arr).size
#=> 67
longest_wiggle(arr)
#=> [0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14, 16, 17, 19, 21, 22, 23, 25,
# 27, 28, 29, 30, 32, 34, 35, 36, 37, 38, 39, 41, 42, 43, 44, 47, 49, 50,
# 52, 53, 54, 55, 56, 57, 58, 62, 63, 65, 66, 67, 70, 72, 74, 75, 77, 80,
# 81, 83, 84, 90, 91, 92, 93, 95, 96, 97, 98, 99]
As indicated, the largest wiggle is comprised of 67 elements of arr. Solution time was essentially instantaneous.
The values of arr at those indices are as follows.
[33, 53, 12, 64, 41, 45, 21, 97, 35, 47, 39, 93, 40, 46, 42, 95, 51, 68, 9,
84, 34, 64, 6, 26, 3, 43, 30, 60, 3, 68, 9, 97, 19, 27, 4, 96, 37, 78, 43,
64, 4, 65, 30, 84, 18, 50, 1, 40, 32, 76, 57, 63, 53, 57, 42, 80, 9, 41, 30,
79, 18, 97, 23, 52, 38, 74, 15]
[33, 53, 12, 64, 41, 45, 21, 97, 35, 92, 0, 93, 40, 69, 6, 95, 51, 72, 9, 84, 34, 64, 2, 98, 3, 43, 30, 60, 3, 82, 9, 97, 19, 99, 4, 96, 9, 78, 43, 64, 4, 65, 30, 90, 18, 60, 1, 40, 32, 100, 29, 63, 46, 98, 42, 82, 9, 84, 30, 79, 18, 97, 23, 52, 38, 74]
Explanation
I had intended to provide an explanation of the algorithm and its implementation, but having since learned there is a superior approach (see my note at the beginning of my answer), I have decided against doing that, but would of course be happy to answer any questions. The link in my note explains, among other things, how dynamic programming can be used here.
Let Wp[i] be the longest wiggle sequence starting at element i, and where the first difference is positive. Let Wn[i] be the same, but where the first difference is negative.
Then:
Wp[k] = max(1+Wn[k'] for k<k'<n, where A[k'] > A[k]) (or 1 if no such k' exists)
Wn[k] = max(1+Wp[k'] for k<k'<n, where A[k'] < A[k]) (or 1 if no such k' exists)
This gives an O(n^2) dynamic programming solution, here in pseudocode
Wp = [1, 1, ..., 1] -- length n
Wn = [1, 1, ..., 1] -- length n
for k = n-1, n-2, ..., 0
for k' = k+1, k+2, ..., n-1
if A[k'] > A[k]
Wp[k] = max(Wp[k], Wn[k']+1)
else if A[k'] < A[k]
Wn[k] = max(Wn[k], Wp[k']+1)
result = max(max(Wp[i], Wn[i]) for i = 0, 1, ..., n-1)
In a comment on #quertyman's answer, #PeterdeRivaz provided a link to an article that considers various approaches to solving the "longest wiggle subsequence" problem. I have implemented "Approach #5", which has a time-complexity of O(n).
The algorithm is simple as well as fast. The first step is to remove one element from each pair of consecutive elements that are equal, and continue to do so until there are no consecutive elements that are equal. For example, [1,2,2,2,3,4,4] would be converted to [1,2,3,4]. The longest wiggle subsequence includes the first and last elements of the resulting array, a, and every element a[i], 0 < i < a.size-1 for which a[i-1] < a[i] > a[i+1] ora[i-1] > a[i] > a[i+1]. In other words, it includes the first and last elements and all peaks and valley bottoms. Those elements are A, D, E, G, H, I in the graph below (taken from the above-referenced article, with permission).
Code
def longest_wiggle(arr)
arr.each_cons(2).
reject { |a,b| a==b }.
map(&:first).
push(arr.last).
each_cons(3).
select { |triple| [triple.min, triple.max].include? triple[1] }.
map { |_,n,_| n }.
unshift(arr.first).
push(arr.last)
end
Example
arr = [33, 53, 12, 64, 50, 41, 45, 21, 97, 35, 47, 92, 39, 0, 93, 55, 40,
46, 69, 42, 6, 95, 51, 68, 72, 9, 32, 84, 34, 64, 6, 2, 26, 98, 3,
43, 30, 60, 3, 68, 82, 9, 97, 19, 27, 98, 99, 4, 30, 96, 37, 9, 78,
43, 64, 4, 65, 30, 84, 90, 87, 64, 18, 50, 60, 1, 40, 32, 48, 50, 76,
100, 57, 29, 63, 53, 46, 57, 93, 98, 42, 80, 82, 9, 41, 55, 69, 84,
82, 79, 30, 79, 18, 97, 67, 23, 52, 38, 74, 15]
a = longest_wiggle(arr)
#=> [33, 53, 12, 64, 41, 45, 21, 97, 35, 92, 0, 93, 40, 69, 6, 95, 51, 72,
# 9, 84, 34, 64, 2, 98, 3, 43, 30, 60, 3, 82, 9, 97, 19, 99, 4, 96, 9,
# 78, 43, 64, 4, 65, 30, 90, 18, 60, 1, 40, 32, 100, 29, 63, 46, 98, 42,
# 82, 9, 84, 30, 79, 18, 97, 23, 52, 38, 74, 15]
a.size
#=> 67
Explanation
The steps are as follows.
arr = [3, 4, 4, 5, 2, 3, 7, 4]
enum1 = arr.each_cons(2)
#=> #<Enumerator: [3, 4, 4, 5, 2, 3, 7, 4]:each_cons(2)>
We can see the elements that will be generated by this enumerator by converting it to an array.
enum1.to_a
#=> [[3, 4], [4, 4], [4, 5], [5, 2], [2, 3], [3, 7], [7, 4]]
Continuing, remove all but one of each group of successive equal elements.
d = enum1.reject { |a,b| a==b }
#=> [[3, 4], [4, 5], [5, 2], [2, 3], [3, 7], [7, 4]]
e = d.map(&:first)
#=> [3, 4, 5, 2, 3, 7]
Add the last element.
f = e.push(arr.last)
#=> [3, 4, 5, 2, 3, 7, 4]
Next, find the peaks and valley bottoms.
enum2 = f.each_cons(3)
#=> #<Enumerator: [3, 4, 5, 2, 3, 7, 4]:each_cons(3)>
enum2.to_a
#=> [[3, 4, 5], [4, 5, 2], [5, 2, 3], [2, 3, 7], [3, 7, 4]]
g = enum2.select { |triple| [triple.min, triple.max].include? triple[1] }
#=> [[4, 5, 2], [5, 2, 3], [3, 7, 4]]
h = g.map { |_,n,_| n }
#=> [5, 2, 7]
Lastly, add the first and last values of arr.
i = h.unshift(arr.first)
#=> [3, 5, 2, 7]
i.push(arr.last)
#=> [3, 5, 2, 7, 4]

Ruby Array#include method not working as intended

Why is the include method not working well? The original question is from the Euler project, Problem 23. I couldn't figure out how to debug it.
My code:
def proper_divisors(n)
(1...n).select {|x| n % x == 0 }.inject(0){|x,y| x + y}
end
def abundant?(n)
(1...n).select {|x| n % x == 0 }.inject(0){|x,y| x + y} > n
end
def non_abundant_sums
s = 0
arr = (12..40).select { |n| n if abundant?(n) }
p arr
(1..40).each do |x|
p x unless arr.include?(proper_divisors(x) - x)
s = s + x unless arr.include?(proper_divisors(x) - x)
end
s
end
p non_abundant_sums
Using p x unless arr.include?(proper_divisors(x) - x) in the above code prints 1 through 40:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40
What I want it to print is 1 through 39:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 31, 33, 34, 35, 37, 39
A solution based on the original methods from the example.
In file problem_23.rb:
def proper_divisors(n)
(1...n).select {|x| n % x == 0 }.inject(0) {|x,y| x + y}
end
def abundant?(n)
proper_divisors(n) > n
end
def non_abundant_sum(low_n, high_n, debug=false)
puts "get all the abundant numbers within range #{low_n} to #{high_n}" if debug
arr = (low_n..high_n).select {|n| n if abundant?(n)}
puts arr.sort.inspect if debug
# http://ruby-doc.org/core-2.1.2/Array.html#method-i-repeated_combination
puts "all combinations of two abundant numbers" if debug
arr = arr.repeated_combination(2).to_a
puts arr.inspect if debug
puts "all unique sums of two abundant number combinations" if debug
arr = arr.map {|x| x[0] + x[1]}.uniq
puts arr.sort.inspect if debug
puts "only select numbers within range" if debug
arr = arr.select {|x| low_n <= x && x <= high_n}
puts arr.inspect if debug
puts "all positive integers within range" if debug
arr2 = (low_n..high_n).map {|i| i}
puts arr2.inspect if debug
puts "all positive integers less all the sums of two abundant numbers" if debug
arr = arr2 - arr
puts arr.inspect if debug
puts "sum of all the positive integers which cannot be written as the sum of two abundant numbers within range #{low_n} to #{high_n}" if debug
arr.inject(0) {|sum,n| sum + n}
end
puts non_abundant_sum(12, 40, true)
Running the code:
$ ruby problem_23.rb
get all the abundant numbers within range 12 to 40
[12, 18, 20, 24, 30, 36, 40]
all combinations of two abundant numbers
[[12, 12], [12, 18], [12, 20], [12, 24], [12, 30], [12, 36], [12, 40], [18, 18], [18, 20], [18, 24], [18, 30], [18, 36], [18, 40], [20, 20], [20, 24], [20, 30], [20, 36], [20, 40], [24, 24], [24, 30], [24, 36], [24, 40], [30, 30], [30, 36], [30, 40], [36, 36], [36, 40], [40, 40]]
all unique sums of two abundant number combinations
[24, 30, 32, 36, 38, 40, 42, 44, 48, 50, 52, 54, 56, 58, 60, 64, 66, 70, 72, 76, 80]
only select numbers within range
[24, 30, 32, 36, 38, 40]
all positive integers within range
[12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
all positive integers less all the sums of two abundant numbers
[12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 31, 33, 34, 35, 37, 39]
sum of all the positive integers which cannot be written as the sum of two abundant numbers within range 12 to 40
554

Stop Pry from putting each value of a returned array on a new line?

I watched the RubyConf 2013 talk on Pry and I have decided I ought to give it a good try.
I am working with some large arrays. It would be easier to work with my code if Pry would display returned arrays the way IRB does. What seems odd is that pry will not add newlines if the number of chars in the displayed array is small but it will add them when the number of chars in the displayed array surpasses some threshold (appears to be 26 chars in my case). Does anybody know how to make Pry stop doing this?
IRB:
main 001(0) > a = [] #=> []
main 002(0) > (1..100).each{|i| a << i} #=> 1..100
main 003(0) > a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
Pry:
[1] pry(main)> a = []
=> []
[2] pry(main)> (1..26).each{ a << 1 }
=> 1..26
[3] pry(main)> a
=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[4] pry(main)> a << 1
=> [1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1]
Edit your .pryrc file to include
Pry.config.print = proc { |output, value| output.puts "=> #{value.inspect}" }
To get pry to print inline like robertjlooby's answer, but retain the pretty-printing:
# in your .pryrc
Pry.config.print = lambda do |output, value, _pry_|
_pry_.pager.open do |pager|
pager.print _pry_.config.output_prefix
Pry::ColorPrinter.pp(value, pager, 9e99)
end
end
adapted from pry source

How to get a specific sequence like this?

There are 100 numbers:
1, 1, 2, 2, 3, 3,.. 50, 50.
How can I get a sequence which has one number between the two 1s, two numbers between the two 2s, three numbers between the two 3s,.. and fifty numbers between the two 50s using the hundred numbers?
Does anyone have a better idea than brute force? Or prove it there's no solution when n = 50.
The Problem: Langford Pairing
The problem is known as Langford Pairing. From Wikipedia:
These sequences are named after C. Dudley Langford, who posed the problem of constructing them in 1958. As Knuth1 describes, the problem of listing ALL Langford pairings for a given N can be solved as an instance of the exact cover problem (one of Karp's 21 NP-complete problem), but for large N the number of solutions can be calculated more efficiently by algebraic methods.
1: The Art of Computer Programming, IV, Fascicle 0: Introduction to Combinatorial Algorithms and Boolean Functions
It's worth noting that there is no solution for N = 50. Solutions only exist for N = 4k or N = 4k - 1. This is proven in a paper by Roy A. Davies (On Langford's Problem II, Math. Gaz. 43, 253-255, 1959), which also gives the pattern to construct a single solution for any feasible N.
Related links
John Miller's page on Langford's Problem
A Perl program based on Roy A. Davies' pattern
Dave Moore's pattern
mathworld.wolfram - Langford's Problem
A CSP model for Microsoft Solver Foundation
Brute force in Java
Here are some solutions that my quick and dirty brute force program was able to find for N < 100. Nearly all of these were found in under a second.
3 [3, 1, 2, 1, 3, 2]
4 [4, 1, 3, 1, 2, 4, 3, 2]
7 [7, 3, 6, 2, 5, 3, 2, 4, 7, 6, 5, 1, 4, 1]
8 [8, 3, 7, 2, 6, 3, 2, 4, 5, 8, 7, 6, 4, 1, 5, 1]
11 [11, 6, 10, 2, 9, 3, 2, 8, 6, 3, 7, 5, 11, 10, 9, 4, 8, 5, 7, 1, 4, 1]
12 [12, 10, 11, 6, 4, 5, 9, 7, 8, 4, 6, 5, 10, 12, 11, 7, 9, 8, 3, 1, 2, 1, 3, 2]
15 [15, 13, 14, 8, 5, 12, 7, 11, 4, 10, 5, 9, 8, 4, 7, 13, 15, 14, 12, 11, 10, 9, 6, 3, 1, 2, 1, 3, 2, 6]
16 [16, 14, 15, 9, 7, 13, 3, 12, 6, 11, 3, 10, 7, 9, 8, 6, 14, 16, 15, 13, 12, 11, 10, 8, 5, 2, 4, 1, 2, 1, 5, 4]
19 [19, 17, 18, 14, 8, 16, 9, 15, 6, 1, 13, 1, 12, 8, 11, 6, 9, 10, 14, 17, 19, 18, 16, 15, 13, 12, 11, 7, 10, 3, 5, 2, 4, 3, 2, 7, 5, 4]
20 [20, 18, 19, 15, 11, 17, 10, 16, 9, 5, 14, 1, 13, 1, 12, 5, 11, 10, 9, 15, 18, 20, 19, 17, 16, 14, 13, 12, 8, 4, 7, 3, 6, 2, 4, 3, 2, 8, 7, 6]
23 [23, 21, 22, 18, 16, 20, 12, 19, 11, 8, 17, 4, 1, 15, 1, 14, 4, 13, 8, 12, 11, 16, 18, 21, 23, 22, 20, 19, 17, 15, 14, 13, 10, 7, 9, 3, 5, 2, 6, 3, 2, 7, 5, 10, 9, 6]
24 [24, 22, 23, 19, 17, 21, 13, 20, 10, 8, 18, 4, 1, 16, 1, 15, 4, 14, 8, 10, 13, 12, 17, 19, 22, 24, 23, 21, 20, 18, 16, 15, 14, 11, 12, 7, 9, 3, 5, 2, 6, 3, 2, 7, 5, 11, 9, 6]
27 [27, 25, 26, 22, 20, 24, 17, 23, 12, 13, 21, 7, 4, 19, 1, 18, 1, 4, 16, 7, 15, 12, 14, 13, 17, 20, 22, 25, 27, 26, 24, 23, 21, 19, 18, 16, 15, 14, 11, 9, 10, 5, 2, 8, 3, 2, 6, 5, 3, 9, 11, 10, 8, 6]
28 [28, 26, 27, 23, 21, 25, 18, 24, 15, 13, 22, 10, 6, 20, 1, 19, 1, 3, 17, 6, 16, 3, 10, 13, 15, 18, 21, 23, 26, 28, 27, 25, 24, 22, 20, 19, 17, 16, 14, 12, 9, 7, 11, 4, 2, 5, 8, 2, 4, 7, 9, 5, 12, 14, 11, 8]
31 [31, 29, 30, 26, 24, 28, 21, 27, 18, 16, 25, 13, 11, 23, 6, 22, 5, 1, 20, 1, 19, 6, 5, 17, 11, 13, 16, 18, 21, 24, 26, 29, 31, 30, 28, 27, 25, 23, 22, 20, 19, 17, 15, 12, 14, 9, 10, 2, 3, 4, 2, 8, 3, 7, 4, 9, 12, 10, 15, 14, 8, 7]
32 [32, 30, 31, 27, 25, 29, 22, 28, 19, 17, 26, 13, 11, 24, 6, 23, 5, 1, 21, 1, 20, 6, 5, 18, 11, 13, 16, 17, 19, 22, 25, 27, 30, 32, 31, 29, 28, 26, 24, 23, 21, 20, 18, 16, 15, 12, 14, 9, 10, 2, 3, 4, 2, 8, 3, 7, 4, 9, 12, 10, 15, 14, 8, 7]
35 [35, 33, 34, 30, 28, 32, 25, 31, 22, 20, 29, 17, 14, 27, 10, 26, 5, 6, 24, 1, 23, 1, 5, 21, 6, 10, 19, 14, 18, 17, 20, 22, 25, 28, 30, 33, 35, 34, 32, 31, 29, 27, 26, 24, 23, 21, 19, 18, 16, 13, 15, 12, 9, 4, 2, 11, 3, 2, 4, 8, 3, 7, 9, 13, 12, 16, 15, 11, 8, 7]
36 [36, 34, 35, 31, 29, 33, 26, 32, 23, 21, 30, 17, 14, 28, 10, 27, 5, 6, 25, 1, 24, 1, 5, 22, 6, 10, 20, 14, 19, 17, 18, 21, 23, 26, 29, 31, 34, 36, 35, 33, 32, 30, 28, 27, 25, 24, 22, 20, 19, 18, 16, 13, 15, 12, 9, 4, 2, 11, 3, 2, 4, 8, 3, 7, 9, 13, 12, 16, 15, 11, 8, 7]
40 [40, 38, 39, 35, 33, 37, 30, 36, 27, 25, 34, 22, 20, 32, 17, 31, 13, 11, 29, 7, 28, 3, 1, 26, 1, 3, 24, 7, 23, 11, 13, 21, 17, 20, 22, 25, 27, 30, 33, 35, 38, 40, 39, 37, 36, 34, 32, 31, 29, 28, 26, 24, 23, 21, 19, 16, 18, 15, 12, 4, 6, 14, 2, 5, 4, 2, 10, 6, 9, 5, 8, 12, 16, 15, 19, 18, 14, 10, 9, 8]
43 [43, 41, 42, 38, 36, 40, 33, 39, 30, 28, 37, 25, 23, 35, 20, 34, 16, 14, 32, 5, 31, 8, 6, 29, 2, 5, 27, 2, 26, 6, 8, 24, 14, 16, 22, 20, 23, 25, 28, 30, 33, 36, 38, 41, 43, 42, 40, 39, 37, 35, 34, 32, 31, 29, 27, 26, 24, 22, 21, 19, 17, 15, 18, 12, 7, 1, 3, 1, 13, 4, 3, 11, 7, 10, 4, 9, 12, 15, 17, 19, 21, 18, 13, 11, 10, 9]
44 [44, 42, 43, 39, 37, 41, 34, 40, 31, 29, 38, 26, 24, 36, 20, 35, 16, 14, 33, 5, 32, 8, 6, 30, 2, 5, 28, 2, 27, 6, 8, 25, 14, 16, 23, 20, 22, 24, 26, 29, 31, 34, 37, 39, 42, 44, 43, 41, 40, 38, 36, 35, 33, 32, 30, 28, 27, 25, 23, 22, 21, 19, 17, 15, 18, 12, 7, 1, 3, 1, 13, 4, 3, 11, 7, 10, 4, 9, 12, 15, 17, 19, 21, 18, 13, 11, 10, 9]
52 [52, 50, 51, 47, 45, 49, 42, 48, 39, 37, 46, 34, 32, 44, 29, 43, 26, 24, 41, 20, 40, 16, 14, 38, 7, 9, 36, 2, 35, 3, 2, 33, 7, 3, 31, 9, 30, 14, 16, 28, 20, 27, 24, 26, 29, 32, 34, 37, 39, 42, 45, 47, 50, 52, 51, 49, 48, 46, 44, 43, 41, 40, 38, 36, 35, 33, 31, 30, 28, 27, 25, 23, 21, 19, 22, 15, 8, 6, 1, 18, 1, 17, 4, 5, 6, 8, 13, 4, 12, 5, 11, 15, 10, 19, 21, 23, 25, 22, 18, 17, 13, 12, 11, 10]
55 [55, 53, 54, 50, 48, 52, 45, 51, 42, 40, 49, 37, 35, 47, 32, 46, 29, 27, 44, 23, 43, 20, 17, 41, 10, 11, 39, 4, 38, 8, 2, 36, 4, 2, 34, 10, 33, 11, 8, 31, 17, 30, 20, 23, 28, 27, 29, 32, 35, 37, 40, 42, 45, 48, 50, 53, 55, 54, 52, 51, 49, 47, 46, 44, 43, 41, 39, 38, 36, 34, 33, 31, 30, 28, 26, 24, 25, 21, 19, 16, 22, 9, 14, 6, 3, 18, 7, 5, 3, 15, 6, 9, 13, 5, 7, 12, 16, 14, 19, 21, 24, 26, 25, 22, 18, 15, 13, 1, 12, 1]
63 [63, 61, 62, 58, 56, 60, 53, 59, 50, 48, 57, 45, 43, 55, 40, 54, 37, 35, 52, 32, 51, 29, 27, 49, 23, 20, 47, 17, 46, 12, 9, 44, 10, 3, 42, 2, 41, 3, 2, 39, 9, 38, 12, 10, 36, 17, 20, 34, 23, 33, 27, 29, 32, 35, 37, 40, 43, 45, 48, 50, 53, 56, 58, 61, 63, 62, 60, 59, 57, 55, 54, 52, 51, 49, 47, 46, 44, 42, 41, 39, 38, 36, 34, 33, 31, 28, 30, 25, 26, 22, 19, 8, 18, 24, 11, 6, 4, 21, 5, 7, 8, 4, 6, 16, 5, 15, 11, 7, 13, 14, 19, 18, 22, 25, 28, 26, 31, 30, 24, 21, 16, 15, 13, 1, 14, 1]
64 [64, 62, 63, 59, 57, 61, 54, 60, 51, 49, 58, 46, 44, 56, 41, 55, 38, 36, 53, 33, 52, 29, 27, 50, 23, 20, 48, 17, 47, 12, 9, 45, 10, 3, 43, 2, 42, 3, 2, 40, 9, 39, 12, 10, 37, 17, 20, 35, 23, 34, 27, 29, 32, 33, 36, 38, 41, 44, 46, 49, 51, 54, 57, 59, 62, 64, 63, 61, 60, 58, 56, 55, 53, 52, 50, 48, 47, 45, 43, 42, 40, 39, 37, 35, 34, 32, 31, 28, 30, 25, 26, 22, 19, 8, 18, 24, 11, 6, 4, 21, 5, 7, 8, 4, 6, 16, 5, 15, 11, 7, 13, 14, 19, 18, 22, 25, 28, 26, 31, 30, 24, 21, 16, 15, 13, 1, 14, 1]
67 [67, 65, 66, 62, 60, 64, 57, 63, 54, 52, 61, 49, 47, 59, 44, 58, 41, 39, 56, 36, 55, 33, 30, 53, 26, 24, 51, 20, 50, 13, 11, 48, 12, 3, 46, 4, 45, 3, 7, 43, 4, 42, 11, 13, 40, 12, 7, 38, 20, 37, 24, 26, 35, 30, 34, 33, 36, 39, 41, 44, 47, 49, 52, 54, 57, 60, 62, 65, 67, 66, 64, 63, 61, 59, 58, 56, 55, 53, 51, 50, 48, 46, 45, 43, 42, 40, 38, 37, 35, 34, 32, 29, 31, 28, 25, 23, 21, 27, 18, 9, 10, 2, 5, 22, 2, 8, 6, 19, 5, 9, 17, 10, 16, 6, 8, 14, 15, 18, 21, 23, 25, 29, 28, 32, 31, 27, 22, 19, 17, 16, 14, 1, 15, 1]
72 [72, 70, 71, 67, 65, 69, 62, 68, 59, 57, 66, 54, 52, 64, 49, 63, 46, 44, 61, 41, 60, 38, 36, 58, 33, 30, 56, 27, 55, 23, 20, 53, 17, 14, 51, 10, 50, 5, 3, 48, 4, 47, 3, 5, 45, 4, 10, 43, 14, 42, 17, 20, 40, 23, 39, 27, 30, 37, 33, 36, 38, 41, 44, 46, 49, 52, 54, 57, 59, 62, 65, 67, 70, 72, 71, 69, 68, 66, 64, 63, 61, 60, 58, 56, 55, 53, 51, 50, 48, 47, 45, 43, 42, 40, 39, 37, 35, 32, 34, 31, 28, 26, 24, 22, 29, 15, 13, 8, 6, 25, 7, 12, 9, 11, 21, 6, 8, 19, 7, 18, 13, 15, 9, 16, 12, 11, 22, 24, 26, 28, 32, 31, 35, 34, 29, 25, 21, 19, 18, 2, 16, 1, 2, 1]
75 [75, 73, 74, 70, 68, 72, 65, 71, 62, 60, 69, 57, 55, 67, 52, 66, 49, 47, 64, 44, 63, 41, 39, 61, 36, 33, 59, 30, 58, 26, 24, 56, 20, 17, 54, 14, 53, 5, 6, 51, 7, 50, 3, 5, 48, 6, 3, 46, 7, 45, 14, 17, 43, 20, 42, 24, 26, 40, 30, 33, 38, 36, 39, 41, 44, 47, 49, 52, 55, 57, 60, 62, 65, 68, 70, 73, 75, 74, 72, 71, 69, 67, 66, 64, 63, 61, 59, 58, 56, 54, 53, 51, 50, 48, 46, 45, 43, 42, 40, 38, 37, 35, 32, 29, 34, 28, 25, 23, 31, 12, 15, 9, 11, 27, 21, 4, 13, 10, 8, 22, 4, 9, 12, 19, 11, 18, 15, 8, 10, 16, 13, 23, 25, 29, 28, 32, 21, 35, 37, 34, 31, 27, 22, 19, 18, 2, 16, 1, 2, 1]
76 [76, 74, 75, 71, 69, 73, 66, 72, 63, 61, 70, 58, 56, 68, 53, 67, 50, 48, 65, 45, 64, 42, 40, 62, 36, 33, 60, 30, 59, 26, 24, 57, 20, 17, 55, 14, 54, 5, 6, 52, 7, 51, 3, 5, 49, 6, 3, 47, 7, 46, 14, 17, 44, 20, 43, 24, 26, 41, 30, 33, 39, 36, 38, 40, 42, 45, 48, 50, 53, 56, 58, 61, 63, 66, 69, 71, 74, 76, 75, 73, 72, 70, 68, 67, 65, 64, 62, 60, 59, 57, 55, 54, 52, 51, 49, 47, 46, 44, 43, 41, 39, 38, 37, 35, 32, 29, 34, 28, 25, 23, 31, 12, 15, 9, 11, 27, 21, 4, 13, 10, 8, 22, 4, 9, 12, 19, 11, 18, 15, 8, 10, 16, 13, 23, 25, 29, 28, 32, 21, 35, 37, 34, 31, 27, 22, 19, 18, 2, 16, 1, 2, 1]
83 [83, 81, 82, 78, 76, 80, 73, 79, 70, 68, 77, 65, 63, 75, 60, 74, 57, 55, 72, 52, 71, 49, 47, 69, 44, 42, 67, 39, 66, 36, 33, 64, 30, 27, 62, 23, 61, 17, 14, 59, 15, 58, 7, 4, 56, 5, 11, 54, 4, 53, 7, 5, 51, 14, 50, 17, 15, 48, 11, 23, 46, 27, 45, 30, 33, 43, 36, 39, 42, 44, 47, 49, 52, 55, 57, 60, 63, 65, 68, 70, 73, 76, 78, 81, 83, 82, 80, 79, 77, 75, 74, 72, 71, 69, 67, 66, 64, 62, 61, 59, 58, 56, 54, 53, 51, 50, 48, 46, 45, 43, 41, 38, 40, 37, 34, 32, 29, 26, 35, 25, 16, 13, 24, 31, 8, 6, 3, 28, 12, 9, 3, 10, 6, 8, 22, 13, 21, 16, 20, 9, 19, 12, 10, 18, 26, 25, 29, 24, 32, 34, 38, 37, 41, 40, 35, 31, 28, 22, 21, 20, 19, 2, 18, 1, 2, 1]
84 [84, 82, 83, 79, 77, 81, 74, 80, 71, 69, 78, 66, 64, 76, 61, 75, 58, 56, 73, 53, 72, 50, 48, 70, 45, 43, 68, 39, 67, 36, 33, 65, 30, 27, 63, 23, 62, 17, 14, 60, 15, 59, 7, 4, 57, 5, 11, 55, 4, 54, 7, 5, 52, 14, 51, 17, 15, 49, 11, 23, 47, 27, 46, 30, 33, 44, 36, 39, 42, 43, 45, 48, 50, 53, 56, 58, 61, 64, 66, 69, 71, 74, 77, 79, 82, 84, 83, 81, 80, 78, 76, 75, 73, 72, 70, 68, 67, 65, 63, 62, 60, 59, 57, 55, 54, 52, 51, 49, 47, 46, 44, 42, 41, 38, 40, 37, 34, 32, 29, 26, 35, 25, 16, 13, 24, 31, 8, 6, 3, 28, 12, 9, 3, 10, 6, 8, 22, 13, 21, 16, 20, 9, 19, 12, 10, 18, 26, 25, 29, 24, 32, 34, 38, 37, 41, 40, 35, 31, 28, 22, 21, 20, 19, 2, 18, 1, 2, 1]
87 [87, 85, 86, 82, 80, 84, 77, 83, 74, 72, 81, 69, 67, 79, 64, 78, 61, 59, 76, 56, 75, 53, 51, 73, 48, 46, 71, 43, 70, 39, 36, 68, 33, 30, 66, 27, 65, 23, 17, 63, 14, 62, 16, 7, 60, 12, 3, 58, 4, 57, 3, 7, 55, 4, 54, 14, 17, 52, 12, 16, 50, 23, 49, 27, 30, 47, 33, 36, 45, 39, 44, 43, 46, 48, 51, 53, 56, 59, 61, 64, 67, 69, 72, 74, 77, 80, 82, 85, 87, 86, 84, 83, 81, 79, 78, 76, 75, 73, 71, 70, 68, 66, 65, 63, 62, 60, 58, 57, 55, 54, 52, 50, 49, 47, 45, 44, 42, 40, 41, 37, 35, 32, 38, 31, 28, 26, 24, 34, 8, 15, 9, 11, 6, 29, 13, 5, 10, 8, 25, 6, 9, 5, 22, 11, 21, 15, 20, 10, 13, 18, 19, 24, 26, 28, 32, 31, 35, 37, 40, 42, 41, 38, 34, 29, 25, 22, 21, 20, 18, 2, 19, 1, 2, 1]
95 [95, 93, 94, 90, 88, 92, 85, 91, 82, 80, 89, 77, 75, 87, 72, 86, 69, 67, 84, 64, 83, 61, 59, 81, 56, 54, 79, 51, 78, 48, 46, 76, 43, 40, 74, 36, 73, 33, 30, 71, 26, 70, 18, 15, 68, 17, 9, 66, 6, 65, 13, 14, 63, 4, 62, 6, 9, 60, 4, 15, 58, 18, 57, 17, 13, 55, 14, 26, 53, 30, 52, 33, 36, 50, 40, 49, 43, 46, 48, 51, 54, 56, 59, 61, 64, 67, 69, 72, 75, 77, 80, 82, 85, 88, 90, 93, 95, 94, 92, 91, 89, 87, 86, 84, 83, 81, 79, 78, 76, 74, 73, 71, 70, 68, 66, 65, 63, 62, 60, 58, 57, 55, 53, 52, 50, 49, 47, 45, 42, 39, 44, 38, 35, 32, 41, 31, 28, 34, 25, 37, 16, 12, 7, 11, 8, 3, 5, 10, 29, 3, 7, 27, 5, 8, 12, 11, 24, 16, 10, 23, 19, 20, 21, 22, 25, 28, 32, 31, 35, 39, 38, 42, 34, 45, 47, 44, 41, 37, 29, 27, 19, 24, 20, 23, 21, 2, 22, 1, 2, 1]
96 [96, 94, 95, 91, 89, 93, 86, 92, 83, 81, 90, 78, 76, 88, 73, 87, 70, 68, 85, 65, 84, 62, 60, 82, 57, 55, 80, 52, 79, 49, 46, 77, 43, 40, 75, 36, 74, 33, 30, 72, 26, 71, 18, 15, 69, 17, 9, 67, 6, 66, 13, 14, 64, 4, 63, 6, 9, 61, 4, 15, 59, 18, 58, 17, 13, 56, 14, 26, 54, 30, 53, 33, 36, 51, 40, 50, 43, 46, 48, 49, 52, 55, 57, 60, 62, 65, 68, 70, 73, 76, 78, 81, 83, 86, 89, 91, 94, 96, 95, 93, 92, 90, 88, 87, 85, 84, 82, 80, 79, 77, 75, 74, 72, 71, 69, 67, 66, 64, 63, 61, 59, 58, 56, 54, 53, 51, 50, 48, 47, 45, 42, 39, 44, 38, 35, 32, 41, 31, 28, 34, 25, 37, 16, 12, 7, 11, 8, 3, 5, 10, 29, 3, 7, 27, 5, 8, 12, 11, 24, 16, 10, 23, 19, 20, 21, 22, 25, 28, 32, 31, 35, 39, 38, 42, 34, 45, 47, 44, 41, 37, 29, 27, 19, 24, 20, 23, 21, 2, 22, 1, 2, 1]
For instructional purposes, here's the source code:
import java.util.*;
public class LangfordPairing {
static void langford(int N) {
BitSet bs = new BitSet();
bs.set(N * 2);
put(bs, N, new int[2 * N]);
}
static void put(BitSet bs, int n, int[] arr) {
if (n == 0) {
System.out.println(Arrays.toString(arr));
System.exit(0); // one is enough!
}
for (int i = -1, L = bs.length() - n - 1;
(i = bs.nextClearBit(i + 1)) < L ;) {
final int j = i + n + 1;
if (!bs.get(j)) {
arr[i] = n;
arr[j] = n;
bs.flip(i);
bs.flip(j);
put(bs, n - 1, arr);
bs.flip(i);
bs.flip(j);
}
}
}
public static void main(String[] args) {
langford(87);
}
}
Solutions for some N values are missing; they are known to require an abnormally large number of operations just to find the first solution by brute force.
Note that as mentioned, there are generally many solutions for any given N. For N = 7, there are 26 solutions:
[7, 3, 6, 2, 5, 3, 2, 4, 7, 6, 5, 1, 4, 1]
[7, 2, 6, 3, 2, 4, 5, 3, 7, 6, 4, 1, 5, 1]
[7, 2, 4, 6, 2, 3, 5, 4, 7, 3, 6, 1, 5, 1]
[7, 3, 1, 6, 1, 3, 4, 5, 7, 2, 6, 4, 2, 5]
[7, 1, 4, 1, 6, 3, 5, 4, 7, 3, 2, 6, 5, 2]
[7, 1, 3, 1, 6, 4, 3, 5, 7, 2, 4, 6, 2, 5]
[7, 4, 1, 5, 1, 6, 4, 3, 7, 5, 2, 3, 6, 2]
[7, 2, 4, 5, 2, 6, 3, 4, 7, 5, 3, 1, 6, 1]
[5, 7, 2, 6, 3, 2, 5, 4, 3, 7, 6, 1, 4, 1]
[3, 7, 4, 6, 3, 2, 5, 4, 2, 7, 6, 1, 5, 1]
[5, 7, 4, 1, 6, 1, 5, 4, 3, 7, 2, 6, 3, 2]
[5, 7, 2, 3, 6, 2, 5, 3, 4, 7, 1, 6, 1, 4]
[1, 7, 1, 2, 6, 4, 2, 5, 3, 7, 4, 6, 3, 5]
[5, 7, 1, 4, 1, 6, 5, 3, 4, 7, 2, 3, 6, 2]
[1, 7, 1, 2, 5, 6, 2, 3, 4, 7, 5, 3, 6, 4]
[2, 7, 4, 2, 3, 5, 6, 4, 3, 7, 1, 5, 1, 6]
[6, 2, 7, 4, 2, 3, 5, 6, 4, 3, 7, 1, 5, 1]
[2, 6, 7, 2, 1, 5, 1, 4, 6, 3, 7, 5, 4, 3]
[3, 6, 7, 1, 3, 1, 4, 5, 6, 2, 7, 4, 2, 5]
[5, 1, 7, 1, 6, 2, 5, 4, 2, 3, 7, 6, 4, 3]
[2, 3, 7, 2, 6, 3, 5, 1, 4, 1, 7, 6, 5, 4]
[4, 1, 7, 1, 6, 4, 2, 5, 3, 2, 7, 6, 3, 5]
[5, 2, 7, 3, 2, 6, 5, 3, 4, 1, 7, 1, 6, 4]
[3, 5, 7, 4, 3, 6, 2, 5, 4, 2, 7, 1, 6, 1]
[3, 5, 7, 2, 3, 6, 2, 5, 4, 1, 7, 1, 6, 4]
[2, 4, 7, 2, 3, 6, 4, 5, 3, 1, 7, 1, 6, 5]
Related links
John Miller - Langford's Problem - Oddity for some N values
OEIS A014552 - Number of solutions to Langford problem
Attachments
Source code and output on ideone.com
There is only a solution to this problem for pairs of numbers from 1-n where n = 4m or n = 4m-1 for any positive integer m.
Update:
For any solution the odd number pairs must occupy two odd-numbered or two even-numbered positions. The even number pairs must occupy one of each. When there are an odd number of odd pairs (eg. 1 1 2 2 3 3 4 4 5 5 - 3 odd pairs) there is no solution. There's no way to place the first number of each pair, without resulting in a clash when you try to place the second.
See http://en.wikipedia.org/wiki/Langford_pairing
Another update:
My answer was basically from Knuth. I've been thinking it through, though, and came up with the following on my own.
For any sequence {1 1 2 2 ... n n} there are, say, m odd pairs, n-m even pairs, and 2n positions in which to place them (i.e. n positions of each parity).
If you place the even pairs first then you use n-m even positions and n-m odd positions, thus you have m positions of each parity left in which to place the odd pairs.
The odd pairs must be placed in positions of the same parity. If m is even there is no problem because half the pairs will will be placed in odd positions, and half in even positions.
If m is odd, however, you can only place m-1 of the odd pairs, at which point you'll have one odd pair left to place, and one position of each parity. As the odd pair requires positions of the same parity there is no solution when m (the number of odd pairs) is odd.
I adopted an elimination approach with paper and pencil for L(2,7).
Place the two 7s. Just three possibilities
Place the two 6s and so on.
It is obvious when placing the 1s, 2s, and 3s simultaneously whether there is a solution or not.
I found 18 of the 26 solutions thus.
When time and paper permits I will tackle L(2,8).
I'm pretty sure I've seen this in Knuth's "The Art of Computer Programming". I'll look it up when I get home tonight.
I think a good heuristic would be to start with the biggest numbers. You'll still need backtracking though.
The problem with the problem is that having a solution for n-1 usually doesn't help you much to find a solution for n.
Is it always possible? I can see the pattern is probable and not definite. It doesn't work for 1s or 1s and 2s.
If it is probablistic, the best idea would be to start with brute force and keep on eliminating wrong options as an when you encounter them.

How do I generate an array of pairwise distances in Ruby?

Say I have an array that represents a set of points:
x = [2, 5, 8, 33, 58]
How do I generate an array of all the pairwise distances?
x = [2, 5, 8, 33, 58]
print x.collect {|n| x.collect {|i| (n-i).abs}}.flatten
I think that would do it.
x.map{|i| x.map{|j| (i-j).abs } }
gives
[[0, 3, 6, 31, 56],
[3, 0, 3, 28, 53],
[6, 3, 0, 25, 50],
[31, 28, 25, 0, 25],
[56, 53, 50, 25, 0]]
(format it like this by printing it with 'pp' instead of puts)
and
x.map{|i| x.map{|j| (i-j).abs } }.flatten
gives
[0, 3, 6, 31, 56, 3, 0, 3, 28, 53, 6, 3, 0, 25, 50, 31, 28, 25, 0, 25, 56, 53, 50, 25, 0]
if you really want an array
If you really do want an array instead of a matrix, this is O(n^2/2) instead of O(n^2).
result=[]
x.each_index{|i| (i+1).upto(x.size-1){|j| result<<(x[i]-x[j]).abs}}

Resources