Given a n*n-sized multi-headed acyclic graph where each node has at most three children and three parents, is there an non-exponential algorithm to identify whether a n-length path exists where no two nodes share the same value, and every value of a set is accounted for?
Basically, I have an n*n maze where each space has a random value (1..n). I need to find a path (from the top to the bottom) of n nodes that includes every value.
Right now I'm using a depth-first search, but that is T(n) = 3T(n-1) + O(1), which is O(3^n), a non-ideal solution.
Either confirming my fears, or pointing me in the right direction would be much appreciated.
Edit: to make this a little bit more concrete, here is a maze with solutions (solved using the depth-first solution).
1 2 5 5 4
1 5 1 3 5
4 1 2 3 2
5 5 4 4 3
4 2 1 2 4
S3, 5, 1, 3, 4, 2, F4
S3, 5, 1, 3, 4, 2, F2
S3, 5, 1, 3, 4, 2, F4
S3, 5, 3, 2, 4, 1, F3
S3, 5, 3, 2, 4, 1, F3
S3, 5, 3, 2, 4, 1, F3
S4, 5, 3, 2, 4, 1, F3
S4, 5, 3, 2, 4, 1, F3
S4, 5, 3, 2, 4, 1, F3
S4, 5, 1, 3, 4, 2, F4
S4, 5, 1, 3, 4, 2, F2
S4, 5, 1, 3, 4, 2, F4
S5, 4, 3, 2, 5, 1, F3
13 total paths`
This problem is NP-complete, and so it is not known whether or not there is a polynomial-time solution. (The standard provisos of possibly being easy in practice, etc., all apply.) One possible reduction is from 3SAT.
Suppose we have a 3SAT instance, such as (a ∨ b ∨ c) ∧ (¬a ∨ ¬b ∨ ¬c). I will show how to use "gadgets" to build an instance of your problem. Before we begin, rewrite the 3SAT problem as (a1 ∨ b1 ∨ c1) ∧ (¬a2 ∨ ¬b2 ∨ ¬c2) together with a1 = a2, b1 = b2, and c1 = c2; that is, make each occurrence of a variable unique, but then add the condition that different occurrences of the same variable must be equal.
First, we make sure that you must pick the number 0 in the first row, so that we can use it later as a "sentinel" that you must avoid.
0 0 0
Now, we build a gadget that enforces the a1 = a2 rule: (The underscore _ here is a new unique number in every use of this gadget)
0 _ 0
a1 0 ¬a1
a2 0 ¬a2
Because of the first row, you must avoid the 0s. This means you either take the path "a1, a2" or the path "¬a1, ¬a2"; the former will correspond to (slightly confusingly) setting a to false, while the latter will correspond to a setting a to true. This is because our clause gadget is really easy then, because we simply write down the clause, e.g. (again _ here is a new variable each time):
0 _ 0
a1 b1 b2
or
0 _ 0
¬a1 ¬b1 ¬b2
Finally, since you've only used one of a1 and ¬a1, etc., we let you take the ones you haven't used freely:
0 _ 0
a1 ¬a1 0
Now, this doesn't quite work, because one of a1 and ¬a1 might have been used in the variable choice gadget, while the other could have been used in a clause. So, we include a new variable #i for each clause that you can take instead of one of the variables. So if variable a1 appears in clause 1, we have
0 _ 0
a1 ¬a1 #1
Here's the complete output of a translation of the original 3SAT clause (highlighting the path corresponding to setting a and b to true, c to false, and picking a from the first clause), with numbers on the left and gloss on the right. The gadgets are re-ordered (first clause gadgets, then for each variable, the equality gadget and then unused gadget), but this doesn't matter since they're independent anyway.
0 0 < 0 . . < .
0 8 < 0 . _ < .
2 < 4 6 a1 < b1 c1
0 16 < 0 . _ .
11 13 15 < -a2 -b2 -c2<
0 17 < 0 . _ < .
2 0 3 < a1 . -a1<
10 0 11 < a2 . -a2<
0 18 < 0 . _ < .
2 3 1 < a1 -a1 #1 <
0 19 < 0 . _ .
10 < 11 9 a2 < -a2 #2
0 20 < 0 . _ < .
4 0 5 < b1 . -b1<
12 0 13 < b2 . -b2<
0 21 < 0 . _ < .
4 < 5 1 b1 < -b1 #1
0 22 < 0 . _ < .
12 < 13 9 b2 < -b2 #2
0 23 < 0 . _ < .
6 < 0 7 c1 < . -c1
14 < 0 15 c2 < . -c2
0 24 < 0 . _ < .
6 7 < 1 c1 -c1< #1
0 25 < 0 . _ < .
14 15 9 < c2 -c2 #2 <
(If you want the whole thing to be square, just include a bunch of zeros at the end of each line.) It's fun to see that no matter how you solve this, at heart, you're solving that 3SAT problem.
At the end of my post is a hastily-written Perl program that generates one of your problems from an input of the form
a b c
-a -b -c
The number of variables in the resulting instance of your problem is 11C + V + 1. Give the program the -r switch to produce gloss instead of numbers.
# Set useful output defaults
$, = "\t"; $\ = "\n";
# Process readability option and force sentinel
my $r = "0";
if( $ARGV[0] =~ /-r/ ) { shift; $r = "."; }
print $r, $r, $r;
# Clause gadgets
my( %v, %c, $m, $c );
$m = 1;
while( <> ) {
my( #v, #m );
$c = $m++;
chomp; #v = split;
for my $v ( #v ) {
push #{$v{strip($v)}}, -1; # hack, argh!
push #m, ($r ? $v.#{$v{strip($v)}} : $m + neg($v));
$c{($r ? (strip($v).#{$v{strip($v)}}) : $m)} = $c;
$v{strip($v)}->[-1] = ($r ? (strip($v).#{$v{strip($v)}}) : $m);
$m += 2 unless $r;
}
print $r, newv(), $r;
print #m;
}
# Variable gadget
for my $v ( sort keys %v ) {
# Force equal
print $r, newv(), $r;
for my $n ( #{$v{$v}} ) {
print $n, $r, ($r ? "-".$n : $n+1);
}
# Unused
for my $n ( #{$v{$v}} ) {
print $r, newv(), $r;
print $n, ($r ? "-".$n : $n+1), ($r ? "\#".$c{$n} : $c{$n});
}
}
# Strip leading -
sub strip {
my( $v ) = #_;
return substr $v, neg($v);
}
# Is this variable negative?
sub neg {
my( $v ) = #_;
return "-" eq substr( $v, 0, 1 );
}
# New, unused variable
sub newv {
return "_" if $r;
return $m++;
}
I'm pretty sure this can be done in polynomial time. I would start with a an empty set and then loop through the rows top to bottom. I'm going to skip any kind of code and show you what the state would look like at each step you should be able to put together an algorithm from there. I'm pretty sure the best case is slightly worse than O(n^2) using a variation of breadth first search and keeping track of the current good paths in a table.
EDIT: If this still isn't fast enough you can improve it by applying Harlequin's optimization.
For Example:
1 2 3
3 2 1
1 2 1
State 0:
R = 0 // Row
P = {} // Path Set
// {{Path so far}, Column}
P' = {
{{1}, 0}
{{2}, 1}
{{3}, 2}
}
P = P'
State 1:
R = 1 // ROW
P = {
{{1}, 0}
{{2}, 1}
{{3}, 2}
}
P' = {
{{1 3}, 0}
{{1 2}, 1}
{{2 3}, 0}
{{2 1}, 2}
{{3 2}, 1}
{{3 1}, 2}
}
State 2:
R = 2
P = {
{{1 3}, 0}
{{1 2}, 1}
{{2 3}, 0}
{{2 1}, 2}
{{3 2}, 1}
{{3 1}, 2}
}
P' = {
{{1 3 2}, 1}
{{2 3 1}, 0}
{{3 2 1}, 0}
{{3 2 1}, 2}
{{3 1 2}, 1}
}
Result:
Path Count: 5
S1 1 3 2 F2
S2 2 3 1 F1
S3 3 2 1 F1
S3 3 2 1 F3
S3 3 1 2 F2
You can try the ant colony optimization. It quickly yields very good results that are very close to the perfect solution.
One optimization for Kevin Loney's solution might be to merge partial paths that contain the same elements at the same column. You would have to note the number of merges with the path if you want to know the number of solutions at the end.
Example: In your 5x5 example, when you arrive at the third row, the third column has three paths leading to it that contain (1 2 5) in some order. You don't have to follow these separately from this point, but can merge them. If you want to know the number of solutions at the end, you just have to adjust your path data structure, e.g. three (1 (1 2 5)) would merge to (3 (1 2 5)).
Look up A* search. It is your friend.
Related
This question already has answers here:
Recover original array from all subsets
(3 answers)
Closed 3 years ago.
I recently came acrosss this question in an hiring challenge :
Given array S of 2^N integers(1 <= N <= 20, 0 <= Si <= 10^9) representing subset sums of an array A, we need to recover array A in sorted order.
e.g. S = {2, 1, 0, 3} => A = {1, 2} as subset sums of A are {0, 1, 2, 1+2}
The order of number in array S may be random.
How can I approach this problem ? Thanks in advance.
You can sort the array containing the subset sums
When u sort the subset sum array
Ai = S[2^i] -- should give you the values of array A in sorted order.
You can make a truth table to get subset sum and trace back
Assuming S is a valid input
eg: S = { 0, 5, 3, 8, 1, 6, 4, 9 }
Sorted S = {0, 1, 3, 4, 5, 6, 8, 9}
A = [A0, A1, A2] ---
A0,A1,A2 -- (Binary, part of subset = 1 not part = 0 )
Index | A0,A1,A2 | Sorted Sum
0 0 0 0 0
1 1 0 0 1
2 0 1 0 3
3 1 1 0 4
4 0 0 1 5
5 1 0 1 6
6 0 1 1 8
7 1 1 1 9
From her we can reverse and find that A0 = S[2^0], A1 = S[2^1], A2 = S[2^2]
The question is to find the number of 5 digits numbers possible using 1, 2, 3, 4, and 5 as digits, in which the set of first k numbers (k is natural number, and k < 5) is not equal to set of numbers from 1 to k.
Clarification - Order of elements of set does not matter. {1, 2} is same as {2, 1} ie {1, 2} = {2, 1}.
For example, in 54213 is a correct number and it will be counted - as
k = 1, we get {5}, and {5} != {1}
k = 2, {5, 4} != {1, 2}
k = 3, {5, 4, 2} != {1, 2, 3}
k = 4, {5, 4, 2, 1} != {1, 2, 3, 4}
Also, the number 13245 is not valid, as for k = 1, {1} = {1}.
Bonus question, find the number of 6 digit possible numbers with same criteria and digits 1, 2, 3, 4, 5, & 6.
Edit - I am sorry for not having followed this up with my method. I have added my solution below.
Number of 5 digit numbers possible with the given digits = 5! = 120
Let's consider the digits that are NOT to be formed.
1 _ _ _ _ = 4! = 24 (As clearly, k = 1 {1} = {1})
2 1 _ _ _ = 3! = 6 (As clearly, k = 2 {2, 1} = {1, 2}, also we will not consider 1 2 _ _ _ as it has already been included in 1)
2 3 1 _ _ = 2! = 2
3 1 2 _ _ = 2! = 2
3 2 1 _ _ = 2! = 2
2 3 4 1 _ = 1
2 4 1 3 _ = 1
2 4 3 1 _ = 1
3 1 4 2 _ = 1
3 2 4 1 _ = 1
3 4 2 1 _ = 1
3 4 1 2 _ = 1
4 - - - _ = 3! x 1 = 6 (Where dashes can be filled by 1, 2, 3)
Total number = 49
But there are the NOT cases. Now, the cases required = 120 - 49 = 71.
For 6, I used recursion, as clearly in case of 5, the series (for the numbers that are NOT to be formed) is
1 x 4! + 1 x 3! + 3 x 2! + 13 x 1! (where 1, 1, 3, and 13 is the solution for the given condition for 1 digit, 2, digit, 3 digit and 4 digit respectively)
{ie, for 1 digit number using only 1, where k < 1, k is natural, number of possible digits - 1 (1). For 2 digit number using only 1, 2, where k < 2, the number of possible digits - 1 (21). For 3, it is 321, 231, 312 and so on)
Hence, for 6, the series becomes
1 x 5! + 1 x 4! + 3 x 3! + 13 x 2! + 71 (where 71 is the solution for given condition of 5 digits)
= 259
ie. for 6, the solutions = 6! - 259 = 461
I know that, for a k-permutation p of size k, built from n elements, there are:
P(n, k) = n! / (n - k)!
possible k-permutations. For example:
k = 2
n = 4
l = [1, 2, 3, 4]
P(n, k) = 4! / (4 - 2)! = 12
1 2 | 2 1 | 3 1 | 4 1
1 3 | 2 3 | 3 2 | 4 2
1 4 | 2 4 | 3 4 | 4 3
And yet another example:
k = 3
n = 4
l = [1, 2, 3, 4]
P(n, k) = 4! / (4 - 3)! = 24
1 2 3 | 2 1 3 | 3 1 2 | 4 1 2
1 2 4 | 2 1 4 | 3 1 4 | 4 1 3
1 3 2 | 2 3 1 | 3 2 1 | 4 2 1
1 3 4 | 2 3 4 | 3 2 4 | 4 2 3
1 4 2 | 2 4 1 | 3 4 1 | 4 3 1
1 4 3 | 2 4 3 | 3 4 2 | 4 3 2
So, how do I find the index of the k-permutation p? Consider the permutations
to be generated lexicographically.
Edit:
I could start by finding in which "block" p is, addressing the block by the first element of p. For example, for p = [3, 2, 4], the index for p should be at least 12 (counting from 0 to P(n, k) - 1).
But then, to find the second element inside that "block", I'd have to see what are the remaining items to be found, and in which position they will be. I mean, I'd be eventually addressing the list [1, 4], and 4 would be at position 2, so simply using the element as key would require some extra manipulation.
I could use a hash to look up the elements and update their positions, but it'd give me a O(n^2) time complexity. Is it possible to do any better?
The number of permutations for a given digit in a given position is given by a formula
(n-digit position)! / (n-k)! where digit position starts on the left with 1.
To get the number of preceding permutations for a given permutation (that is, its index), multiply the formula for each digit by the number of preceding digits not already used, and add them up.
Example 1, k = 2, n = 4, p = [3,4]
First digit, 3:
(4-1)! / (4-2)! * (number of unused preceding digits, 2) = 6
There are six permutations preceding the first that has 3 in position 1.
Second digit, 4:
(4-2)! / (4-2)! * (number of unused preceding digits, 2) = 2
There are two permutations preceding the first that has 4 in position 2.
Zero based index: 6 + 2 = 8.
Example 2, k = 3, n = 4, p = [3,2,4]
First digit, 3:
(4-1)! / (4-3)! * (number of unused preceding digits, 2) = 12
There are 12 permutations preceding the first that has 3 in position 1.
Second digit, 2:
(4-2)! / (4-3)! * (number of unused preceding digits, 1) = 2
There are two permutations preceding the first that has 2 in position 2.
Third digit, 4:
(4-3)! / (4-3)! * (number of unused preceding digits, 1) = 1
There is one permutation preceding the first that has 4 in position 3.
Zero based index: 12 + 2 + 1 = 15.
TXR language:
$ txr -p "(pos '(1 4 3) (perm '(1 2 3 4) 3))"
5
It is brute force, however; of course pos knows nothing about the structure of permutations.
Use binary search tree (BST). Store all you numbers in it before you start and delete them after you use one. To find x-th element maintain .subtreeSize for every vertex and just descend the tree to find the number you need. Pseudocode:
def findXth(x):
curVertex = BST.root
while:
curPosition = curVertex.leftChild.subtreeSize
if curPosition == x: return curVertex.value
elif curPosition > x: curVertex = curVertex.leftChild
elif curPosition < x: curVertex = curVertex.rightChild
Don't forget to check for vertices existence and to delete the vertex you find.
Overall complexity is going to be O(n log n).
you can reference below function
/**
* list all k or <=k size permutation of a given list with n unique elements.
* n can be bigger than 64. this function will take O(K^N) time, Bad.
*
* #param uniqueList
* #param permutationSize
* #param permutation
* #param only Only show the permutation of permutationSize,
* else show all permutation of less than or equal to permutationSize.
*/
public static void my_permutationOf(List<Integer> uniqueList, int permutationSize, List<Integer> permutation, boolean only) {
if (permutation == null) {
assert 0 < permutationSize && permutationSize <= uniqueList.size();
permutation = new ArrayList<>(permutationSize);
if (!only) {
System.out.println(Arrays.toString(permutation.toArray()));
}
}
for (int i : uniqueList) {
if (permutation.contains(i)) {
continue;
}
permutation.add(i);
if (!only) {
System.out.println(Arrays.toString(permutation.toArray()));
} else if (permutation.size() == permutationSize) {
System.out.println(Arrays.toString(permutation.toArray()));
}
if (permutation.size() < permutationSize) {
my_permutationOf(uniqueList, permutationSize, permutation, only);
}
permutation.remove(permutation.size() - 1);
}
}
E.g. you can think the element is the index
public static void main(String[] args) throws Exception {
my_permutationOf(new ArrayList<Integer>() {
{
add(0);
add(1);
add(2);
add(3);
}
}, 3, null, true);
}
the result is
[0, 1, 2]
[0, 1, 3]
[0, 2, 1]
[0, 2, 3]
[0, 3, 1]
[0, 3, 2]
[1, 0, 2]
[1, 0, 3]
[1, 2, 0]
[1, 2, 3]
[1, 3, 0]
[1, 3, 2]
[2, 0, 1]
[2, 0, 3]
[2, 1, 0]
[2, 1, 3]
[2, 3, 0]
[2, 3, 1]
[3, 0, 1]
[3, 0, 2]
[3, 1, 0]
[3, 1, 2]
[3, 2, 0]
[3, 2, 1]
I'm looking for a way to reduce the length of a huge list with the Total function and a threshold parameter. I would like to avoid the use of For and If (coming from old habits).
Example :
List that I want to "reduce" :{1,5,3,8,11,3,4} with a threshold of 5.
Output that I want : {6,11,11,7}
That means that I use the Total function on the first parts of the list and look if the result of this function is higher than my threshold. If so, I use the result of the Total function and go to the next part of the list.
Another example is {1,1,1,1,1} with a threshold of 5. Result should be {5}.
Thanks!
EDIT : it is working but it is pretty slow. Any ideas in order to be faster?
EDIT 2 : the loop stuff (quit simple and not smart)
For[i = 1, i < Length[mylist] + 1, i++,
sum = sum + mylist[[i]];
If[sum > Threshold ,
result = Append[result , sum]; sum = 0; ]; ];
EDIT 3 : I have now a new thing to do.
I have to work now with a 2D list like {{1,2}{4,9}{1,3}{0,5}{7,3}}
It is more or less the same idea but the 1st and 2nd part of the list have to be higher than the thresold stuff (both of them).
Example : If lst[[1]] and lst[[2]] > threshold do the summuation for each part of the 2D list. I tried to adapt the f2 function from Mr.Wizard for this case but I didn't succeed. If it is easier, I can provide 2 independant lists and work with this input f3[lst1_,lst2_,thres_]:=
Reap[Sow#Fold[If[Element of the lst1 > thr && Element of the lst2, Sow##; #2, # + #2] &, 0, lst1]][[2, 1]] for example.
EDIT 4 :
You are right, it is not really clear. But the use of the Min## > thr statement is working perfectly.
Old code (ugly and not smart at all):
sumP = 0;
resP = {};
sumU = 0;
resU = {};
For[i = 1, i < Length[list1 + 1, i++,
sumP = sumP + list1[[i]];
sumU = sumU + list2[[i]];
If[sumP > 5 && sumU > 5 ,
resP = Append[resP, sumP]; sumP = 0;
resU = Append[resU, sumU]; sumU = 0;
];
]
NEW fast by Mr.Wizard :
f6[lst_, thr_] :=
Reap[Sow#Fold[If[Min## > thr , Sow##1; #2, #1 + #2] &, 0, lst]][[2,
1]]
That ~40times faster. Thanks a lot.
Thread[{resP, resU}] == f6[Thread[{list1,list2}], 5] True
I recommend using Fold for this kind of operation, combined with either linked lists or Sow and Reap to accumulate results. Append is slow because lists in Mathematica are arrays and must be reallocated every time an element is appended.
Starting with:
lst = {2, 6, 4, 4, 1, 3, 1, 2, 4, 1, 2, 4, 0, 7, 4};
Here is the linked-list version:
Flatten # Fold[If[Last## > 5, {#, #2}, {First##, Last## + #2}] &, {{}, 0}, lst]
{8, 8, 7, 7, 11, 4}
This is what the output looks like before Flatten:
{{{{{{{}, 8}, 8}, 7}, 7}, 11}, 4}
Here is the method using Sow and Reap:
Reap[Sow # Fold[If[# > 5, Sow##; #2, # + #2] &, 0, lst]][[2, 1]]
{8, 8, 7, 7, 11, 4}
A similar method applied to other problems: (1) (2)
The Sow # on the outside of Fold effectively appends the last element of the sequence which would otherwise be dropped by the algorithm.
Here are the methods packaged as functions, along with george's for easy comparison:
f1[lst_, thr_] :=
Flatten # Fold[If[Last## > thr, {#, #2}, {First##, Last## + #2}] &, {{}, 0}, lst]
f2[lst_, thr_] :=
Reap[Sow#Fold[If[# > thr, Sow##; #2, # + #2] &, 0, lst]][[2, 1]]
george[t_, thresh_] := Module[{i = 0, s},
Reap[While[i < Length[t], s = 0;
While[++i <= Length[t] && (s += t[[i]]) < thresh]; Sow[s]]][[2, 1]]
]
Timings:
big = RandomInteger[9, 500000];
george[big, 5] // Timing // First
1.279
f1[big, 5] // Timing // First
f2[big, 5] // Timing // First
0.593
0.468
Here is the obvious approach which is oh 300x faster.. Pretty isn't always best.
t = Random[Integer, 10] & /# Range[2000];
threshold = 4;
Timing[
i = 0;
t0 = Reap[
While[i < Length[t], s = 0;
While[++i <= Length[t] && (s += t[[i]]) < threshold ];
Sow[s]]][[2, 1]]][[1]]
Total[t] == Total[t0]
Timing[ t1 =
t //. {a___, b_ /; b < threshold, c_, d___} -> {a, b + c, d} ][[1]]
t1 == t0
I interpret your requirement as:
if an element in the list is less than the threshold value, add it to the next element in the list;
repeat this process until the list no longer changes.
So, for the threshold 5 and the input list {1,5,3,8,11,3,4} you'ld get
{6,3,8,11,3,4}
{6,11,11,3,4}
{6,11,11,7}
EDIT
I've now tested this solution to your problem ...
Implement the operation by using a replacement rule:
myList = {1,5,3,8,11,3,4}
threshold = 5
mylist = mylist //. {a___, b_ /; b < threshold, c_, d___} :> {a, b+c, d}
Note the use of ReplaceRepeated (symbolification //.).
I would like to populate an n * n (n being odd) matrix in the following way:
_ _ _ 23 22 21 20
_ _ 24 10 9 8 37
_ 25 11 3 2 19 36
26 12 4 1 7 18 35
27 13 5 6 17 34 _
28 14 15 16 33 _ _
29 30 31 32 _ _ _
What is an easy way to do this using Mathematica?
With this helper function:
Clear[makeSteps];
makeSteps[0] = {};
makeSteps[m_Integer?Positive] :=
Most#Flatten[
Table[#, {m}] & /# {{-1, 0}, {-1, 1}, {0, 1}, {1, 0}, {1, -1}, {0, -1}}, 1];
We can construct the matrix as
constructMatrix[n_Integer?OddQ] :=
Module[{cycles, positions},
cycles = (n+1)/2;
positions =
Flatten[FoldList[Plus, cycles + {#, -#}, makeSteps[#]] & /#
Range[0, cycles - 1], 1];
SparseArray[Reverse[positions, {2}] -> Range[Length[positions]]]];
To get the matrix you described, use
constructMatrix[7] // MatrixForm
The idea behind this is to examine the pattern that the positions of consecutive numbers 1.. follow. You can see that these form the cycles. The zeroth cycle is trivial - contains a number 1 at position {0,0} (if we count positions from the center). The next cycle is formed by taking the first number (2) at position {1,-1} and adding to it one by one the following steps: {0, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 0} (as we move around the center). The second cycle is similar, but we have to start with {2,-2}, repeat each of the previous steps twice, and add the sixth step (going up), repeated only once: {0, -1}. The third cycle is analogous: start with {3,-3}, repeat all the steps 3 times, except {0,-1} which is repeated only twice. The auxiliary function makeSteps automates the process. In the main function then, we have to collect all positions together, and then add to them {cycles, cycles} since they were counted from the center, which has a position {cycles,cycles}. Finally, we construct the SparseArray out of these positions.
I don't know the Mathematica syntax but I guess you could use an algorithm like this:
start in the middle of the matrix
enter a 1 into the middle
go up-right (y-1 / x+1)
set integer iter=1
set integer num=2
while cursor is in matrix repeat:
enter num in current field
increase num by 1
repeat iter times:
go left (x-1 / y)
enter num in current field
increase num by 1
repeat iter times:
go down-left (x-1 / y+1)
enter num in current field
increase num by 1
repeat iter times:
go down (x / y+1)
enter num in current field
increase num by 1
repeat iter times:
go right (x+1 / y)
enter num in current field
increase num by 1
repeat iter times:
go up-right (x+1 / y-1)
enter num in current field
increase num by 1
repeat iter-1 times:
go up (x / y-1)
enter num in current field
increase num by 1
go up-up-right (y-2 / x+1)
increase iter by 1
you can also pretty easily convert this algorithm into a functional version or into a tail-recursion.
Well, you will have to check in the while loop if you aren't out of bounds as well. If n is odd then you can just count num up while:
m = floor(n/2)
num <= n*n - (m+m*m)
I'm pretty sure that there's a simpler algorithm but that's the most intuitive one to me.
The magic numbers on the diagonal starting at 1 and going up right can be arrived at from
f[n_] := 2 Sum[2 m - 1, {m, 1, n}] + UnitStep[n - 3] Sum[2 m, {m, 1, n - 2}]
In := f#Range#5
Out := {2, 8, 20, 38, 62}
With this it should be easy to set up a SparseArray. I'll play around with it a bit and see how hard that is.
First version:
i = 10;
a = b = c = Array[0 &, {2 (2 i + 1), 2 (2 i + 1)}];
f[n_] := 3*n*(n + 1) + 1;
k = f[i - 2];
p[i_Integer] :=
ToRules#Reduce[
-x + y < i - 1 && -x + y > -i + 1 &&
(2 i + 1 - x)^2 + (2 i + 1 - y)^2 <= 2 i i - 2 &&
3 i - 1 > x > i + 1 &&
3 i - 1 > y > i + 1, {x, y}, Integers];
((a[[Sequence ## #]] = 1) & /# ({x, y} /. {p[i]}));
((a[[Sequence ## (# + {2, 2})]] = 0) & /# ({x, y} /. {p[i - 1]}));
(b[[Sequence ## #]] = k--)&/#((# + 2 i {1, 1}) &/# (SortBy[(# - 2 i {1, 1}) &/#
Position[a, 1],
N#(Mod[-10^-9 - Pi/4 + ArcTan[Sequence ## #], 2 Pi]) &]));
c = Table[b[[2 (2 i + 1) - j, k]], {j, 2 (2 i + 1) - 1},
{k, 2 (2 i + 1) - 1}];
MatrixPlot[c]
Edit
A better one:
genMat[m_] := Module[{f, k, k1, i, n, a = {{1}}},
f[n_] := 3*n*(n + 1) + 1;
For[n = 1, n <= m, n++,
a = ArrayPad[a, 1];
k1 = (f[n - 1] + (k = f[n]) + 2)/2 - 1;
For[i = 2, i <= n + 1, i++, a[[i, 2n + 1]] = k--; a[[2-i+2 n, 1]] = k1--];
For[i = n + 2, i <= 2 n + 1, i++, a[[i, 3n+2-i]] = k--; a[[-i,i-n]] = k1--];
For[i = n, i >= 1, i--, a[[2n+1, i]] = k--;a[[1, -i + 2 n + 2]] = k1--];
];
Return#MatrixForm[a];
]
genMat[5]
A partial solution, using image procssing:
Image /# (Differences#(ImageData /#
NestList[
Fold[ImageAdd,
p = #, (HitMissTransform[p, #, Padding -> 0] & /#
{{{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, -1, -1, -1}, {-1, -1, -1, -1}}})] &, img, 4]))