How to rewrite Ackermann function in non-recursive style? - java

I have function
public static int func(int M,int N){
if(M == 0 || N == 0) return M+N+1;
return func(M-1, func(M, N-1));
}
How to rewrite it in non-recursive style ?
Maybe, is it implementation some algorithm?

Not quite O(1) but definitely non-recursive.
public static int itFunc(int m, int n){
Stack<Integer> s = new Stack<Integer>;
s.add(m);
while(!s.isEmpty()){
m=s.pop();
if(m==0||n==0)
n+=m+1;
else{
s.add(--m);
s.add(++m);
n--;
}
}
return n;
}

All the answers posted previously don't properly implement Ackermann.
def acker_mstack(m, n)
stack = [m]
until stack.empty?
m = stack.pop
if m.zero?
n += 1
elsif n.zero?
stack << m - 1
n = 1
else
stack << m - 1 << m
n -= 1
end
end
n
end

This looks like homework, so I won't give you the answer but I will lead you in the right direction:
If you want to breakdown the recursion, it might be useful for you to list out all the values as they progress, letting m = {0...x} n = {0...y}.
For example:
m = 0, n = 0 = f(0,0) = M+N+1 = 1
m = 1, n = 0 = f(1,0) = M+N+1 = 2
m = 1, n = 1 = f(1,1) = f(0,f(1,0)) = f(0,2) = 3
m = 2, n = 1 = f(2,1) = f(1,f(2,0)) = f(1,3) = f(0,f(1,2)) = f(0,f(0,f(1,1))
= f(0,f(0,3)) = f(0,4) = 5
With this, you can come up with a non-recursive relationship (a non-recursive function definition) that you can use.
Edit: So it looks like this is the Ackermann function, a total computable function that is not primitive recursive.

This is the a correct version which already examined by myself.
public static int Ackermann(int m, int n){
Stack<Integer> s = new Stack<Integer>;
s.add(m);
while(!s.isEmpty()){
m=s.pop();
if(m==0) { n+=m+1; }
else if(n==0)
{
n += 1;
s.add(--m);
}
else{
s.add(--m);
s.add(++m);
n--;
}
}
return n;
}

I couldn't get #LightyearBuzz's answer to work, but I found this Java 5 code from WikiWikiWeb that worked for me:
import java.util.HashMap;
import java.util.Stack;
public class Ackerman {
static class Pair <T1,T2>{
T1 x; T2 y;
Pair(T1 x_,T2 y_) {x=x_; y=y_;}
public int hashCode() {return x.hashCode() ^ y.hashCode();}
public boolean equals(Object o_) {Pair o= (Pair) o_; return x.equals(o.x) && y.equals(o.y);}
}
/**
* #param args
*/
public static int ack_iter(int m, int n) {
HashMap<Pair<Integer,Integer>,Integer> solved_set= new HashMap<Pair<Integer,Integer>,Integer>(120000);
Stack<Pair<Integer,Integer>> to_solve= new Stack<Pair<Integer,Integer>>();
to_solve.push(new Pair<Integer,Integer>(m,n));
while (!to_solve.isEmpty()) {
Pair<Integer,Integer> head= to_solve.peek();
if (head.x.equals(0) ) {
solved_set.put(head,head.y + 1);
to_solve.pop();
}
else if (head.y.equals(0)) {
Pair<Integer,Integer> next= new Pair<Integer,Integer> (head.x-1,1);
Integer result= solved_set.get(next);
if(result==null){
to_solve.push(next);
}
else {
solved_set.put(head, result);
to_solve.pop();
}
}
else {
Pair<Integer,Integer> next0= new Pair<Integer,Integer>(head.x, head.y-1);
Integer result0= solved_set.get(next0);
if(result0 == null) {
to_solve.push(next0);
}
else {
Pair<Integer,Integer> next= new Pair<Integer,Integer>(head.x-1,result0);
Integer result= solved_set.get(next);
if (result == null) {
to_solve.push(next);
}
else {
solved_set.put(head,result);
to_solve.pop();
}
}
}
}
System.out.println("hash size: "+solved_set.size());
System.out.println("consumed heap: "+ (Runtime.getRuntime().totalMemory()/(1024*1024)) + "m");
return solved_set.get(new Pair<Integer,Integer>(m,n));
}
}

Written in python, using only 1 array and 1 variable, hope this helps!
def acker(m,n):
right = [m]
result = n
i = 0
while True:
if len(right) == 0:
break
if right[i] > 0 and result > 0:
right.append(right[i])
right[i] -= 1
result -= 1
i += 1
elif right[i] > 0 and result == 0:
right[i] -= 1
result = 1
elif right[i] == 0:
result += 1
right.pop()
i -=1
return result

Well I came here to find the answer of this question. But could not write a code even after looking at the answers. So, I tried it myself and after some struggle built the code.
So, I will give you a hint (because I feel etiquettes here are that the homework questions are not meant to be fully answered).
So you can use a single stack to compute the function without using recursion. Just look at the flow of control in David's answer. You have to use that. Just start a while(1) loop and inside that check for the case your arguments are satisfying. Let the desired block amongst if-else blocks execute.Then push the two latest arguments of ackerman function into the stack. Then at the end of the loop pop them and let the cycle repeat till an end condition is reached where no further arguments of ackermann function are generated. You have to put a for statement inside the while loop to keep checking it. And finally get the final results.
I don't know how much of this is understandable, but I wish I could have some idea to start with. So, just shared the way.

Related

Recursive function responding different value

I wrote a java recursive function to get sum of a number as follows, and the sum should be single digit as well.the problem i am facing here is it should return the else part at the end where as it is giving the after if else condition return statement:
static int recSum(int n){
int sum = 0;
while(n!=0){
sum += n%10;
n = n/10;
}
if(sum>9) {
recSum(sum);
}
else {
return sum;
}
return sum ;
}
Let us say n = 12345 so at the end it needs to return 5 where as it is returning 14. However it is going to the else part but the correct value is not returning. I got the solution with the ternary operator without else loop. but would like to what is the reason for this i am getting the previous sum of 14 rather 5 (5 comes from 14 = 1+4)
Appreciate the response on this
The change you should do is fairly simple: you should remove the last return statement and just return the result of recursive call:
static int recSum(int n){
int sum = 0;
while(n!=0){
sum += n%10;
n = n/10;
}
if(sum>9) {
return recSum(sum);
}
else {
return sum;
}
}
When this function gets to the if statement and calls the function again the 15 is saved on the stack until the current call is finished, when the current call is finished the previous answer was 15 so it's returning that because you dont modify it in anyway after it gets returned.
This is an iterative way (NOT a good way to build recursion in your program)
while (n != 0) {
sum += n % 10;
n = n / 10;
}
This is the correct recursive way and works even for 0 and negative numbers.
static int recSum(int n) {
int sum = 0;
sum = sum + (n % 10);
n = n / 10;
if (n != 0) {
return sum + recSum(n);
} else {
return sum;
}
}

ProjectEuler solution returns incorrect answer

The problem I'm trying to solve comes from ProjectEuler.
Some integers have following property:
n + reverse(n) = a number consisting entirely of odd digits.
For example:
14: 14 + 41 = 55
Numbers starting or ending with 0 aren't allowed.
How many of these "reversible" numbers are there below 10^9?
The problem also gives a hint:
there are 120 such numbers below 1000.
I'm quite new to Java, and I tried to solve this problem by writing a program that checks all the numbers up to a billion, which is not the best way, I know, but I'm ok with that.
The problem is that my program gives out a wrong amount of numbers and I couldn't figure out why! (The code will most likely contain some ugly things, feel free to improve it in any way)
int result = 0;
boolean isOdd = true;
boolean hasNo0 = true;
public int reverseNumber(int r) //this method should be working
{ //guess the main problem is in the second method
int n = 0;
String m = "";
if (r % 10 == 0) { hasNo0 = false; }
while (r > 0){
n = r % 10;
m = String.valueOf(m+n);
r /= 10;
}
result = Integer.parseInt(m);
return result;
}
public void isSumOdd(int max)
{
int number = 1;
int sum = 0;
Sums reverseIt = new Sums();
int amount = 0;
while (number <= max)
{
sum = reverseIt.reverseNumber(number) + number;
while (sum > 0)
{
int x = sum % 10;
if (x % 2 == 0) { isOdd = false; }
sum /= 10;
}
if (isOdd && hasNo0) { amount++; }
number++;
isOdd = true;
hasNo0 = true;
}
System.out.println(amount);
}
Called by
Sums first = new Sums();
first.reversibleNumbers(1000000000);
The most important problem in your code is the following line:
sum = reverseIt.reverseNumber(number) + number;
in isSumOdd(int max) function. Here the reverseIt object is a new instance of Sums class. Since you are using Sums member data (the boolean variables) to signal some conditions when you use the new instance the value of these member variables is not copied to the current caller object. You have to change the line to:
sum = this.reverseNumber(number) + number;
and remove the Sums reverseIt = new Sums(); declaration and initialization.
Edit: Attempt to explain why there is no need to instantiate new object instance to call a method - I've found the following answer which explains the difference between a function and a (object)method: https://stackoverflow.com/a/155655/25429. IMO the explanation should be enough (you don't need a new object because the member method already has access to the member data in the object).
You overwrite odd check for given digit when checking the next one with this code: isOdd = false;. So in the outcome you check only whether the first digit is odd.
You should replace this line with
idOdd = idOdd && (x % 2 == 0);
BTW. You should be able to track down an error like this easily with simple unit tests, the practice I would recommend.
One of the key problems here is that your reverseNumber method does two things: check if the number has a zero and reverses the number. I understand that you want to ignore the result (or really, you have no result) if the number is a multiple of 10. Therefore, you have two approaches:
Only send numbers into reverseNumber if they are not a multiple of 10. This is called a precondition of the method, and is probably the easiest solution.
Have a way for your method to give back no result. This is a popular technique in an area of programming called "Functional Programming", and is usually implemented with a tool called a Monad. In Java, these are implemented with the Optional<> class. These allow your method (which always has to return something) to return an object that means "nothing at all". These will allow you to know if your method was unable or unwilling to give you a result for some reason (in this case, the number had a zero in it).
I think that separating functionnalities will transform the problem to be easier. Here is a solution for your problem. Perhaps it isn't the best but that gives a good result:
public static void main(final String [] args) {
int counter = 0;
for (int i = 0; i < 20; i++) {
final int reversNumber = reverseNumber(i);
final int sum = i + reversNumber;
if (hasNoZeros(i) && isOdd(sum)) {
counter++;
System.out.println("i: " + i);
System.out.println("r: " + reversNumber);
System.out.println("s: " + sum);
}
}
System.out.println(counter);
}
public static boolean hasNoZeros(final int i){
final String s = String.valueOf(i);
if (s.startsWith("0") || s.endsWith("0")) {
return false;
}
return true;
}
public static int reverseNumber(final int i){
final StringBuilder sb = new StringBuilder(String.valueOf(i));
return Integer.parseInt(sb.reverse().toString());
}
public static boolean isOdd(final int i){
for (final char s : String.valueOf(i).toCharArray()) {
if (Integer.parseInt(String.valueOf(s))%2 == 0) {
return false;
}
}
return true;
}
the output is:
i: 12
r: 21
s: 33
i: 14
r: 41
s: 55
i: 16
r: 61
s: 77
i: 18
r: 81
s: 99
4
Here is a quick working snippet:
class Prgm
{
public static void main(String args[])
{
int max=(int)Math.pow(10, 3); //change it to (10, 9) for 10^9
for(int i=1;i<=max;i++)
{
if(i%10==0)
continue;
String num=Integer.toString(i);
String reverseNum=new StringBuffer(num).reverse().toString();
String sum=(new Long(i+Long.parseLong(reverseNum))).toString();
if(sum.matches("^[13579]+$"))
System.out.println(i);
}
}
}
It prints 1 number(satisfying the condition) per line, wc is word count linux program used here to count number of lines
$javac Prgm.java
$java Prgm
...//Prgm outputs numbers 1 per line
$java Prgm | wc --lines
120

Loop through numbers from 0 to 100 and print out every third number without the modulo function using recursion

I had an interview the other day that asked the question, loop through the numbers from 0 to 100 and print out every third number. This is a very easy question if you know what the modulo function is. So I came up with the solution (Note I was using Java):
for (int i=0; i<100; i++) {
if (i % 3 == 0) {
System.out.println(i);
}
}
He then asked, what if you can't use division or the modulo function. So I had to think about this for about 30 seconds, and came up with a solution, that I knew was very inefficient, and let him know it was very inefficient, but would work.
int x = 3;
for (int i=0; i<100; i++) {
for (int j=0; j<33; j++) {
if (x*j==i) {
System.out.println(i);
break;
}
}
}
I'm free writing this without testing, so it might not work 100%, but you get the idea of how I solved the problem. He said he understood what I was trying to do. He then said that there is another way to do it using a recursive function. He tried to briefly explain it to me, but I didn't understand how you could use a recursive function to solve this problem. Can anyone come up with a solution using recursion?
EDIT:
Thanks for all the answers! I didn't think this question would attract as much attention as it did, but I appreciate all the answers. Some of you didn't understand that you can ONLY increment by 1. So you must loop through every natural number from 0 to 100.
There is a cool trick to test if a number is divisible by three. If the sum of all its digits is divisible by three, then the original is divisible by three. This can be applied recursively: if I have a number a, I can add all the digits of a together to get b and see if b is divisible by 3. How do I know if b is divisible by three? Add all of its digits together to get c and see if c is divisible by three...
As with all recursion, you have to stop at some point. The base case is when you have a sum which is only one digit long- you can have a list of digits divisible by three and check against these. In code:
public boolean printDivisibleByThrees(){
for(int i=0; i<100; i++){
if(isDivisibleByThree(i)){
System.out.println(i);
}
}
}
public boolean isDivisibleByThree(int i){
if(i<0){
i = -1*i; //we only care about the absolute value of i
}
if(Arrays.asList(0,3,6,9).contains(i)){
return true;
} else if(i<10){
return false; //one digit number not divisible by three
} else {
int j = sumDigits(i);
return isDivisibleByThree(j);
}
}
public int sumDigits(int i){
String iString = (new Integer(i)).toString();
int sum = 0;
for(char digit : iString.toCharArray()){
sum += (new Integer(digit+"")).intValue();
}
return sum;
}
As no answer has been picked yet I like to add my two cents here.
Since the trick is do the modulo function with recursion and without division (as I understood) here is my solution:
public static void main(String[] args) {
for ( int i = 1; i <=100; i++ ){
if ( mod(i, 3) ){
System.out.println(i);
}
}
}
public static boolean mod(int a, int b){
if ( a < 0 ){
return false;
}else if (a==b){
return true;
}else{
return mod( a-b, b );
}
}
EDIT
This version will handle division by 0 and negative numbers on the modulo function:
public static boolean mod(int a, int b){
if ( b < 0 ){
b=b*-1;
}
if ( a < 0 || b == 0){
return false;
}else if (a==b){
return true;
}else{
return mod( a-b, b );
}
}
Use a second parameter that will keep if the number is or not the third
public class Rec
{
public static void rec(int n, int t) {
if(t==3) {
System.out.println(n);
t=0; // reset it
}
if(n!=100) {
rec(++n, ++t);
}
}
public static void main (String[] args)
{
rec(0, 3);
}
}
One can define the modulus operator using recursion as follows:
// Assume a, b > 0
static int mod(a, b) {
if (a < b) {
return a;
} else {
return mod(a-b, b);
}
}
So then you could do:
for (int i=0; i<100; i++) {
if (mod(i, 3) == 0) {
System.out.println(i);
}
}
I want to add one more answer that is probably unusual, but works fine for each range.
The code is C++ (I'm from mobile and I've only a C++ compiler on it), but it is quite easy to understand and to rewrite in Java.
#include <iostream>
void foo(int c, int n) {
static int i = 0;
if(c >= n) return;
switch(i++) {
case 1:
case 2:
foo(++c, n);
break;
case 0:
case 3:
std::cout << c << std::endl;
i = 1;
foo(++c, n);
}
}
int main() {
foo(0, 100);
}
Another variation on the recursion (JavaScript code):
function f(m,i){
if (i == 100){
return;
} else if (i == 3*m){
console.log(i);
f(m + 1,i + 1);
} else {
f(m,i + 1);
}
}
f(0,0);
Why not just do:
for (int i = 0; i < 100; i += 3)
System.out.println(i);
This way you don't have to check if it is every third number, because it goes up by 3 each time.
void printNth(int max, int n, int i, int sinceLastPrinted) {
if (i>max) {
return;
}
if (sinceLastPrinted == n-1) {
System.out.println(i);
sinceLastPrinted = -1;
}
printNth(max, n, i+1, sinceLastPrinted+1);
}
printNth(100, 3, 0, 0);
It's also not 100% clear whether the last number (100 in the example) should be included (if it is "a 3rd number"), depending on that you might need to modify to:
if (i>=max) {
And also not very clear where to start the "every 3rd"? 0, 3, 6, or 2, 5, 8? The advantage of my function is that this can be easily modified by passing different value for i
This would work. !
public class Recursion {
public static void main(String[] args) {
myRecursiveMethod(0,1,100,3);
}
public static void myRecursiveMethod(int begin,int temp,int end,int n)
{
if(begin<=end)
{
if(temp==n)
{
System.out.println(begin);
temp=0;
}
myRecursiveMethod(++begin,++temp,end,n);
}
}
}

Euler 14 - Runtime too long (Not really duplicate, I didn't understand how to solve it from similar answer)

So I'm solving Question #14 on ProjectEuler and my code's output is not coming out. The method is good, if I use the example from the website I get the same result BUT I think I get stuck in loop, I don't get a result even if I use a number like "3" or "4" not 1,000,000. What I'm doing wrong? I tried to understand the last question and I didn't really get much with that cache stuff.Here is my code:
import java.util.Arrays;
public class problem_14 {
// n->n/2 (even)
// n->3n+1(odd)
static long max=0;
static long counter = 0;
//Which starting number, under one million, produces the longest chain?
public static long dochain(long n){
while(n!=1){
if(n%2==0){
n=n/2;
counter++;
}
else {
n=(3*n)+1;
counter++;
}
}
counter++;
return counter;
}
public static void main(String args[]){
long chain=0;;
long nr=0;
for(int i=0;i<1000000;i++){
chain = dochain(i);
if (chain>max){
max = chain;
nr = i;
}
System.out.println("nr="+nr+" lungime="+max);
}
}
}
Your dochain() method goes into an infinite loop if you give it a 0.
while (n != 1) {
if (n % 2 == 0) { // true for n == 0
n = n / 2; // n is still 0
counter++;
} else {
n = (3 * n) + 1;
counter++;
}
}
You are checking if it's divisible by 2, which it is, then dividing by 2, which leaves n == 0 and looping forever.
Since your main for loop starts at 0...
You are starting your for loop from i = 0 which is causing dochain() to run infinitely.
Start from i =1.

Is this implementation of gcd correct

public static int divisor(int m, int n) {
if (m == 0 || n == 0) {
return m+n;
} else {
return divisor(n, m%n);
}
}
It's giving me wrong answers for some input(I don't know which as they don't reveal which input they use for test case) in the amazon.interviewstreet.com
Also why this implementation keeps giving me stackoverflow(again no idea for which inputs)
public static int divisor(int m, int n) {
if(m == 0 || n == 0) {
return m+n;
} else if (m > n) {
return divisor(n, m%n);
} else {
return divisor(m, n%m);
}
}
Please let me know what am I missing. I'm new to programming and am still a beginner.
I think first one is a code for a programming contest. If so be careful with your data types. May be 'int' is not enough to hold the inputs. Try 'long' instead.
(and this will work only if your algorithm is correct.)
I think
return(m, n%m);
should be
return divisor(m, n%m);
Maybe invalid handling of negative values of n and m?
Read e.g. this: Best way to make Java's modulus behave like it should with negative numbers?
for the second part what is
return(m, n%m);
Is this code get compiled ?
use :
public static int divisor(int m, int n) {
if(m == 0 || n == 0)
return m+n;
else if(m>n)
return divisor(n, m%n);
else
return divisor(m, n%m);}
First,
return(m, n%m)
definitely does not compile, I suppose it was meant to be
return divisor(m, n%m);
Second, I guess what is wrong in the second snippet is handling of negative numbers.
Because A and B have the same GCD as -A and -B, I would add
m = Math.abs(m);
n = Math.abs(n);
to the beginning of the method
For the second part :
Also why this implementation keeps giving me stackoverflow(again no idea for which inputs)?
Try this input set :
5
3 1 16 5 10
It will give you the stackoverflow error. For your given code in pastebin.
Why ?
If the input is '1' there will be this problem.
edit your code part like below and see the out put for input (1 1).
public static int divisor(int m, int n) {
System.out.println("### "+m+" "+n);
if (m == 0 || n == 0) {
return m + n;
} else if (m > n) {
return divisor(n, m % n);
} else {
return divisor(m, n % m);
}
}
in some point out put will be like this :
.
.
### 1 1134903170
### 1 0
### 1 1836311903
### 1 0
### 1 -1323752223
### -1323752223 1
### -1323752223 1
### -1323752223 1
.
.
because in your code the function calling is like below.
public static int divFib(int num) {
int i = 1, j = 2, temp;
while (divisor(num, j) == 1) {
temp = j;
j = j + i;
i = temp;
}
return j;
}
divisor(num, j) will be called like divisor(1, 2) then below part will execute
else {
return divisor(m, n % m);
}
the calling will be like divisor(1,0) because n%m = 2%1 =0
then '1' will be return as (m+n = 1).
then while (divisor(num, j) == 1){} will execute again and 'j' will be get increased. But 'num' is '1'. the same thing happens again and again. resulting 'j' to be a huge number and eventually it will assigned a negative number. (I think you know why its happening).
The thing is this will not ever stopped. so the stack will be overflowed due to huge number of function calls.
I think this is a quite clear explanation and if you have any doubt please ask.
(Sorry i mistakenly post the answer here.)

Categories

Resources