find modular multiplicative inverse - wolfram-mathematica

is it possible to find the solution of following: 9^(-1)%M ie inverse of 9 modulo M where 2<=M<=10^9 it may not be a prime and gcd(9,M) may not be 1 if not possible to find such a solution is there any method to solve: ((10^n-1)/9)%M 1<=n<=10^16

Since this is tagged wolfram-mathematica I assume you are asking in the context of Mathematica, in which case there is a built-in function to do this:
PowerMod[9,-1,m]
This will give you the inverse of 9, modulo m, for whatever value of m you want.
Table[PowerMod[9,-1,m],{m,2,1000}]
will produce:
PowerMod::ninv: 0 is not invertible modulo 3. >>
PowerMod::ninv: 3 is not invertible modulo 6. >>
PowerMod::ninv: 0 is not invertible modulo 9. >>
General::stop: Further output of PowerMod::ninv will be
suppressed during this calculation. >>
{1, PowerMod[9, -1, 3], 1, 4, PowerMod[9, -1, 6], 4, 1,
PowerMod[9, -1, 9], 9, 5, PowerMod[9, -1, 12], 3, 11,
PowerMod[9, -1, 15], 9, 2, PowerMod[9, -1, 18], 17, 9,
PowerMod[9, -1, 21], 5, 18, PowerMod[9, -1, 24], 14, 3,
PowerMod[9, -1, 27], 25, 13, PowerMod[9, -1, 30], 7, 25,
PowerMod[9, -1, 33], 19, 4, PowerMod[9, -1, 36], 33, 17,
PowerMod[9, -1, 39], 9, 32, PowerMod[9, -1, 42], 24, 5,
PowerMod[9, -1, 45], 41, 21, PowerMod[9, -1, 48], 11, 39,
PowerMod[9, -1, 51], 29, 6, PowerMod[9, -1, 54], 49, 25,
PowerMod[9, -1, 57], 13, 46, PowerMod[9, -1, 60], 34, 7,
PowerMod[9, -1, 63], 57, 29, PowerMod[9, -1, 66], 15, 53,
PowerMod[9, -1, 69], 39, 8, PowerMod[9, -1, 72], 65, 33,
PowerMod[9, -1, 75], 17, 60, PowerMod[9, -1, 78], 44, 9,
PowerMod[9, -1, 81], 73, 37, PowerMod[9, -1, 84], 19, 67,
PowerMod[9, -1, 87], 49, 10, PowerMod[9, -1, 90], 81, 41,
PowerMod[9, -1, 93], 21, 74, PowerMod[9, -1, 96], 54, 11,
PowerMod[9, -1, 99], 89}
You can get rid of the invalid output from that list with:
Select[%, IntegerQ]
which gives:
{1, 1, 4, 4, 1, 9, 5, 3, 11, 9, 2, 17, 9, 5, 18, 14, 3, 25, 13, 7,
25, 19, 4, 33, 17, 9, 32, 24, 5, 41, 21, 11, 39, 29, 6, 49, 25, 13,
46, 34, 7, 57, 29, 15, 53, 39, 8, 65, 33, 17, 60, 44, 9, 73, 37, 19,
67, 49, 10, 81, 41, 21, 74, 54, 11, 89}
If you want to think smart, you can also organize this table better by skipping the elements that are not coprime with 9. One way to achieve this using more advanced Mathematica syntax would be:
Map[{#, PowerMod[9, -1, m]} &, Select[Range[100], GCD[#, 9] == 1 &]]
which gives you output:
{{2, 1}, {4, 1}, {5, 4}, {7, 4}, {8, 1}, {10, 9}, {11, 5}, {13, 3},
{14, 11}, {16, 9}, {17, 2}, {19, 17}, {20, 9}, {22, 5}, {23, 18},
{25, 14}, {26, 3}, {28, 25}, {29, 13}, {31, 7}, {32, 25}, {34, 19},
{35, 4}, {37, 33}, {38, 17}, {40, 9}, {41, 32}, {43, 24}, {44, 5},
{46, 41}, {47, 21}, {49, 11}, {50, 39}, {52, 29}, {53, 6}, {55, 49},
{56, 25}, {58, 13}, {59, 46}, {61, 34}, {62, 7}, {64, 57}, {65, 29},
{67, 15}, {68, 53}, {70, 39}, {71, 8}, {73, 65}, {74, 33}, {76, 17},
{77, 60}, {79, 44}, {80, 9}, {82, 73}, {83, 37}, {85, 19}, {86, 67},
{88, 49}, {89, 10}, {91, 81}, {92, 41}, {94, 21}, {95, 74}, {97, 54},
{98, 11}, {100, 89}}
That gives you a list of pairs, and each pair has the m value and then the inverse of 9 modulo that m value. For example, {61,34} is on that list, which means 9*34 is 1 mod 61. You can check that this is right.

Related

Even distribution of numbers in array

My problem is that I have a given array of n numbers between 1 and 100. The goal is to pick 5 numbers which result in a minimum total distance. The total distance is calculated by summing up the distance of each number in the initial array to the closest of the 5 picked numbers.
What I (sort of) tried and thought about:
Taking the average number of the array and dividing it by 5 to get something useful?
Dividing the array length by 5, that numbers x and then the first number is array[x] the second one is array[x*2] and so on
Example
Input [5, 10, 15, 20, ..., 85, 90, 95, 100]
Output [10, 30, 50, 70, 90]
(There might be a better output but I hope this makes the goal clear)
As you can see I'm pretty lost and just can't come up with a solution. There probably is a super easy solution to this that I just don't get.
I am just looking for a hint not a solution, I wan't to figure that out myself.
Here is an algorithm that works in polynomial time.
First, sort your array of n things. Next, calculate a 2-dim array which for every 0 <= i <= j < n contains the index of the optimal element to fill the range from the ith element to the jth element. Fill out a similar array of the total distance for each interval from that optimal array.
As an example with the above sample output, the first 2-dim array could look like:
optimal_index = [
[ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9],
[ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10],
[ 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10],
[ 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11],
[ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11],
[ 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12],
[ 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12],
[ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13],
[ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13],
[ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14],
[10, 10, 11, 11, 12, 12, 13, 13, 14, 14],
[11, 11, 12, 12, 13, 13, 14, 14, 15],
[12, 12, 13, 13, 14, 14, 15, 15],
[13, 13, 14, 14, 15, 15, 16],
[14, 14, 15, 15, 16, 16],
[15, 15, 16, 16, 17],
[16, 16, 17, 17],
[17, 17, 18],
[18, 18],
[19],
]
where the index of the optimal element for the range from i to j is at optimal_index[i][j-i]. With the same indexing scheme, the cost matrix would be:
optimal_cost = [
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280, 320, 360, 405, 450, 500],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280, 320, 360, 405, 450],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280, 320, 360, 405],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280, 320, 360],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280, 320],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100],
[ 0, 5, 10, 20, 30, 45, 60, 80],
[ 0, 5, 10, 20, 30, 45, 60],
[ 0, 5, 10, 20, 30, 45],
[ 0, 5, 10, 20, 30],
[ 0, 5, 10, 20],
[ 0, 5, 10],
[ 0, 5],
[ 0],
]
Now what about if we fill ranges with 2 elements? This is a question of taking each range, and looking the costs at each point we could divide it. That new data structure just needs to contain the places to separate between "closest to first element" and "closest to second". From this division we can take any range and quickly divide it into the optimal 2, then tell you what the two selected elements are, and the total cost. This can be filled in with a similar matrix. Note that the previous optimal_cost matrix will make these calculations very straightforward.
Next, what about ranges with 4 elements? This is exactly the same as ranges of 2 elements, except that we are now dividing between the first pair and the second pair. But the logic is the same.
And finally, what about our problem with 5 elements? That's just a question of calculating the optimal division between closest to the first 4 elements and closest to the last one. So just try all of the possibilities.
The natural generalization of this to filling k things in an array of size n is O(n^3 log(k)).

Re-numbering residues in PDB file with biopython

I have a sequence alignment as:
RefSeq :MXKQRSLPLXQKRTKQAISFSASHRIYLQRKFSH .....
Templatepdb:-----------------ISFSASHR------FSHAQADFAG
I am trying to write a code that re-number residues based on this alignment in PDB file as:
original pdb : RES ID= 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 4 4 4 4 4 5 ...
new pdb : RES ID = 18 18 18 19 19 19 19 19 20 20 20 21 21 22 23 24 25 31 31 31 31 32 32 33 34 35 36 ...
If alignment only has gaps at beginning of alignment, easy to figure out. Only count gaps("-") and add sum of gaps in to residue.id= " " "sum of gap" " "
However, I could not find a way if there are gaps in the middle of the sequence.
Do you have any suggestions?
If I understand it correctly,
Your input is an alignment:
'-----------------ISFSASHR------FSHAQADFAG'
and a list of residue numbers:
[1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 18, 18, 18, 18]
And your output is the residue number shifted by the number of gaps before the residue:
[18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 25, 25, 25, 25, 32, 32, 32, 33, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 41, 41, 41, 41]
Below is the code to demonstrate it. There are numerous ways to calculate the output.
The way I do it is to keep a dictionary shift_dict with key as the original number and value as the shifted number.
import itertools
import random
def random_residue_number(sequence):
nested = [[i + 1] * random.randint(1, 10) for i in range(len(sequence))]
merged = list(itertools.chain.from_iterable(nested))
return merged
def aligned_residue_number(alignment, original_number):
gap_shift = 0
residue_count = 0
shift_dict = {}
for residue in alignment:
if residue == '-':
gap_shift += 1
else:
residue_count += 1
shift_dict[residue_count] = gap_shift + residue_count
return [shift_dict[number] for number in original_number]
sequence = 'ISFSASHRFSHAQADFAG'
alignment = '-----------------ISFSASHR------FSHAQADFAG'
original_number = random_residue_number(sequence)
print(original_number)
# [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 18, 18, 18, 18]
new_number = aligned_residue_number(alignment, original_number)
print(new_number)
# [18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 25, 25, 25, 25, 32, 32, 32, 33, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 41, 41, 41, 41]

How to split a range into N parts

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 }

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