Auto complete an array according a vector - ruby

I have an array of 16 squares and I would like to auto complete it with integers values depending of the position in the array and the vector TOP_RIGHT.
TOP_RIGHT = 3
# Build the array...
#top_right = Array.new(16, 0)
#top_right.each_index do |square|
#top_right[square] = square / TOP_RIGHT if (0...16).include?(square - TOP_RIGHT)
end
# Print the array...
i = 0
#top_right.each do |square|
puts if i % 4 == 0
print "#{square} "
i += 1
end
My code seems to be okay, but after testing the result is:
0 0 0 1
1 1 2 2
2 3 3 3
4 4 4 5
I would like to get this array:
0 0 0 0
1 1 1 0
2 2 1 0
3 2 1 0
Do you think it is possible, using array and simple Ruby methods?
Thanks, and happy end year!
Edit:
In the previous example, TOP_RIGHT is a vector like and its value is the number of cases that we can add or sub in order to go from the source square to the destination square (which is on top-right).
For example if I get this other vector: TOP, its value is 4 and the generated array can be:
# print_array(4)
0 0 0 0
1 1 1 1
2 2 2 2
3 3 3 3
...and if the vector is RIGHT, its value is -1 and the array can be:
# print_array(-1)
3 2 1 0
3 2 1 0
3 2 1 0
3 2 1 0
Isn't it a little beat tricky? :)
I don't see how to process for designing a constructor which can build such arrays, by passing a value of a vector.

If you use an array to hold an array, and don't try to do it in a vector, it's not too bad:
#!/usr/bin/ruby1.8
top_right = 3
array_size = 4
a = (0...array_size).collect do |i|
(0...array_size).collect do |j|
[i, j].collect do |e|
top_right - e
end.min
end
end.reverse
a.each do |e|
p e
end
=> [0, 0, 0, 0]
=> [1, 1, 1, 0]
=> [2, 2, 1, 0]
=> [3, 2, 1, 0]
And if you really need the array squished into a vector, then:
v = a.flatten

Related

Example of compress column format for rank-deficient matrices

It is the first time I deal with column-compress storage (CCS) format to store matrices. After googling a bit, if I am right, in a matrix having n nonzero elements the CCS is as follows:
-we define a vector A_v of dimensions n x 1 storing the n non-zero elements
of the matrix
- we define a second vector A_ir of dimensions n x 1 storing the rows of the
non-zero elements of the matrix
-we finally define a third vector A_jc whose elements are the indices of the
elements of A_v which corresponds to the beginning of new column, plus a
final value which is by convention equal t0 n+1, and identifies the end of
the matrix (pointing theoretically to a virtual extra-column).
So for instance,
if
M = [1 0 4 0 0;
0 3 5 2 0;
2 0 0 4 6;
0 0 7 0 8]
we get
A_v = [1 2 3 4 5 7 2 4 6 8];
A_ir = [1 3 2 1 2 4 2 3 3 4];
A_jc = [1 3 4 7 9 11];
my questions are
I) is what I wrote correct, or I misunderstood anything?
II) what if I want to represent a matri with some columns which are zeroes, e.g.,
M2 = [0 1 0 0 4 0 0;
0 0 3 0 5 2 0;
0 2 0 0 0 4 6;
0 0 0 0 7 0 8]
wouldn't the representation of M2 in CCS be identical to the one of M?
Thanks for the help!
I) is what I wrote correct, or I misunderstood anything?
You are perfectly correct. However, you have to take care that if you use a C or C++ library offsets and indices should start at 0. Here, I guess you read some Fortran doc for which indices are starting at 1. To be clear, here is below the C version, which simply translates the indices of your Fortran-style correct answer:
A_v = unmodified
A_ir = [0 2 1 0 1 3 1 2 2 4] (in short [1 3 2 1 2 4 2 3 3 4] - 1)
A_jc = [0 2 3 6 8 10] (in short [1 3 4 7 9 11] - 1)
II) what if I want to represent a matri with some columns which are
zeroes, e.g., M2 = [0 1 0 0 4 0 0;
0 0 3 0 5 2 0;
0 2 0 0 0 4 6;
0 0 0 0 7 0 8]
wouldn't the representation of M2 in CCS be identical to the one of M?
I you have an empty column, simply add a new entry in the offset table A_jc. As this column contains no element this new entry value is simply the value of the previous entry. For instance for M2 (with index starting at 0) you have:
A_v = unmodified
A_ir = unmodified
A_jc = [0 0 2 3 6 8 10] (to be compared to [0 2 3 6 8 10])
Hence the two representations are differents.
If you just start learning about sparse matrices there is an excelllent free book here: http://www-users.cs.umn.edu/~saad/IterMethBook_2ndEd.pdf

Coming with a procedure to generate an array with special properties

I have an array of size n. Each element can hold any integer as long as the following properties holds:
1) All elements are non-negative
2) sum(array[0,i+1])<i for 0<=i<n
3) sum(array)=n-1
Let's call such an array a bucket.
I need to come up with a procedure that will generate the next bucket.
We can assume the first bucket is {0,0,0...n-1}
Example: For n=5, some possible combinations are
[0 0 0 0 4]
[0 0 0 1 3]
[0 0 0 2 2]
[0 0 0 3 1]
[0 0 1 2 1]
[0 0 2 1 1]
[0 1 1 1 1]
[0 1 0 0 3]
[0 1 1 0 2]
I'm having trouble coming up with a procedure that hits all the possible combinations. Any hints/tips? (Note I want to generate the next bucket. I'm not looking to print out all possible buckets at once)
You can use a simple backtracking procedure. The idea is to keep track of the current sum and the current index i. This would allow you to express the required constrains.
n = 5
a = [0] * n
def backtrack(i, sum):
if i > 0 and sum > i-1:
return
if i == n:
if sum == n-1:
print(a)
return
for e in range(n-sum):
a[i] = e
backtrack(i + 1, sum+e)
backtrack(0, 0)
test run

Counting subrows in each row of a matrix in Matlab?

I need an algorithm in Matlab which counts how many adjacent and non-overlapping (1,1) I have in each row of a matrix A mx(n*2) without using loops. E.g.
A=[1 1 1 0 1 1 0 0 0 1; 1 0 1 1 1 1 0 0 1 1] %m=2, n=5
Then I want
B=[2;3] %mx1
Specific case
Assuming A to have ones and zeros only, this could be one way -
B = sum(reshape(sum(reshape(A',2,[]))==2,size(A,2)/2,[]))
General case
If you are looking for a general approach that must work for all integers and a case where you can specify the pattern of numbers, you may use this -
patt = [0 1] %%// pattern to be found out
B = sum(reshape(ismember(reshape(A',2,[])',patt,'rows'),[],2))
Output
With patt = [1 1], B = [2 3]
With patt = [0 1], B = [1 0]
you can use transpose then reshape so each consecutive values will now be in a row, then compare the top and bottom row (boolean compare or compare the sum of each row to 2), then sum the result of the comparison and reshape the result to your liking.
in code, it would look like:
A=[1 1 1 0 1 1 0 0 0 1; 1 0 1 1 1 1 0 0 1 1] ;
m = size(A,1) ;
n = size(A,2)/2 ;
Atemp = reshape(A.' , 2 , [] , m ) ;
B = squeeze(sum(sum(Atemp)==2))
You could pack everything in one line of code if you want, but several lines is usually easier for comprehension. For clarity, the Atemp matrix looks like that:
Atemp(:,:,1) =
1 1 1 0 0
1 0 1 0 1
Atemp(:,:,2) =
1 1 1 0 1
0 1 1 0 1
You'll notice that each row of the original A matrix has been broken down in 2 rows element-wise. The second line will simply compare the sum of each row with 2, then sum the valid result of the comparisons.
The squeeze command is only to remove the singleton dimensions not necessary anymore.
you can use imresize , for example
imresize(A,[size(A,1),size(A,2)/2])>0.8
ans =
1 0 1 0 0
0 1 1 0 1
this places 1 where you have [1 1] pairs... then you can just use sum
For any pair type [x y] you can :
x=0; y=1;
R(size(A,1),size(A,2)/2)=0; % prealocarting memory
for n=1:size(A,1)
b=[A(n,1:2:end)' A(n,2:2:end)']
try
R(n,find(b(:,1)==x & b(:,2)==y))=1;
end
end
R =
0 0 0 0 1
0 0 0 0 0
With diff (to detect start and end of each run of ones) and accumarray (to group runs of the same row; each run contributes half its length rounded down):
B = diff([zeros(1,size(A,1)); A.'; zeros(1,size(A,1))]); %'// columnwise is easier
[is js] = find(B==1); %// rows and columns of starts of runs of ones
[ie je] = find(B==-1); %// rows and columns of ends of runs of ones
result = accumarray(js, floor((ie-is)/2)); %// sum values for each row of A

How to recognize a square in a bitmap?

I came across this interview question:
In a N x N bi-dimensional array of boolean elements, how do you determine if the values form a square?
For example:
true true true true
true false false true
true false false true
true true true true
form a square.
I figured that I have to start by checking if there is a square in the middle (if N is odd that is always true) and then recursively checking the values at the perimeter.
Is this the best way to do it or is there a better, faster, way to find out?
A squre could be determined by two points. Let's say the left-top point (x1,y1) and the right-bottom point (x2,y2). And, let's use 1 as true, and 0 as false.
Consider an array:
array = [None] * 5
array[0] = [1, 1, 1, 1, 0]
array[1] = [1, 0, 0, 1, 0]
array[2] = [1, 0, 0, 1, 0]
array[3] = [1, 1, 1, 1, 0]
array[4] = [1, 0, 0, 1, 0]
It's obviously that (0,0)(3,3) forms a square in this case. And we could find a property that:
A square is formed if and only if:
By adding the two row borders together, you will get a sequence of 2;
The length of the sequence is equal to the distance between to two row borders.
By adding the two column borders together, you will get a sequence of 2;
The length of the sequence is equal to the distance between to two column borders.
Exploiting the property above, you would get an algorithm:
row_segment = []
col_segment = []
for v1 in range(len(array)):
for v2 in range(v1+1, len(array)):
add_row = [array[v1][col]+array[v2][col] for col in range(len(array))]
add_col = [array[row][v1]+array[row][v2] for row in range(len(array))]
row_distance = v2-v1
row_sum = sum(add_row[:row_distance+1])
col_sum = sum(add_col[:row_distance+1])
for i in range(len(array)-row_distance):
j = i+row_distance
if row_sum == 2*(row_distance+1):
row_segment.append([v1, i, v2, j])
if col_sum == 2*(row_distance+1):
col_segment.append([i, v1, j, v2])
row_sum = row_sum - add_row[i] + add_row[j+1] if j+1 < len(array) else None
col_sum = col_sum - add_col[i] + add_col[j+1] if j+1 < len(array) else None
for i in row_segment:
if i in col_segment:
print "Square ({x1}, {y1}) ({x2}, {y2})".format(x1=i[0], y1=i[1], x2=i[2], y2=i[3])
Let's run some tests:
Test 1:
0 0 0 0 0
0 0 1 1 1
0 0 1 0 1
0 0 1 1 1
0 0 0 0 0
Square (1, 2) (3, 4)
Test 2:
0 0 0 0 0
1 1 1 1 1
1 0 1 0 1
1 1 1 0 1
0 0 1 1 1
Square (1, 0) (3, 2)
Test 3:
0 0 0 0 0
1 1 1 1 1
1 0 1 0 1
1 1 1 1 1
0 0 0 0 0
Square (1, 0) (3, 2)
Square (1, 2) (3, 4)
Test 4:
1 1 1 1 1
1 0 1 0 1
1 1 0 0 1
1 0 0 1 0
1 1 1 1 1
No squares found

Print all ways to sum n integers so that they total a given sum.

I'm trying to come up with an algorithm that will print out all possible ways to sum N integers so that they total a given value.
Example. Print all ways to sum 4 integers so that they sum up to be 5.
Result should be something like:
5 0 0 0
4 1 0 0
3 2 0 0
3 1 1 0
2 3 0 0
2 2 1 0
2 1 2 0
2 1 1 1
1 4 0 0
1 3 1 0
1 2 2 0
1 2 1 1
1 1 3 0
1 1 2 1
1 1 1 2
This is based off Alinium's code.
I modified it so it prints out all the possible combinations, since his already does all the permutations.
Also, I don't think you need the for loop when n=1, because in that case, only one number should cause the sum to equal value.
Various other modifications to get boundary cases to work.
def sum(n, value):
arr = [0]*n # create an array of size n, filled with zeroes
sumRecursive(n, value, 0, n, arr);
def sumRecursive(n, value, sumSoFar, topLevel, arr):
if n == 1:
if sumSoFar <= value:
#Make sure it's in ascending order (or only level)
if topLevel == 1 or (value - sumSoFar >= arr[-2]):
arr[(-1)] = value - sumSoFar #put it in the n_th last index of arr
print arr
elif n > 0:
#Make sure it's in ascending order
start = 0
if (n != topLevel):
start = arr[(-1*n)-1] #the value before this element
for i in range(start, value+1): # i = start...value
arr[(-1*n)] = i # put i in the n_th last index of arr
sumRecursive(n-1, value, sumSoFar + i, topLevel, arr)
Runing sums(4, 5) returns:
[0, 0, 0, 5]
[0, 0, 1, 4]
[0, 0, 2, 3]
[0, 1, 1, 3]
[1, 1, 1, 2]
In pure math, a way of summing integers to get a given total is called a partition. There is a lot of information around if you google for "integer partition". You are looking for integer partitions where there are a specific number of elements. I'm sure you could take one of the known generating mechanisms and adapt for this extra condition. Wikipedia has a good overview of the topic Partition_(number_theory). Mathematica even has a function to do what you want: IntegerPartitions[5, 4].
The key to solving the problem is recursion. Here's a working implementation in python. It prints out all possible permutations that sum up to the total. You'll probably want to get rid of the duplicate combinations, possibly by using some Set or hashing mechanism to filter them out.
def sum(n, value):
arr = [0]*n # create an array of size n, filled with zeroes
sumRecursive(n, value, 0, n, arr);
def sumRecursive(n, value, sumSoFar, topLevel, arr):
if n == 1:
if sumSoFar > value:
return False
else:
for i in range(value+1): # i = 0...value
if (sumSoFar + i) == value:
arr[(-1*n)] = i # put i in the n_th last index of arr
print arr;
return True
else:
for i in range(value+1): # i = 0...value
arr[(-1*n)] = i # put i in the n_th last index of arr
if sumRecursive(n-1, value, sumSoFar + i, topLevel, arr):
if (n == topLevel):
print "\n"
With some extra effort, this can probably be simplified to get rid of some of the parameters I am passing to the recursive function. As suggested by redcayuga's pseudo code, using a stack, instead of manually managing an array, would be a better idea too.
I haven't tested this:
procedure allSum (int tot, int n, int desiredTotal) return int
if n > 0
int i =
for (int i = tot; i>=0; i--) {
push i onto stack;
allSum(tot-i, n-1, desiredTotal);
pop top of stack
}
else if n==0
if stack sums to desiredTotal then print the stack end if
end if
I'm sure there's a better way to do this.
i've find a ruby way with domain specification based on Alinium's code
class Domain_partition
attr_reader :results,
:domain,
:sum,
:size
def initialize(_dom, _size, _sum)
_dom.is_a?(Array) ? #domain=_dom.sort : #domain= _dom.to_a
#results, #sum, #size = [], _sum, _size
arr = [0]*size # create an array of size n, filled with zeroes
sumRecursive(size, 0, arr)
end
def sumRecursive(n, sumSoFar, arr)
if n == 1
#Make sure it's in ascending order (or only level)
if sum - sumSoFar >= arr[-2] and #domain.include?(sum - sumSoFar)
final_arr=Array.new(arr)
final_arr[(-1)] = sum - sumSoFar #put it in the n_th last index of arr
#results<<final_arr
end
elsif n > 1
#********* dom_selector ********
n != size ? start = arr[(-1*n)-1] : start = domain[0]
dom_bounds=(start*(n-1)..domain.last*(n-1))
restricted_dom=domain.select do |x|
if x < start
false; next
end
if size-n > 0
if dom_bounds.cover? sum-(arr.first(size-n).inject(:+)+x) then true
else false end
else
dom_bounds.cover?(sum+x) ? true : false
end
end # ***************************
for i in restricted_dom
_arr=Array.new(arr)
_arr[(-1*n)] = i
sumRecursive(n-1, sumSoFar + i, _arr)
end
end
end
end
a=Domain_partition.new (-6..6),10,0
p a
b=Domain_partition.new [-4,-2,-1,1,2,3],10,0
p b
If you're interested in generating (lexically) ordered integer partitions, i.e. unique unordered sets of S positive integers (no 0's) that sum to N, then try the following. (unordered simply means that [1,2,1] and [1,1,2] are the same partition)
The problem doesn't need recursion and is quickly handled because the concept of finding the next lexical restricted partition is actually very simple...
In concept: Starting from the last addend (integer), find the first instance where the difference between two addends is greater than 1. Split the partition in two at that point. Remove 1 from the higher integer (which will be the last integer in one part) and add 1 to the lower integer (the first integer of the latter part). Then find the first lexically ordered partition for the latter part having the new largest integer as the maximum addend value. I use Sage to find the first lexical partition because it's lightening fast, but it's easily done without it. Finally, join the two portions and voila! You have the next lexical partition of N having S parts.
e.g. [6,5,3,2,2] -> [6,5],[3,2,2] -> [6,4],[4,2,2] -> [6,4],[4,3,1] -> [6,4,4,3,1]
So, in Python and calling Sage for the minor task of finding the first lexical partition given n and s parts...
from sage.all import *
def most_even_partition(n,s): # The main function will need to recognize the most even partition possible (i.e. last lexical partition) so it can loop back to the first lexical partition if need be
most_even = [int(floor(float(n)/float(s)))]*s
_remainder = int(n%s)
j = 0
while _remainder > 0:
most_even[j] += 1
_remainder -= 1
j += 1
return most_even
def portion(alist, indices):
return [alist[i:j] for i, j in zip([0]+indices, indices+[None])]
def next_restricted_part(p,n,s):
if p == most_even_partition(n,s):return Partitions(n,length=s).first()
for i in enumerate(reversed(p)):
if i[1] - p[-1] > 1:
if i[0] == (s-1):
return Partitions(n,length=s,max_part=(i[1]-1)).first()
else:
parts = portion(p,[s-i[0]-1]) # split p (soup?)
h1 = parts[0]
h2 = parts[1]
next = list(Partitions(sum(h2),length=len(h2),max_part=(h2[0]-1)).first())
return h1+next
If you want zeros (not actual integer partitions), then the functions only need small modifications.
Try this code. I hope it is easier to understand. I tested it, it generate correct sequence.
void partition(int n, int m = 0)
{
int i;
// if the partition is done
if(n == 0){
// Output the result
for(i = 0; i < m; ++i)
printf("%d ", list[i]);
printf("\n");
return;
}
// Do the split from large to small int
for(i = n; i > 0; --i){
// if the number not partitioned or
// willbe partitioned no larger than
// previous partition number
if(m == 0 || i <= list[m - 1]){
// store the partition int
list[m] = i;
// partition the rest
partition(n - i, m + 1);
}
}
}
Ask for clarification, if required.
The is One of the output
6
5 1
4 2
4 1 1
3 3
3 2 1
3 1 1 1
2 2 2
2 2 1 1
2 1 1 1 1
1 1 1 1 1 1
10
9 1
8 2
8 1 1
7 3
7 2 1
7 1 1 1
6 4
6 3 1
6 2 2
6 2 1 1
6 1 1 1 1
5 5
5 4 1
5 3 2
5 3 1 1
5 2 2 1
5 2 1 1 1
5 1 1 1 1 1
4 4 2
4 4 1 1
4 3 3
4 3 2 1
4 3 1 1 1
4 2 2 2
4 2 2 1 1
4 2 1 1 1 1
4 1 1 1 1 1 1
3 3 3 1
3 3 2 2
3 3 2 1 1
3 3 1 1 1 1
3 2 2 2 1
3 2 2 1 1 1
3 2 1 1 1 1 1
3 1 1 1 1 1 1 1
2 2 2 2 2
2 2 2 2 1 1
2 2 2 1 1 1 1
2 2 1 1 1 1 1 1
2 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1

Resources