Using stack to find the greatest common divisor - ruby

I am trying to implement an alogorithm to find the greatest common divisor using a stack: I am unable to formulate the correct answer based on my logic below. Please help. Here is my code:
def d8(a,b)
if (a==b)
return a
end
s = Stack.new
s.push(b)
s.push(a)
c1 = s.pop
c2 = s.pop
while c1!=c2
if s.count>0
c1 = s.pop
c2 = s.pop
end
if c1== c2
return c1
elsif c1>c2
c1 = c1-c2
s.push(c2)
s.push(c1)
else
c2 = c2 -c1
s.push(c2)
s.push(c1)
end
end
return nil
end

GCD cannot be nil. Two integers always have a GCD. So the logic in the function is already incorrect just because under some condition it has a return nil.
Looking at this return nil condition, it is happening when c1 == c2 (it will exit the while loop). At the same time, inside the while loop, you return a value if c1 == c2. These two cases are in logical contradiction. In other words, you are exiting the while loop on the c1 == c2 condition and treating that condition as invalid before your if c1 == c2 condition can trigger and treat the condition as valid and return the correct answer.
Simplifying the logic a little, you get:
def d8(a,b)
return a if a == b # Just a simpler way of doing a small if statement
s = Stack.new # "Stack" must be a gem, not std Ruby; "Array" will work here
s.push(b)
s.push(a)
#c1 = s.pop # These two statements aren't really needed because of the first
#c2 = s.pop # "if" condition in the while loop
while c1 != c2
if s.count > 0
c1 = s.pop
c2 = s.pop
end
# if c1 == c2 isn't needed because the `while` condition takes care of it
if c1 > c2
c1 = c1 - c2
else
c2 = c2 - c1
end
# These pushes are the same at the end of both if conditions, so they
# can be pulled out
s.push(c2)
s.push(c1)
end
return c1 # This return occurs when c1 == c2
end
This will work, but it becomes more obvious that the use of a stack is superfluous and serves no purpose at all in the algorithm. s.count > 0 will always be true, and you are popping variables off right after you push them (basically a no-op). So this is equivalent to:
def d8(a,b)
return a if a == b
c1 = a
c2 = b
while c1 != c2
if c1 > c2
c1 = c1 - c2
else
c2 = c2 - c1
end
end
return c1
end

Java code for it would be
public static int gcd (int p, int q) {
StackGeneric<Integer> stack = new StackGeneric<Integer>();
int temp;
stack.push(p);
stack.push(q);
while (true) {
q = stack.pop();
p = stack.pop();
if (q == 0) {
break;
}
temp = q;
q = p % q;
p = temp;
stack.push(p);
stack.push(q);
}
return p;
}
Replace the function call in recursive solution with the while loop and iterate it till the second argument becomes 0, as it happens with the recursive function call
public static int gcd (int p, int q) {
if (q == 0) {
return p;
}
return gcd(q, p % q);
}

Related

Tail recursive solution in Scala for Linked-List chaining

I wanted to write a tail-recursive solution for the following problem on Leetcode -
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contains a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example:
*Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)*
*Output: 7 -> 0 -> 8*
*Explanation: 342 + 465 = 807.*
Link to the problem on Leetcode
I was not able to figure out a way to call the recursive function in the last line.
What I am trying to achieve here is the recursive calling of the add function that adds the heads of the two lists with a carry and returns a node. The returned node is chained with the node in the calling stack.
I am pretty new to scala, I am guessing I may have missed some useful constructs.
/**
* Definition for singly-linked list.
* class ListNode(_x: Int = 0, _next: ListNode = null) {
* var next: ListNode = _next
* var x: Int = _x
* }
*/
import scala.annotation.tailrec
object Solution {
def addTwoNumbers(l1: ListNode, l2: ListNode): ListNode = {
add(l1, l2, 0)
}
//#tailrec
def add(l1: ListNode, l2: ListNode, carry: Int): ListNode = {
var sum = 0;
sum = (if(l1!=null) l1.x else 0) + (if(l2!=null) l2.x else 0) + carry;
if(l1 != null || l2 != null || sum > 0)
ListNode(sum%10,add(if(l1!=null) l1.next else null, if(l2!=null) l2.next else null,sum/10))
else null;
}
}
You have a couple of problems, which can mostly be reduced as being not idiomatic.
Things like var and null are not common in Scala and usually, you would use a tail-recursive algorithm to avoid that kind of things.
Finally, remember that a tail-recursive algorithm requires that the last expression is either a plain value or a recursive call. For doing that, you usually keep track of the remaining job as well as an accumulator.
Here is a possible solution:
type Digit = Int // Refined [0..9]
type Number = List[Digit] // Refined NonEmpty.
def sum(n1: Number, n2: Number): Number = {
def aux(d1: Digit, d2: Digit, carry: Digit): (Digit, Digit) = {
val tmp = d1 + d2 + carry
val d = tmp % 10
val c = tmp / 10
d -> c
}
#annotation.tailrec
def loop(r1: Number, r2: Number, acc: Number, carry: Digit): Number =
(r1, r2) match {
case (d1 :: tail1, d2 :: tail2) =>
val (d, c) = aux(d1, d2, carry)
loop(r1 = tail1, r2 = tail2, d :: acc, carry = c)
case (Nil, d2 :: tail2) =>
val (d, c) = aux(d1 = 0, d2, carry)
loop(r1 = Nil, r2 = tail2, d :: acc, carry = c)
case (d1 :: tail1, Nil) =>
val (d, c) = aux(d1, d2 = 0, carry)
loop(r1 = tail1, r2 = Nil, d :: acc, carry = c)
case (Nil, Nil) =>
acc
}
loop(r1 = n1, r2 = n2, acc = List.empty, carry = 0).reverse
}
Now, this kind of recursions tends to be very verbose.
Usually, the stdlib provide ways to make this same algorithm more concise:
// This is a solution that do not require the numbers to be already reversed and the output is also in the correct order.
def sum(n1: Number, n2: Number): Number = {
val (result, carry) = n1.reverseIterator.zipAll(n2.reverseIterator, 0, 0).foldLeft(List.empty[Digit] -> 0) {
case ((acc, carry), (d1, d2)) =>
val tmp = d1 + d2 + carry
val d = tmp % 10
val c = tmp / 10
(d :: acc) -> c
}
if (carry > 0) carry :: result else result
}
Scala is less popular on LeetCode, but this Solution (which is not the best) would get accepted by LeetCode's online judge:
import scala.collection.mutable._
object Solution {
def addTwoNumbers(listA: ListNode, listB: ListNode): ListNode = {
var tempBufferA: ListBuffer[Int] = ListBuffer.empty
var tempBufferB: ListBuffer[Int] = ListBuffer.empty
tempBufferA.clear()
tempBufferB.clear()
def listTraversalA(listA: ListNode): ListBuffer[Int] = {
if (listA == null) {
return tempBufferA
} else {
tempBufferA += listA.x
listTraversalA(listA.next)
}
}
def listTraversalB(listB: ListNode): ListBuffer[Int] = {
if (listB == null) {
return tempBufferB
} else {
tempBufferB += listB.x
listTraversalB(listB.next)
}
}
val resultA: ListBuffer[Int] = listTraversalA(listA)
val resultB: ListBuffer[Int] = listTraversalB(listB)
val resultSum: BigInt = BigInt(resultA.reverse.mkString) + BigInt(resultB.reverse.mkString)
var listNodeResult: ListBuffer[ListNode] = ListBuffer.empty
val resultList = resultSum.toString.toList
var lastListNode: ListNode = null
for (i <-0 until resultList.size) {
if (i == 0) {
lastListNode = new ListNode(resultList(i).toString.toInt)
listNodeResult += lastListNode
} else {
lastListNode = new ListNode(resultList(i).toString.toInt, lastListNode)
listNodeResult += lastListNode
}
}
return listNodeResult.reverse(0)
}
}
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions, explanations, efficient algorithms with a variety of languages, and time/space complexity analysis in there.

Recursive solution to common longest substring between two strings

I am trying to return the length of a common substring between two strings. I'm very well aware of the DP solution, however I want to be able to solve this recursively just for practice.
I have the solution to find the longest common subsequence...
def get_substring(str1, str2, i, j):
if i == 0 or j == 0:
return
elif str1[i-1] == str2[j-1]:
return 1 + get_substring(str1, str2, i-1, j-1)
else:
return max(get_substring(str1, str2, i, j-1), get_substring(str1, str2, j-1, i))
However, I need the longest common substring, not the longest common sequence of letters. I tried altering my code in a couple of ways, one being changing the base case to...
if i == 0 or j == 0 or str1[i-1] != str2[j-1]:
return 0
But that did not work, and neither did any of my other attempts.
For example, for the following strings...
X = "AGGTAB"
Y = "BAGGTXAYB"
print(get_substring(X, Y, len(X), len(Y)))
The longest substring is AGGT.
My recursive skills are not the greatest, so if anybody can help me out that would be very helpful.
package algo.dynamic;
public class LongestCommonSubstring {
public static void main(String[] args) {
String a = "AGGTAB";
String b = "BAGGTXAYB";
int maxLcs = lcs(a.toCharArray(), b.toCharArray(), a.length(), b.length(), 0);
System.out.println(maxLcs);
}
private static int lcs(char[] a, char[] b, int i, int j, int count) {
if (i == 0 || j == 0)
return count;
if (a[i - 1] == b[j - 1]) {
count = lcs(a, b, i - 1, j - 1, count + 1);
}
count = Math.max(count, Math.max(lcs(a, b, i, j - 1, 0), lcs(a, b, i - 1, j, 0)));
return count;
}
}
You need to recurse on each separately. Which is easier to do if you have multiple recursive functions.
def longest_common_substr_at_both_start (str1, str2):
if 0 == len(str1) or 0 == len(str2) or str1[0] != str2[0]:
return ''
else:
return str1[0] + longest_common_substr_at_both_start(str1[1:], str2[1:])
def longest_common_substr_at_first_start (str1, str2):
if 0 == len(str2):
return ''
else:
answer1 = longest_common_substr_at_both_start (str1, str2)
answer2 = longest_common_substr_at_first_start (str1, str2[1:])
return answer2 if len(answer1) < len(answer2) else answer1
def longest_common_substr (str1, str2):
if 0 == len(str1):
return ''
else:
answer1 = longest_common_substr_at_first_start (str1, str2)
answer2 = longest_common_substr(str1[1:], str2)
return answer2 if len(answer1) < len(answer2) else answer1
print(longest_common_substr("BAGGTXAYB","AGGTAB") )
I am so sorry. I didn't have time to convert this into a recursive function. This was relatively straight forward to compose. If Python had a fold function a recursive function would be greatly eased. 90% of recursive functions are primitive. That's why fold is so valuable.
I hope the logic in this can help with a recursive version.
(x,y)= "AGGTAB","BAGGTXAYB"
xrng= range(len(x)) # it is used twice
np=[(a+1,a+2) for a in xrng] # make pairs of list index values to use
allx = [ x[i:i+b] for (a,b) in np for i in xrng[:-a]] # make list of len>1 combinations
[ c for i in range(len(y)) for c in allx if c == y[i:i+len(c)]] # run, matching x & y
...producing this list from which to take the longest of the matches
['AG', 'AGG', 'AGGT', 'GG', 'GGT', 'GT']
I didn't realize getting the longest match from the list would be a little involved.
ls= ['AG', 'AGG', 'AGGT', 'GG', 'GGT', 'GT']
ml= max([len(x) for x in ls])
ls[[a for (a,b) in zip(range(len(ls)),[len(x) for x in ls]) if b == ml][0]]
"AGGT"

Is there a way to make this code faster and if possible avoid loops?

A1, B1, C1, A2, B2 and C2 are 6 matrix with the same dimensions 4435X2000.
I have to find the values i, j and k for which A1(k,2000) == A2(i,j) and B1(k,2000) == B2(i,j) and C1(k,2000) == C2(i,j) , with the condition X(k)==1 and Y(i,j)==1
The objective is to find: counter, L, T and D
Is there a way to make this code faster? Can I avoid loops?
counter=0;
L(1)=0;
T(1)=0;
D(1)=0;
for k=1:4435
if X(k)==1 % X is a vector (4435x1)
F(k,:) = [A1(k,2000) B1(k,2000) C1(k,2000)]
for i=1:4435
for j=100:1999
if Y(i,j)==1 % Y is a matrix (4435x1999)
if F(k,:) == [A2(i,j) B2(i,j) C2(i,j)]
counter = counter+1;
L(counter)=k;
T(counter)=i;
D(counter)=j;
end
end
end
end
end
end
I want a solution that will save me at least 80% of the computation time!
and not have the error message: Out of memory
See how this works out for you -
%// Store X-Y data by calling X() and Y() functions
X_data = X(1:4435);
Y_data = Y(1:4435,100:1999);
range1 = 100:1999 %// define range for columns
A2 = A2(:,range1); %// Crop out A2, B2, C2 based on column-range
B2 = B2(:,range1);
C2 = C2(:,range1);
Y_data = Y_data(:,range1)==1;
%// Indices for dim-3
idx_X = find(X_data==1)
%// Map X==1 onto A1, B1, C1
A1Lr = A1(X_data==1,end)
B1Lr = B1(X_data==1,end)
C1Lr = C1(X_data==1,end)
%// Setup output array to store L, T, D as single Nx3 output array
out = zeros(sum(Y_data(:))*numel(A1Lr),3);
%// Try out(sum(Y_data(:)==1)*numel(A1Lr),3)=0; instead for speed!
%// Start collecting output indices
count = 1;
for iter1 = 1:numel(A1Lr)
[R,C] = find(Y_data & A2==A1Lr(iter1) & B2==B1Lr(iter1) & C2==C1Lr(iter1));
nR = numel(R);
out(count:count+nR-1,:) = [R C repmat(iter1,nR,1)];
count = count + nR;
end
out(find(out(:,1)==0,1):end,:)=[];
%// Packup the outputs
T = out(:,1)
D = out(:,2) + range1(1)-1
L = idx_X(out(:,3))
It is very difficult to determine what your code is actually supposed to accomplish, without really working to interpret your code. However, I'll give it a crack:
% Determine where X is true.
XTrue = X == 1;
% Extract values from A1,B1,C1 where X is true.
F ( XTrue , 1 : 3 ) = [ A1(XTrue,2000) B1(XTrue,2000) C1(XTrue,2000) ];
% Determine where Y is true.
YTrueIndex = find ( Y == 1 );
% Determine where the extracted values match
counter = [];
L = [];
T = [];
D = [];
for ( ii = 1 : length(YTrueIndex) )
indexCurrent = YTrueIndex(ii)
FRowsThatMatch = F(:,1)==A2(indexCurrent) & F(:,2)==B2(indexCurrent) & F(:,3)==C2(indexCurrent);
matchCount = length ( find ( FRowsThatMatch ) );
if ( matchCount > 0 )
counter = counter + matchCount;
[ i , j ] = ind2sub ( size ( Y ) , indexCurrent );
L = [ L , find ( FRowsThatMatch ) ];
T = [ T , ones(matchCount,1)*i ];
D = [ D , ones(matchCount,2)*j ];
end
end

ruby Argument Error: wrong number of arguments [duplicate]

This question already has answers here:
Using stack to find the greatest common divisor
(2 answers)
Closed 9 years ago.
Hi All I am new to ruby and I am trying to implement the alogrithm to find the greatest
common divisor using a stack:
Here is my code:
def d8(a,b)
return a if (a==b)
s = Stack.new
s.push(b)
s.push(a)
c1 = s.pop(a)
c2 = s.pop(b)
while c1!=c2
if s.count>0
c1 = s.pop(c1)
c2 = s.pop(c2)
end
if c1== c2
return c1
elsif c1>c2
c1 = c1-c2
s.push(c2)
s.push(c1)
else
c2 = c2 -c1
s.push(c2)
s.push(c1)
end
end
return nil
end
However, I keep getting a Argument Error: wrong number of arguments (1 for 0)
from line 7
Stack#pop method probably takes no arguments, so it should be:
c1 = s.pop
c2 = s.pop

Passing function as arguments in Matlab

I've just started to program and i've had some problems in passing function as arguments using MATLAB. I've to implement Lagrange algorithm for interpolation.
C1 and C2 are vectors that represent points to interpolate coordinates.
My main problem is that I don't know how to explain in my f1 definition that temp1 and temp2 are not variables, but values determined on every iteration of a for loop (for i and j).
I think the code remaining part could be almost correct.
function [ ] = lagrange(C1, C2)
n = length(C1);
f2 = inline('');
g = inline('');
for i = 1:n
temp0 = C2(i);
temp1 = C1(i);
for j = 1:n
if (i~=j)
temp2 = C1(j);
temp3 = C2(j);
f1 = inline('(x-temp2/(temp1-temp2)','x','temp1','temp2');
f2 = f2.*f1
end
g = g+temp0*f2;
end
end
%plot g
end

Resources