Recursion: Binary to Decimal - java

I am working on a recursive method that takes a binary number as a string and displays its decimal equivalent. I am unsure if my base cases are correct. Also, am I properly imposing recursion within the method?
public static void main(String[] args){
System.out.println("Enter a binary string ");
String binary = input.nextLine();
System.out.println("The decimal equivalent of " + binary + " is "+ binary2Decimal(binary));
}
//MethodOverloading
public static int binary2Decimal(String binary){
return binary2Decimal(binary,0, binary.length()-1);
}
public static void binary2Decimal(String binary, int low, int high){
int temp=0;
if(binary.charAt(high) == 0)
temp *= 2;
else if(binary.charAt(high) == 1)
temp = (temp * 2) + 1;
return binary2Decimal(binary,low,high -1)+temp;
}
}

You don't have a base case; binary2Decimal (3-arg version) always calls itself. (Since the only thing changing from one call to the next is high, your base case should probably involve that somehow.)

Some points:
Your method:
public static void binary2Decimal(String binary, int low, int high)
should have a return type of int instead of void.
You aren't using your variable low (so you can get rid of it if you want).
You need a base case with some code like:
if (high == 0) {
return somevalue;
}
else {
return binary2Decimal(binary,low,high -1)+temp;
}
Otherwise you will get into an infinite loop, and your method will recurse indefinitely.

Related

Finding the Base 2 Logarithm of a number using Recursion in java

I'm trying to write a recursive method in Java to find the base 2 log for multiples of 2.
I've successfully computed the log using this recursive method.
import java.util.*;
class temp
{
static int log(int number)
{
if(number==1)
return 0;
return log(number/2)+1;
}
public static void main(String s[])
{
Scanner input=new Scanner(System.in);
System.out.println("Enter Multiple of 2:");
System.out.println("Log is:"+log(input.nextInt())); //calling log with return value of nextInt()
}
}
Where I've run aground is trying to implement the same program using a different method , a method where i start multiplying from 2 in recursive calls until it becomes equal to the given number. Here's what i've tried:
class logarithmrecursion
{
static int step=1;
static int log(int number)
{
final int temp=number;
if(number>=temp && step!=1)
return 0;
step++;
return log(number*2)+1;
}
}
During the first call, number is equal to temp so i use a step variable to prevent the execution of the termination condition.If i don't use "number" variable in the recursive call, i don't have a way to accumulate the previous product but number variable is already equal to temp and will trigger the termination condition in the next recursive call , thus always giving output 1.
What can i do to make this program work?
The first, reducing, version has a fixed termination value of 1.
But the second version's termination depends on the number, so you have to pass that into the recursive call. So, your main function calls a private recursive version:
static int log(int number) {
return log(number, 1);
}
private static int log(int number, int current) {
return current < number ? log(number, current * 2) + 1 : 0;
}
Note: Your algorithm rounds the value up. To give the (more expected) rounded down result, which agrees with (int)(Math.log(i) / Math.log(2)), use this variation:
private static int log(int number, int current) {
return current <= number / 2 ? log(number, current * 2) + 1 : 0;
}
This kind of pattern - using a wrapper function - is common where initial state of the recursion needs to setup once, but we don't want to burden the caller with having to know about what is an implementation choice.
Your first method may also be coded as one line:
static int log(int number) {
return number == 1 ? 0 log(number/2) + 1;
}
try this:
import java.util.Scanner;
public class LogTest
{
static int calLog(final int number)
{
if(number < 2) {
return 0;
}
return log(number, 2, 1);
}
static int log(final int number, final int accumulated, final int step)
{
if(accumulated >= number) {
return step;
}
return log(number, accumulated * 2, step+1);
}
public static void main(String s[])
{
Scanner input=new Scanner(System.in);
System.out.println("Enter Multiple of 2:");
System.out.println("Log is:"+calLog(input.nextInt())); //calling log with return value of nextInt()
}
}

how to count many times a character occurs in a string without using s loop

the code below is meant to count each time character 'x' occurs in a string but it only counts once ..
I do not want to use a loop.
public class recursionJava
{
public static void main(String args[])
{
String names = "xxhixx";
int result = number(names);
System.out.println("number of x: " + result);
}
public static int number (String name)
{
int index = 0, result = 0;
if(name.charAt(index) == 'x')
{
result++;
}
else
{
result = result;
}
index++;
if (name.trim().length() != 0)
{
number(name);
}
return result;
}
}
You could do a replacement/removal of the character and then compare the length of the resulting string:
String names = "xxhixx";
int numX = names.length() - names.replace("x", "").length(); // numX == 4
If you don't want to use a loop, you can use recursion:
public static int number (String name)
{
if (name.length () == 0)
return 0;
int count = name.charAt(0)=='x' ? 1 : 0;
return count + number(name.substring(1));
}
As of Java 8 you can use streams:
"xxhixx".chars().filter(c -> ((char)c)=='x').count()
Previous recursive answer (from Eran) is correct, although it has quadratic complexity in new java versions (substring copies string internally). It can be linear one:
public static int number(String names, int position) {
if (position >= names.length()) {
return 0;
}
int count = number(names, position + 1);
if ('x' == names.charAt(position)) {
count++;
}
return count;
}
Your code does not work because of two things:
Every time you're calling your recursive method number(), you're setting your variables index and result back to zero. So, the program will always be stuck on the first letter and also reset the record of the number of x's it has found so far.
Also, name.trim() is pretty much useless here, because this method only removes whitespace characters such as space, tab etc.
You can solve both of these problems by
making index and result global variables and
using index to check whether or not you have reached the end of the String.
So in the end, a slightly modified (and working) Version of your code would look like this:
public class recursionJava {
private static int index = 0;
private static int result = 0;
public static void main(String[] args) {
String names = "xxhixx";
int result = number(names);
System.out.println("number of x: " + result);
}
public static int number (String name){
if(name.charAt(index) == 'x')
result++;
index++;
if(name.length() - index > 0)
number(name);
return result;
}
}
You can use StringUtils.countMatches
StringUtils.countMatches(name, "x");

java : Inverted string triangle using recursion?

I'm trying to write a method that accept a string and print an
inverted triangle from it. For example, if I had
trianglePrint("abcdefgh"), the output would be
abcdefgh
abcfgh
abgh
ab
It kinda of works...it's just that I'm getting the following errors
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
-1 at Triangle.trianglePrint(Triangle.java:39) at Triangle.trianglePrint(Triangle.java:43) at
Triangle.trianglePrint(Triangle.java:43) at
Triangle.trianglePrint(Triangle.java:43) at
Triangle.trianglePrint(Triangle.java:43) at
Triangle.trianglePrint(Triangle.java:17) at
Triangle.main(Triangle.java:6)
Any suggestions on what I'm doing wrong? Suggestions on a more
efficient way to code this, will be appreciated too.
public class Triangle
{
public static void main(String[] args)
{
trianglePrint("abcdefgh");
}
public static void trianglePrint(String string)
{
int length,terms ;
length =string.length() ;
if (length%2==0)
terms = (length/2);
else
terms = (length/2) +1 ;
trianglePrint(string,terms,length);
}
public static void trianglePrint(String string,int terms,int length)
{
String [] Array = new String [terms];
int padterm= length ;
/*if (length%2==0)
terms = (length/2);
else
terms = (length/2) +1 ;
*/
if (terms == 1)
if (length%2==0)
Array[0]=pad(string.substring(0,2),padterm) ;
else
Array[0]=pad(string.substring(0,1),padterm) ;
else
Array[terms-1]=pad((string.substring(0, terms)
+string.substring(length-terms)),padterm);
//use to monitor value of term
System.out.println(terms);
//used to monitor actual array content
System.out.println(Array[terms-1]);
trianglePrint(string,(terms-1),length);
}
public static void printList(String[] list,int position)
{
if (position < list.length)
System.out.println(list[position]);
printList(list,position+1);
}
//pads with appropriate spaces
public static String pad(String string,int length)
{
String result ;
if (string.length() >= length)
result = string ;
else
result = pad(" "+ string+" " ,length);
return result ;
}
}
You need a condition to stop the recursion. If terms is 0, then Array[terms-1] will cause Exception, like:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at Triangle.trianglePrint(Triangle.java:46)
So when variable temrs becomes 0, we need to stop recursion. You can add the following code to trianglePrint method, which will make your program work.
if(0 == terms)
{
return;
}
Change
public static void trianglePrint(String string,int terms,int length)
{
to
public static void trianglePrint(String string,int terms,int length)
{
if(0 == terms)
{
return;
}
Output in console;
4
abcdefgh
3
abcfgh
2
abgh
1
ab
I wrote new code to solve the problem for you, using recursion. I believe it is both shorter and more efficient than your existing solution. An assumption goes into this: the strings have an even number of digits (you didn't explain how to handle odd number of digits)
public static void solve(String word) {
solve(word, 0);
}
public static void solve(String word, int it) {
// print starting spaces
for(int i = 0; i < it; i++)
System.out.print(" ");
// print out string
System.out.print(word);
// print new line
System.out.println();
if(word.length() > 2) {
int newlengthperside = (word.length() - 2)/2;
solve( word.substring(0, newlengthperside) + word.substring(word.length() - newlengthperside), it+1);
}
}
To understand this code, first look at the main method. We have a for loop that prints out a certain number of spaces before the string, based on the variable passed to the method, then we print out the string, then we print out a new line. Afterwards, we determine if the length of the string is not finished yet, and we take the left side and the right side of the new string, and call the method again. This recursion will terminate once the string has less than or equal to 2 characters.
We also make the method easy to use by overloading the method with another solve that just takes in a word, and calls the main solve method with that word and 0, the number of spaces to initially print.
Your algorithm (as I understand it), seems to simplify into this
public static void trianglePrint(String in,
int offset) {
if (offset >= in.length()) { // Terminating condition.
return;
}
StringBuilder sb = new StringBuilder(offset); // For padding.
for (int i = 0; i < offset; i++) {
sb.append(' ');
}
final String padding = sb.toString(); // This is the padding, so don't clear.
sb.append(in); // Add the current input.
sb.append(padding); // Add more "invisible" padding.
System.out.println(sb.toString()); // print it.
int left = in.length() / 2; // One half.
String lh = in.substring(0, left - 1); // the left.
String rh = in.substring(left + 1, in.length()); // the right.
trianglePrint(lh + rh, offset + 1); // recurse.
}
public static void trianglePrint(String in) {
trianglePrint(in, 0);
}
You're doing recursion to simply decrement the terms argument. This is not a good use of recursion (outside of a functional programming language optimized for tail recursion) and would be better implemented using a for loop. The good recursive paradigm for this would be to actually shorten the string:
public static void trianglePrint(String string) {
trianglePrint(string, 0);
}
public static void trianglePrint(String string, int padding) {
for (int i = 0; i < padding; i++) {
System.out.print(" ");
}
System.out.println(string);
if (string.length > 2) {
int midpoint = string.length()/2; //assumes string length is even
trianglePrint(string.substring(0, midpoint - 1) + string.substring(midpoint + 1), padding + 1);
}
}
Not necessarily the fastest code, but very simple.
A slightly different approach can simplify further by leveraging the recursion more fully for the padding. StringBuilder also makes it easier to delete from the middle of a string:
public static void trianglePrint2(String s) {
System.out.println(s);
int mid = s.length()/2;
if (!s.replace(" ", "").equals("")) //if not all spaces
trianglePrint(" " + new StringBuilder(s).delete(mid-1, mid+1) + " ");
}
or alternatively (more efficient):
public static void trianglePrint(String s) {
trianglePrint(s, s.length()/2);
}
public static void trianglePrint(String string, int mid) {
System.out.println(s);
if (string.length() > mid)
trianglePrint(" " + new StringBuilder(s).delete(mid-1, mid+1), mid);
}
Both will work with odd or even lengths.

java.lang.OutOfMemoryError: Java heap space and HashMap

Sorry to post this code again. Previously the issue was I got a stack overflow error which was fixed by using long instead of int. However for a big value of n, I got a Exception in thread "main" java.lang.OutOfMemoryError: Java heap space.
Question:
Given a positive integer n, prints out the sum of the lengths of the Syracuse
sequence starting in the range of 1 to n inclusive. So, for example, the call:
lengths(3)
will return the the combined length of the sequences:
1
2 1
3 10 5 16 8 4 2 1
which is the value: 11. lengths must throw an IllegalArgumentException if
its input value is less than one.
My Code:
import java.util.*;
public class Test {
HashMap<Long,Integer> syraSumHashTable = new HashMap<Long,Integer>();
public Test(){
}
public int lengths(long n)throws IllegalArgumentException{
int sum =0;
if(n < 1){
throw new IllegalArgumentException("Error!! Invalid Input!");
}
else{
for(int i=1;i<=n;i++){
sum+=getStoreValue(i);
}
return sum;
}
}
private int getStoreValue(long index){
int result = 0;
if(!syraSumHashTable.containsKey(index)){
syraSumHashTable.put(index, printSyra(index,1));
}
result = (Integer)syraSumHashTable.get(index);
return result;
}
public static int printSyra(long num, int count) {
if (num == 1) {
return count;
}
if(num%2==0){
return printSyra(num/2, ++count);
}
else{
return printSyra((num*3)+1, ++count) ;
}
}
}
Since I have to add to the sum of the previous numbers, I will end up Exception in thread "main" java.lang.OutOfMemoryError: Java heap space for a huge value of n. I know the hashtable is suppose to assist in speeding up the calculations. How do I make sure that my recursion method, printSyra can return the value early if it has encountered an element that I have calculated before using the HashMap.
Driver Code:
public static void main(String[] args) {
// TODO Auto-generated method stub
Test t1 = new Test();
System.out.println(t1.lengths(90090249));
//System.out.println(t1.lengths(3));
}
you need to use iterative method instead of recursion. that recursive method will make pressure on the stack trace of the thread.
public static int printSyra(long num, int count) {
if (num == 1) {
return count;
}
while (true) {
if (num == 1) break; else if (num%2 == 0) {num /= 2; count++;) else {num = (num*3) + 1; count++;}
}
return count;
}

How to create a program that adds subtracts devides and multiplies 2 fractions?

first i would like to start saying that i am new to programing and i don t know much. with that said i would appreciate if anyone could help me with my program that it is supposed to read 2 fractions and an operator for example "2/3 + 4/5". i have some of the code done but it still give me an error when i run it here is what i have so far:
public class Fraction {
private static int numer;
private static int denom;
public Fraction(int num, int den)
{
numer = num;
denom = den;
simplify();
}
int findGcd(int a, int b)
{
int temp;
while(b != 0)
{
temp = b;
b = a % b;
a = temp;
}
return a;
}
void simplify()
{
int gcd = findGcd(numer, denom);
numer /= gcd;
denom /= gcd;
}
public int getNumer(){
return numer;
}
public int getDenom(){
return denom;
}
Fraction add(Fraction x) {
Fraction result;
if (x.getDenom()== getDenom()) {
result = new Fraction(x.getNumer() + getNumer(), denom);
} else {
denom = this.getDenom() * x.getDenom();
numer = this.getNumer() * x.getDenom() + x.getNumer() * this.getDenom();
return new Fraction(numer,denom);
}
return result;
}
public String toString(){
return (Integer.toString(numer) + "/" +
Integer.toString(denom));
}
public static void main (String []args){
Fraction a = new Fraction(1,3);
Fraction b = new Fraction(4,5);
System.out.println(a.toString());
System.out.println(b.toString());
}
}
thank you for your help i really appreciate it.
Why are you making your fields static? static fields belong to the class as opposed to each instantiation (not what you want here). Try removing the static keyword.
On another note, you mentioned that you'd like to read input from the user. You might want to look into using a Scanner for this (in case you don't already know about this handy class).
Once you read the input, something like 2/3 + 4/5, you can split your string using a space as your delimiter. Now, you can parse a fraction from the first (2/3) and third (4/5) elements of the newly formed string array, and perform the operation that corresponds to the second element of the array (+).
There is a difference between static variable and instance variable.
Static variable is a class variable which is common for all instances.. So, if you change these variables for one instance, it will be changed for all the instances.
Instance variable, on the other hand, are specific to each instance.. They are binded to an instance of a class.
That being said.. You need to modify your code a little bit..
Change your static variables in your class to instance variables..
private static int numer;
private static int denom;
The above two variables should be instance variables.. So that they are unique for each instance you create for your class..
So, change them to: -
private int numer;
private int denom;
And for reading user input, A.R.S has already given you link to a valuable class..

Categories

Resources