Recursion, multiple base cases in VBA - algorithm

I'm trying to take the first block of code from this link: http://www.geeksforgeeks.org/dynamic-programming-subset-sum-problem/
Copied and pasted below:
bool isSubsetSum(int set[], int n, int sum)
{
// Base Cases
if (sum == 0)
return true;
if (n == 0 && sum != 0)
return false;
// If last element is greater than sum, then ignore it
if (set[n-1] > sum)
return isSubsetSum(set, n-1, sum);
/* else, check if sum can be obtained by any of the following
(a) including the last element
(b) excluding the last element */
return isSubsetSum(set, n-1, sum) || isSubsetSum(set, n-1, sum-set[n-1]);
}
And translate it into a recursive VBA function that I plan on calling from a Sub.
So far I have:
Function SubSum(source(), n As Integer, sum)
If sum = 0 Then
SubSum = True
End If
If (n = 0 And sum <> 0) Then
SubSum = False
End If
If source(n - 1) > sum Then
SubSum = SubSum(source, n - 1, sum)
End If
SubSum = (SubSum(source, n - 1, sum) Or SubSum(source, n - 1, sum - source(n - 1)))
End Function
My issue is that returning a value in each of the basecases doesn't exit that instance of the function. So when n=0 and sum<>0, SubSum is set equal to False and the function continues to the next if statement. The dataset I'm using is small and efficiency isn't an issue, I'm just trying to understand VBA's syntax.
After doing some research I found this post:Subset sum algorithm in vba
But it doesn't implement it recursively.

or use elseif to avoid exit function
Sub test()
Dim arr() As Variant
Dim sum As Long
Dim n As Long
Dim result As Boolean
arr = Array(3, 34, 4, 12, 5, 2)
n = 9
result = SubSum(arr, UBound(arr), n)
End Sub
Function SubSum(source As Variant, n As Long, sum As Long) As Boolean
If sum = 0 Then
SubSum = True
ElseIf (n = 0 And sum <> 0) Then
SubSum = False
ElseIf source(n - 1) > sum Then
SubSum = SubSum(source, n - 1, sum)
Else
SubSum = (SubSum(source, n - 1, sum) Or SubSum(source, n - 1, sum - source(n - 1)))
End If
End Function

My issue is ..... and the function continues to the next if statement.
To solve that problem you will have to use Exit Function.
For example
'
'~~> Rest of the code
'
If sum = 0 Then
SubSum = True
Exit Function
ElseIf (n = 0 And sum <> 0) Then
SubSum = False
Exit Function
End If
'
'~~> Rest of the code
'

Related

logical matrix how to find efficiently row/column with true value

I'm trying to find a efficient solution for the next riddle:
i have a logical matrix at (n * n) size filled in false values
i need to create a function that will get zero or one as argument it will shift all
the values in the matrix one step to the left (meaning the first
element on the first row is deleted and the last element in the last
row is our new bit) and return true if there is a row/column in our
matrix contains only one's values.
No limitation on the data structure.
My naive solution in javascript:
const next = (bit, matrix) => {
matrix.shift()
matrix.push(bit);
const matrix_size = Math.sqrt(matrix.length);
let col_sum = 0;
let row_sum = 0;
for (let i = 0; i < matrix.length; ++i) {
col_sum = matrix[i];
row_sum += matrix[i];
if ((i + 1) % matrix_size === 0) {
if (row_sum === matrix_size) return true;
row_sum = 0;
}
for (let j = i + matrix_size;j < (i + ((matrix_size * matrix_size) - 1)); j += matrix_size) {
col_sum += matrix[j];
}
if (col_sum === matrix_size) return true;
}
return false;
}
i used 1d array as data structure but it doesn't really help my to reduce time complexity.
Love to hear some ideas :)
Let’s think about following example matrix:
[0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 1, 1,
1, 1, 1, 1]
and push zero 16 times.
Then, False, True, True, True, False, True, True, True, False, True, True, True, False, False False and False will be obtained.
There is cyclic behavior (False, True, True, True).
If the length of continued ones was fixed, it isn’t necessary to recalculate every time in update.
Updated the matrix, the length of continued ones at top-left and bottom-right can be change, and it can be needed to update the cyclic memory.
Maintaining continued ones sequences, maintaining total count of cyclic behavior affected by the sequences, the complexity for the rows will be in O(1).
In case of column, instead of shifting and pushing, let matrix[cur]=bit and cur = (cur+1)%(matrix_size*matrix_size) to represent cur as the actual upper-left of the matrix.
Maintaining col_sum of each column, maintaining total count satisfying the all-ones-condition, the complexity will be O(1).
class Matrix:
def __init__(self, n):
self.mat = [0] * (n*n)
self.seq_len = [0] * (n*n)
self.col_total = [0] * n
self.col_archive = 0
self.row_cycle_cnt = [0] * n
self.cur = 0
self.continued_one = 0
self.n = n
def update(self, bit):
prev_bit = self.mat[self.cur]
self.mat[self.cur] = bit
# update col total
col = self.cur % self.n
if self.col_total[col] == self.n:
self.col_archive -= 1
self.col_total[col] += bit - prev_bit
if self.col_total[col] == self.n:
self.col_archive += 1
# update row index
# process shift out
if prev_bit == 1:
prev_len = self.seq_len[self.cur]
if prev_len > 1:
self.seq_len[(self.cur + 1) % (self.n * self.n)] = prev_len-1
if self.n <= prev_len and prev_len < self.n*2:
self.row_cycle_cnt[self.cur % self.n] -= 1
# process new bit
if bit == 0:
self.continued_one = 0
else:
self.continued_one = min(self.continued_one + 1, self.n*self.n)
# write the length of continued_one at the head of sequence
self.seq_len[self.cur+1 - self.continued_one] = self.continued_one
if self.n <= self.continued_one and self.continued_one < self.n*2:
self.row_cycle_cnt[(self.cur+1) % self.n] += 1
# update cursor
self.cur = (self.cur + 1) % (self.n * self.n)
return (self.col_archive > 0) or (self.row_cycle_cnt[self.cur % self.n] > 0)
def check2(self):
for y in range(self.n):
cnt = 0
for x in range(self.n):
cnt += self.mat[(self.cur + y*self.n + x) % (self.n*self.n)]
if cnt == self.n:
return True
for x in range(self.n):
cnt = 0
for y in range(self.n):
cnt += self.mat[(self.cur + y*self.n + x) % (self.n*self.n)]
if cnt == self.n:
return True
return False
if __name__ == "__main__":
import random
random.seed(123)
m = Matrix(4)
for i in range(100000):
ans1 = m.update(random.randint(0, 1))
ans2 = m.check2()
assert(ans1 == ans2)
print("epoch:{} mat={} ans={}".format(i, m.mat[m.cur:] + m.mat[:m.cur], ans1))

Fastest solution for all possible combinations, taking k elements out of n possible with k>2 and n large

I am using MATLAB to find all of the possible combinations of k elements out of n possible elements. I stumbled across this question, but unfortunately it does not solve my problem. Of course, neither does nchoosek as my n is around 100.
Truth is, I don't need all of the possible combinations at the same time. I will explain what I need, as there might be an easier way to achieve the desired result. I have a matrix M of 100 rows and 25 columns.
Think of a submatrix of M as a matrix formed by ALL columns of M and only a subset of the rows. I have a function f that can be applied to any matrix which gives a result of either -1 or 1. For example, you can think of the function as sign(det(A)) where A is any matrix (the exact function is irrelevant for this part of the question).
I want to know what is the biggest number of rows of M for which the submatrix A formed by these rows is such that f(A) = 1. Notice that if f(M) = 1, I am done. However, if this is not the case then I need to start combining rows, starting of all combinations with 99 rows, then taking the ones with 98 rows, and so on.
Up to this point, my implementation had to do with nchoosek which worked when M had only a few rows. However, now that I am working with a relatively bigger dataset, things get stuck. Do any of you guys think of a way to implement this without having to use the above function? Any help would be gladly appreciated.
Here is my minimal working example, it works for small obs_tot but fails when I try to use bigger numbers:
value = -1; obs_tot = 100; n_rows = 25;
mat = randi(obs_tot,n_rows);
while value == -1
posibles = nchoosek(1:obs_tot,i);
[num_tries,num_obs] = size(possibles);
num_try = 1;
while value == 0 && num_try <= num_tries
check = mat(possibles(num_try,:),:);
value = sign(det(check));
num_try = num_try + 1;
end
i = i - 1;
end
obs_used = possibles(num_try-1,:)';
Preamble
As yourself noticed in your question, it would be nice not to have nchoosek to return all possible combinations at the same time but rather to enumerate them one by one in order not to explode memory when n becomes large. So something like:
enumerator = CombinationEnumerator(k, n);
while(enumerator.MoveNext())
currentCombination = enumerator.Current;
...
end
Here is an implementation of such enumerator as a Matlab class. It is based on classic IEnumerator<T> interface in C# / .NET and mimics the subfunction combs in nchoosek (the unrolled way):
%
% PURPOSE:
%
% Enumerates all combinations of length 'k' in a set of length 'n'.
%
% USAGE:
%
% enumerator = CombinaisonEnumerator(k, n);
% while(enumerator.MoveNext())
% currentCombination = enumerator.Current;
% ...
% end
%
%% ---
classdef CombinaisonEnumerator < handle
properties (Dependent) % NB: Matlab R2013b bug => Dependent must be declared before their get/set !
Current; % Gets the current element.
end
methods
function [enumerator] = CombinaisonEnumerator(k, n)
% Creates a new combinations enumerator.
if (~isscalar(n) || (n < 1) || (~isreal(n)) || (n ~= round(n))), error('`n` must be a scalar positive integer.'); end
if (~isscalar(k) || (k < 0) || (~isreal(k)) || (k ~= round(k))), error('`k` must be a scalar positive or null integer.'); end
if (k > n), error('`k` must be less or equal than `n`'); end
enumerator.k = k;
enumerator.n = n;
enumerator.v = 1:n;
enumerator.Reset();
end
function [b] = MoveNext(enumerator)
% Advances the enumerator to the next element of the collection.
if (~enumerator.isOkNext),
b = false; return;
end
if (enumerator.isInVoid)
if (enumerator.k == enumerator.n),
enumerator.isInVoid = false;
enumerator.current = enumerator.v;
elseif (enumerator.k == 1)
enumerator.isInVoid = false;
enumerator.index = 1;
enumerator.current = enumerator.v(enumerator.index);
else
enumerator.isInVoid = false;
enumerator.index = 1;
enumerator.recursion = CombinaisonEnumerator(enumerator.k - 1, enumerator.n - enumerator.index);
enumerator.recursion.v = enumerator.v((enumerator.index + 1):end); % adapt v (todo: should use private constructor)
enumerator.recursion.MoveNext();
enumerator.current = [enumerator.v(enumerator.index) enumerator.recursion.Current];
end
else
if (enumerator.k == enumerator.n),
enumerator.isInVoid = true;
enumerator.isOkNext = false;
elseif (enumerator.k == 1)
enumerator.index = enumerator.index + 1;
if (enumerator.index <= enumerator.n)
enumerator.current = enumerator.v(enumerator.index);
else
enumerator.isInVoid = true;
enumerator.isOkNext = false;
end
else
if (enumerator.recursion.MoveNext())
enumerator.current = [enumerator.v(enumerator.index) enumerator.recursion.Current];
else
enumerator.index = enumerator.index + 1;
if (enumerator.index <= (enumerator.n - enumerator.k + 1))
enumerator.recursion = CombinaisonEnumerator(enumerator.k - 1, enumerator.n - enumerator.index);
enumerator.recursion.v = enumerator.v((enumerator.index + 1):end); % adapt v (todo: should use private constructor)
enumerator.recursion.MoveNext();
enumerator.current = [enumerator.v(enumerator.index) enumerator.recursion.Current];
else
enumerator.isInVoid = true;
enumerator.isOkNext = false;
end
end
end
end
b = enumerator.isOkNext;
end
function [] = Reset(enumerator)
% Sets the enumerator to its initial position, which is before the first element.
enumerator.isInVoid = true;
enumerator.isOkNext = (enumerator.k > 0);
end
function [c] = get.Current(enumerator)
if (enumerator.isInVoid), error('Enumerator is positioned (before/after) the (first/last) element.'); end
c = enumerator.current;
end
end
properties (GetAccess=private, SetAccess=private)
k = [];
n = [];
v = [];
index = [];
recursion = [];
current = [];
isOkNext = false;
isInVoid = true;
end
end
We can test implementation is ok from command window like this:
>> e = CombinaisonEnumerator(3, 6);
>> while(e.MoveNext()), fprintf(1, '%s\n', num2str(e.Current)); end
Which returns as expected the following n!/(k!*(n-k)!) combinations:
1 2 3
1 2 4
1 2 5
1 2 6
1 3 4
1 3 5
1 3 6
1 4 5
1 4 6
1 5 6
2 3 4
2 3 5
2 3 6
2 4 5
2 4 6
2 5 6
3 4 5
3 4 6
3 5 6
4 5 6
Implementation of this enumerator may be further optimized for speed, or by enumerating combinations in an order more appropriate for your case (e.g., test some combinations first rather than others) ... Well, at least it works! :)
Problem solving
Now solving your problem is really easy:
n = 100;
m = 25;
matrix = rand(n, m);
k = n;
cont = true;
while(cont && (k >= 1))
e = CombinationEnumerator(k, n);
while(cont && e.MoveNext());
cont = f(matrix(e.Current(:), :)) ~= 1;
end
if (cont), k = k - 1; end
end

Knapsack 0-1 with fixed quanitity

I'm writing a variation of knapsack 0-1 with multiple constraints. In addition to a weight constraint I also have a quantity constraint, but in this case I want to solve the knapsack problem given that I'm required to have exactly n items in my knapsack, with a weight less than or equal to W. I'm currently implementing a dynamic programming ruby solution for the simple 0-1 case based off of the code at Rosetta Code at http://rosettacode.org/wiki/Knapsack_problem/0-1#Ruby.
What's the best way to implement the fixed quantity constraint?
You could add a third dimension to the table: Number of items. Each item included adds both weight in the weight-dimension, and count in the count-dimension.
def dynamic_programming_knapsack(problem)
num_items = problem.items.size
items = problem.items
max_cost = problem.max_cost
count = problem.count
cost_matrix = zeros(num_items, max_cost+1, count+1)
num_items.times do |i|
(max_cost + 1).times do |j|
(count + 1).times do |k|
if (items[i].cost > j) or (1 > k)
cost_matrix[i][j][k] = cost_matrix[i-1][j][k]
else
cost_matrix[i][j][k] = [
cost_matrix[i-1][j][k],
items[i].value + cost_matrix[i-1][j-items[i].cost][k-1]
].max
end
end
end
end
cost_matrix
end
To find the solution (which items to pick), you need to look at the grid cost_matrix[num_items-1][j][k], for all values of j and k, and find the cell with maximum value.
Once you find the winning cell, you need to trace backwards towards the start (i = j = k = 0). On each cell you examine, you need to determine if item i was used to get here or not.
def get_used_items(problem, cost_matrix)
itemIndex = problem.items.size - 1
currentCost = -1
currentCount = -1
marked = Array.new(cost_matrix.size, 0)
# Locate the cell with the maximum value
bestValue = -1
(problem.max_cost + 1).times do |j|
(problem.count + 1).times do |k|
value = cost_matrix[itemIndex][j][k]
if (bestValue == -1) or (value > bestValue)
currentCost = j
currentCount = k
bestValue = value
end
end
end
# Trace path back to the start
while(itemIndex >= 0 && currentCost >= 0 && currentCount >= 0)
if (itemIndex == 0 && cost_matrix[itemIndex][currentCost][currentCount] > 0) or
(cost_matrix[itemIndex][currentCost][currentCount] != cost_matrix[itemIndex-1][currentCost][currentCount])
marked[itemIndex] = 1
currentCost -= problem.items[itemIndex].cost
currentCount -= 1
end
itemIndex -= 1
end
marked
end

I want a function in VB SCRIPT to calculate numerology

I want a function to calculate numerology.For example if i enter "XYZ" then my output should be 3 .
Here is how it became 3:
X = 24
Y = 25
Z = 26
on adding it becomes 75 which again adds up to 12 (7+5) which again adds up to 3(1+2) . Similarly whatever names i should pass,my output should be a single digit score.
Here you are:
Function Numerology(Str)
Dim sum, i, char
' Convert the string to upper case, so that 'X' = 'x'
Str = UCase(Str)
sum = 0
' For each character, ...
For i = 1 To Len(Str)
' Check if it's a letter and raise an exception otherwise
char = Mid(Str, i , 1)
If char < "A" Or char > "Z" Then Err.Raise 5 ' Invalid procedure call or argument
' Add the letter's index number to the sum
sum = sum + Asc(char) - 64
Next
' Calculate the result using the digital root formula (http://en.wikipedia.org/wiki/Digital_root)
Numerology = 1 + (sum - 1) Mod 9
End Function
In vbscript:
Function numerology(literal)
result = 0
for i = 1 to Len(literal)
'' // for each letter, take its ASCII value and substract 64,
'' so "A" becomes 1 and "Z" becomes 26
result = result + Asc(Mid(literal, i, 1)) - 64
next
'' // while result is bigger than 10, let's sum it's digits
while(result > 10)
partial = 0
for i = 1 to Len(CStr(result))
partial = partial + CInt(Mid(CStr(result), i, 1))
next
result = partial
wend
numerology = result
End Function
I have no idea what this could possible be used for but it was fun to write anyway.
Private Function CalcStupidNumber(ByVal s As String) As Integer
s = s.ToLower
If (s.Length = 1) Then 'End condition
Try
Return Integer.Parse(s)
Catch ex As Exception
Return 0
End Try
End If
'cover to Values
Dim x As Int32
Dim tot As Int32 = 0
For x = 0 To s.Length - 1 Step 1
Dim Val As Integer = ConvertToVal(s(x))
tot += Val
Next
Return CalcStupidNumber(tot.ToString())
End Function
Private Function ConvertToVal(ByVal c As Char) As Integer
If (Char.IsDigit(c)) Then
Return Integer.Parse(c)
End If
Return System.Convert.ToInt32(c) - 96 ' offest of a
End Function

recursion: cut array of integers in two parts of equal sum - in a single pass

Using recursion, find an index that cuts an array in two parts so that both parts have equal sum.
Cut means to cut like with a knife. All the cells with index <= to the result must be equal in their sum to the all the cells with index > to the result. No cells can be left off or be part of both sides.
The arrays contains arbitrary integers (i.e. positives, negatives, and zeros).
If there is no such index return -1.
You are not allowed to allocate heap objects.
You must do it in a single pass.
You must do it with recursion (i.e. cannot use loop constructs).
Can be in any language or pseudocode.
Forgot to add this: You cannot modify the array
Here's a way to do it that takes advantage of Ruby's ability to return multiple values. The first value is the index for the split (if it exists), the second is the sum of each half (or the sum of the whole array if no split is found):
def split(arr, index = 0, sum = 0)
return -1, arr[index] if index == arr.length - 1
sum = sum + arr[index]
i, tail = split(arr, index + 1, sum)
if i > -1
return i, tail
elsif sum == tail
return index, sum
end
return -1, arr[index] + tail
end
Calling it like this:
p split([1, 1, 2])
p split([1])
p split([-1, 2, 1])
p split([2, 3, 4])
p split([0, 5, 4, -9])
Results in this:
[1, 2]
[-1, 1]
[1, 1]
[-1, 9]
[0, 0]
EDIT:
Here's a slightly modified version to address onebyone.livejournal.com's comments. Now each index in the array is accessed only once:
def split(arr, index = 0, sum = 0)
curr = arr[index]
return -1, curr if index == arr.length - 1
sum = sum + curr
i, tail = split(arr, index + 1, sum)
if i > -1
return i, tail
elsif sum == tail
return index, sum
end
return -1, curr + tail
end
Iterating with recursion is a trivial transformation, so we'll assume you know how to do that.
If you use your "one pass" to build your own array of "sum to this index", and can make another pass on that array, I could see how to do it. Just iterate through that second array and subtract sum[x] from sum[last]. If you ever find a situation where the result = sum[x] you return x. If you don't then return -1.
As Neil N mentioned, if you define "pass" very loosely for recursion, such that the entire recursion can actually visit indices multiple times, then you could dispense with the second array.
After thinking about this a bit, I suspect the idea is to get you to only visit every array element once (in order), and to use recursion's built-in stack property to get rid of the need for any second array.
What you do is write your recursive routine to save off it's current index's array value in a local, add that value to a passed in "sum_of_array" value, then call itself on the next highest index (if there is one). If there isn't a next highest index, it saves the sum into a global, which is now available to every stacked recursive call. Each routine finishes by checking its sum against the global sum. If it is half, then it returns its index. Otherwise it returns -1. If a non -1 was returned from a call to itself, this last step is skipped and that value is returned. I'll show in pseudo-Ada
Total_Sum : integer;
function Split (Subject : Integer_Array; After : Integer := 0; Running_Sum : Integer := 0) is
begin
Running_Sum := Running_Sum + Subject(After);
if (After < Subject'last) then --'// comment Hack for SO colorizer
Magic_Index : constant Integer := Split (Subject, After + 1, Running_Sum);
if (Magic_Index = -1) then
if (Total_Sum - Running_Sum = Running_Sum) then
return After;
else
return -1;
end if;
else
return Magic_Index;
end if;
else
Total_Sum := Running_Sum;
return -1;
end if;
end Split;
This code should have the properties that:
Calling it with just an array will return the described "split" index, or -1 if there isn't one.
It only reads from any element in the source array once
It reads the source array elements in strict index order.
No extra structured data storage (array) is required.
public static Int32 SplitIndex(Int32[] array, Int32 left, Int32 right, Int32 leftsum, Int32 rightsum)
{
if (left == right - 1)
{
return (leftsum == rightsum) ? left : -1;
}
if (leftsum > rightsum)
{
return SplitIndex(array, left, right - 1, leftsum, rightsum + array[right - 1]);
}
else
{
return SplitIndex(array, left + 1, right, leftsum + array[left + 1], rightsum);
}
}
The method is called as follows.
Int32[] a = { 1, 2, 3, 1, 6, 1 };
Console.WriteLine(SplitIndex(a, -1, a.Length, 0, 0));
This can be reduced to use only a single sum and targeting zero.
public static Int32 SplitIndex(Int32[] array, Int32 left, Int32 right, Int32 sum)
{
if (left == right - 1)
{
return (sum == 0) ? left : -1;
}
if (sum > 0)
{
return SplitIndex(array, left, right - 1, sum - array[right - 1]);
}
else
{
return SplitIndex(array, left + 1, right, sum + array[left + 1]);
}
}
The method is now called as follows.
Int32[] a = { 1, 2, 3, 1, 6, 1 };
Console.WriteLine(SplitIndex(a, -1, a.Length, 0));
Take a look at the following, using only 1 index, assume array's indexes are 1-based:
int recursion(index, rightvalue, leftvalue, array)
{
if array=[] then
{
if rightvalue=leftvalue then return index
else return -1
}
else
{
if rightvalue <= leftvalue
{ recursion(index+1, rightvalue+array[1], leftvalue, array[2..len(array)] }
else
{ recursion(index, rightvalue, leftvalue+array[len(array)], array[1..len(array)-1] }
}
int main_function(array)
{
return recursion(1, 0, 0, array)
}
My version:
# Returns either (right sum from the currentIndex, currentIndex, False),
# or, if the winning cut is found, (sum from the cut, its index, True)
def tryCut(anArray, currentIndex, currentLeftSum):
if currentIndex == len(anArray):
return (0, currentIndex, currentLeftSum==0)
(nextRightSum, anIndex, isItTheWinner) = tryCut(anArray, currentIndex + 1, currentLeftSum + anArray[currentIndex])
if isItTheWinner: return (nextRightSum, anIndex, isItTheWinner)
rightSum = anArray[currentIndex] + nextRightSum
return (rightSum, currentIndex, currentLeftSum == rightSum)
def findCut(anArray):
(dummy, anIndex, isItTheWinner) = tryCut(anArray, 0, 0)
if isItTheWinner: return anIndex
return -1
Note: if the index returned is 5, I mean that sum(anArray[:5]) == sum(anArray[5:]). The "extremes" are also valid (where the sum of an empty slice is meant to be zero), i.e. if the sum of the whole array is zero, then 0 and len(anArray) are also valid cuts.
Here's an implementation in Erlang, since I'm learning it and this seemed like an interesting challenge. Idea shamelessly cribbed from Pesto's solution.
find_split(List) -> {Idx, _Sum} = find_split(List, 1, 0), Idx.
find_split([Head], _Idx, _Sum) -> {-1, Head};
find_split([Head|Tail], Idx, Sum) ->
case find_split(Tail, Idx + 1, Sum + Head) of
{-1, Tailsum} when Sum + Head == Tailsum -> {Idx, Sum + Head};
{-1, Tailsum} -> {-1, Head + Tailsum};
Ret -> Ret
end.
Haskell:
split' _ s [] = (-1, s)
split' idx s (x:xs) | sidx >= 0 = (sidx, s')
| s * 2 == s' = (idx - 1, s)
| otherwise = (-1, s')
where (sidx, s') = split' (idx + 1) (x + s) xs
split = fst . split' 0 0
Your rules are somewhat misleading. You require that no objects are to be allocated on the heap, but IMHO there is no solution where the algorithm does not have space requirements of O(n), i.e. the stack grows linearly with the length of the list and tail calls are not possible because the function has to inspect the return values from the recursive call.
Code in C/C++/Java:
function cut(int i, int j, int s1, int s2, int a[])
{
if(i==j && s1==s2)
return i;
else if(i==j && s1!=s2)
return -1;
else if(s1>s2)
return cut(i, j-1, s1, s2 + a[j-1]);
else
return cut(i+1, j, s1 + a[i+1], s2);
}
Call using the following syntax:
cut(0, array.length, 0, 0, array);

Resources