Trouble using recursion to print out converging and diverging sequence of numbers - java

The wording of the problem is
"Write a method writeSequence that accepts an integer n as a parameter and prints a symmetric sequence of n numbers with descending integers ending in 1 followed by ascending integers beginning with 1, as in the table below:"
The table is essentially:
1 = 1
2 = 1 1
3 = 2 1 2
4 = 2 1 1 2
5 = 3 2 1 2 3
6 = 3 2 1 1 2 3
My attempted code is
public void writeSequence(int n){
if (n < 1){
throw new IllegalArgumentException();
}
if (n == 1){
System.out.print(n + " ");
}
else if (n == 2){
System.out.print(1 + " " + 1 + " ");
}
else if (n % 2 == 0){
System.out.print(n - (n/2) + " ");
writeSequence(n - (n/2));
System.out.print(n - (n/2) + " ");
}
else{
System.out.print(n-(n/2) + " ");
writeSequence(n - 2 );
System.out.print(n-(n/2)+ " ");
}
}
For inputs 1-10, my code is not generating the correct answer for 6, 8, and 10. Any help is greatly appreciated.
Edit:
Fixed spelling in title
Edit 2:
My results are
1 = 1
2 = 1 1
3 = 2 1 2
4 = 2 1 1 2
5 = 3 2 1 2 3
6 = 3 2 1 2 3 (wrong)
7 = 4 3 2 1 2 3 4
8 = 4 2 1 1 2 4 (wrong)
9 = 5 4 3 2 1 2 3 4 5
10 = 5 3 2 1 2 3 5 (wrong)
If someone could show me where I have made an error in my code that would be great!

Your recursive call passes the incorrect value. Each time the algorithm recurses, it should decrease the value by 2.
Change this:
writeSequence(n - (n/2));
to this:
writeSequence(n - 2);

Related

Recursive approach to finding out all the ways to change a €5 note?

I've been given a problem about finding all the possible combinations to change a 5 euro note. I've written a program that fails to result the correct number of combinations.
My approach was inspired from the following:
500 can be divided into 200, 200 and 100.
200 can be divided into 100 and 100.
100 can be divided into 50 and 50.
After I've written my code, I've realised that 100 can also be divided into 5 20's. This is a fault which I am aware of but I do not know how to fix using my approach.
My approach was a recursive one as can be seen below, it simply checks the first digit and divides it accordingly.
Here is what I tried:
public class Q1 {
public static int counter;
public static void main(String[] args) {
divide(500);
System.out.println(counter);
}
private static void divide(int x) {
System.out.println("Dividing " + x);
if(x == 1) {
return;
}
counter++;
int length = String.valueOf(x).length();
int fd = Integer.parseInt(Integer.toString(x).substring(0, 1));
String zeros;
if(fd != 1) {
zeros = Integer.toString(x).substring(1, length);
}else {
zeros = Integer.toString(x).substring(1, length-1);
}
if(fd == 5) {
divide(Integer.parseInt(2 + "" + zeros));
divide(Integer.parseInt(2 + "" + zeros));
divide(Integer.parseInt(1 + "" + zeros));
}else if(fd == 2) {
divide(Integer.parseInt(1 + "" + zeros));
divide(Integer.parseInt(1 + "" + zeros));
}else if(fd == 1) {
divide(Integer.parseInt(5 + "" + zeros));
divide(Integer.parseInt(5 + "" + zeros));
}
}
}
For example using the above program misses
10 = 2 + 2 + 2 + 2 + 2
I am aware of working solutions already present like this one but I would like to maintain my approach if possible.
Using the program to finding out the combinations for 500 cents results 388 ways, where the correct answer is 6295435. Something tells me I'm forgetting something else other than the above example.
Here are some hints about why you get the wrong number:
A correct way to determine all possibilities
Try to split 5 instead of 500 for simplicity. Notice that there are 4 possibilities, namely 5 =
5
2 + 2 + 1
2 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1
Now try dividing 10 instead of 500.
Notice that this can be split up into 11 different ways:
10 =
10
5 + 5
5 + 2 + 2 + 1
5 + 2 + 1 + 1 + 1
5 + 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
This solution follows the following pattern:
The number x you want to split is already an answer.
Decrease the amount of lowest numbers by 1 by splitting one of these numbers into as many next largest numbers as possible. Always ignore ones. If there is only one number (and ones) left, split x into as many next lowest numbers as possible and continue.
For example, x = 10. Then: 10 is the lowest number -> split it up into 5 + 5 -> 5 is the lowest number ->split it up into 2 + 2 + 1 -> 2 is the lowest number since ones are ignored -> split it up into 1 + 1 -> we have another 2, split it up into 1 + 1 (this is equal to the solution 5 + 1 + 1 + 1 + 1 so now we have 5 as only one number apart from ones. Next lowest number is 2)-> split x=10 into 2 + 2 + 2 + 2 + 2 -> 2 is the lowest number; split it into 1 + 1 -> we have another 2 ...
This can be done in an recursive approach.
Things that went wrong in your code
What you code does with the example of dividing 10 is the following:
10 is divided into 5 + 5
the first 5 is divided into 2 + 2 + 1
one of these twos is divided into 1 + 1
the other two is divided into 1 + 1
Now, the second 5 from the division into 5 + 5 is divided into 2 + 2 + 1
One of these twos is divided into 1 + 1
The other two is divided into 1 + 1
Giving it a total score of 7 possibilities.
Trying to map These 7 possibilities to the 11 above, you count 10 =
10 once
5 + 5 once
5 + 2 + 2 + 1 twice
5 + 2 + 1 + 1 + 1 twice
5 + 1 + 1 + 1 + 1 + 1 twice
and missing the other 6 options.
So the assumption that this question can be solved by an approach like this one:
10 = 5 + 5 -> evaluate the first 5, then evaluate the second 5
is wrong because in both cases this leads to a distribution of 10 = 5 + evaluation of 5, counting only the options where at least one 5 is contained in the final distribution of 10 (counting it multiple times whearas distributions without fives are not evaluated).
Another mistake is that the code says there is no possible distribution of 1 where there actually exists one (1 = 1).
Also, the question is unclear about
can x equal all possible whole numbers? -> 4 is not split up into 2 + 2 in your Code
is 1 + 1 + 2 a different solution from 1 + 2 + 1 and 2 + 1 + 1?
(I don't have the reputation to ask this in a comment yet).
Remaining an recursive approach can only be done with some significant changes. A possible way to do so is stated above.

Java - Simple formatting regarding power of 2 triangle

Overview
I'm sure this is a simple problem for most of you on here, but I have been struggling with a small spacing problem and was hoping I can learn from someone more experienced. I need to produce a triangle similar to the one below. You can see that the numbers are aligned correctly no matter the length.
Enter the number of lines: 8
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
1 2 4 8 16 32 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 64 32 16 8 4 2 1
My Code
Here is what I have so far. It isn't the prettiest, but it seems to give me the correct values at least.
import java.util.Scanner;
public class Pyramid2
{
public static void main(String[] args)
{
int i, j, k, l, a;
//Create a Scanner object
Scanner in = new Scanner (System.in);
//Prompt the user to enter number of rows in pyramid
System.out.print("Enter number of rows: ");
int rows = in.nextInt();
a = rows;
//Variables to determine length
int length = ("" + rows).length();
String str = " %" + length + "s";
//Logic
for (i = 1; i <= rows; i++)
{
for (j = a; j > 0; j--)
{
System.out.printf(str, " ");
}
for (j = 1; j <= (2*rows); j++)
{
if (j == (rows+1))
{
continue;
}
if (j < (rows+1))
{
k = j;
}
else
{
k = ((2*rows)-j+1);
}
if (k >= (rows+1-i))
{
l = (int)Math.pow(2, (i+k-rows-1));
String str1 = "" + l;
System.out.printf(str, str1);
}
}
a--;
System.out.println();
}
}
}
My Results
This is the console output when 6 rows are chosen. Everything looks good until row 5 when a 2 digit number (16) appears. What are some efficient ways to align the results properly?
Enter number of rows: 6
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
You calculate length as the number of digits in rows, but it needs to be number of digits in largest number in triangle.
E.g. for rows = 6, largest number is 32, so length should be 2.
For rows = 8, largest number is 128, so length should be 3.
Largest number is 2rows, which in Java means 1 << rows, so change length calculation to:
int length = ("" + (1 << rows)).length();
You are also adding one too many blanks on the left.
Change code to this:
a = rows - 1;
First of all i can recommend to determine the largest number in pyramid. Then count digits in this number. For 8 rows this number is 128, it has 3 digits. According this information we can decide that we need 3+1=4 (including spaces) characters to print every value in pyramid.
After it you have to complete every output number by spaces (from the left) to achive string size of 4 characters.
And the global prefix for every pyramid line will contain (rows - i) * 4 spaces.

Java - Bit manipulation (count number of 1s in number)

Can someone explain to my why this method works, I've worked through what it does, but why does this work. Is there a pattern that binary numbers have? Like for example at i = 3, why does it do res[1] + 1 to get 2. How does res[3 >> 1] + (3&1) help to count the number of ones in the binary number of 3?
What the code should do: It works so don't worry about that. It is supposed to return a list that contains the number of ones in the binary representation of each number until num+1. And num is always >= 0. So for num = 5, you would get [0, 1, 1, 2, 1, 2], where the last index represents the number of 1s in the binary representation of 5, and the first index is number of ones in binary rep of 0.
Code:
public int[] countBits(int num) {
int[] res = new int[num+1];
for (int i = 0; i<num+1; i++){
res[i] = res[i >> 1] + (i & 1);
}
return res;
}
This is the part I can't wrap my head around:
res[i] = res[i >> 1] + (i & 1);
EDIT - This is not homework, so please fully explain your answer. This is to help with interviews.
int[] res = new int[num+1];
for (int i = 0; i<num+1; i++){
res[i] = res[i >> 1] + (i & 1);
}
return res;
rewritten as
int[] res = new int[num+1];
for (int i = 0; i<num+1; i++){
x = res[i >> 1];
y = (i & 1);
res[i] = x + y;
}
return res;
Create an array to fit the answers, +1?
for each, starting at the low end.
res[0] = res[0] + 0&1 = 0 + 0 = 0;
res[1] = res[0] + 1&1 = 0 + 1 = 1;
res[2] = res[1] + 0&1 = 1 + 0 = 0;
res[3] = res[1] + 1&1 = 1 + 1 = 2;
Looking at this pattern, I can see that because of the right shift, and the masking with &, it's splitting the problem into 2, one that's been solved previously due to the iteration order, and a bit check of the last digit.
assuming a 8 bit int, for brevity,
1 = 00000001
2 = 00000010
3 = 00000011
Split the binary into parts.
i i>>1 y&1
1 = 0000000 1
2 = 0000001 0
3 = 0000001 1
So it fetches the results for the number of ones in the first half of the array, then counts the last digit.
Because of the iteration order, and array initialisation values, this is guaranteed to work.
For values < 0 , due to 2's compliment it gets hairy, which is why it only works for values >=0
in 'res[i] = res[i >> 1] + (i & 1);'
one number's result is divide into 2 parts
the last bit is 1 or not,which can be calculate by (i & 1).
the first (n-1) bits,this number is equals to res[i >> 1]'s bitcount.this is a simple recursive call
shift by 1 gives the floor number divided by 2.
AND 1 returns 1 if the last bit of the number is 1
Hope the below table helps to see what is happening :) Just my 2 cents.
<pre>
--------------------------------
<b>
# 8 4 2 1 >>1 &1 Ans
</b>
-------------------------------
0 0 0 0 0 0 0 0
1 0 0 0 1 0 1 1
2 0 0 1 0 1 0 1
3 0 0 1 1 1 1 2
4 0 1 0 0 2 0 1
5 0 1 0 1 2 1 2
6 0 1 1 0 3 0 2
7 0 1 1 1 3 1 3
8 1 0 0 0 4 0 1
9 1 0 0 1 4 1 2
10 1 0 1 0 5 0 2
11 1 0 1 1 5 1 3
12 1 1 0 0 6 0 2
13 1 1 0 1 6 1 3
14 1 1 1 0 7 0 3
15 1 1 1 1 7 1 4
</pre>

Finding Levenshtein distance on two string

I am trying to implement in Eclipse Java Levenshtein distance on the following two strings:
I took the idea from Wikipedia, but I don't know why my output is wrong, I need help to find my mistake/s.
"kruskal"
"causal"
package il.ac.oranim.alg2016;
public class OPT {
public static void main(String[] args)
{
char[] t={'k','r','u','s','k','a','l'};
char[] s={'c','a','u','s','a','l'};
for (int i=0;i<=s.length;i++)
{
for (int j=0;j<=t.length;j++)
System.out.print(LevenshteinDistance(s,t)[i][j]+" ");
System.out.println();
}
}
private static int[][] LevenshteinDistance(char s[], char t[])
{
// d is a table with m+1 rows and n+1 columns
int[][] d=new int[s.length+1][t.length+1];
for (int i=0;i<=s.length;i++)
d[i][0] = i; // deletion
for (int j=0;j<=t.length;j++)
d[0][j] = j; // insertion
for (int j=1;j<t.length;j++)
{
for (int i=1;i<s.length;i++)
{
if (s[i] ==t[j])
d[i][j]=d[i-1][j-1];
else
d[i][j] = Math.min(Math.min((d[i-1][ j] + 1),
(d[i][j-1] + 1)),
(d[i-1][j-1] + 1)) ;
}
}
return d;
}
}
My output:
0 1 2 3 4 5 6 7
1 1 2 3 4 4 5 0
2 2 1 2 3 4 5 0
3 3 2 1 2 3 4 0
4 4 3 2 2 2 3 0
5 5 4 3 3 3 2 0
6 0 0 0 0 0 0 0
The output should be:
0 1 2 3 4 5 6 7
1 1 2 3 4 5 6 7
2 2 2 3 4 5 5 6
3 3 3 2 3 4 5 6
4 4 4 3 2 3 4 5
5 5 5 4 3 3 3 4
6 6 6 5 4 4 4 3
If you reread the specifications, you will find there are two errors:
on the wikipedia, they use indices ranging from 1 to (and including n), a string starts at index i=1 according to Wikipedia where it is i=0 in Java; and
the weights are not updated correctly:
if (s[i] ==t[j])
d[i][j]=d[i-1][j-1];
In the specifications, this should be the minimum of d[i-1][j]+1, d[i][j-1]+1 and d[i-1][j-1]. It is not guaranteed that d[i-1][j-1] is the lowest value, so you should effectively calculate it.
If one takes these mistakes into account, one can modify the table update algorithm (changes on comment //):
for (int j=1;j<=t.length;j++) { //use <= instead of <
for (int i=1;i<=s.length;i++) { //use <= instead of <
if (s[i-1] ==t[j-1]) //use i-1 and j-1
d[i][j] = Math.min(Math.min(d[i-1][j]+1,d[i][j-1]+1),d[i-1][j-1]); //use the correct update
else
d[i][j] = Math.min(Math.min(d[i-1][j]+1,d[i][j-1]+1),d[i-1][j-1]+1);
}
}

Can't understand how recursion works in this example

I was given the following code:
public int func(int n){
if(n == 1)
return 2;
else
return 3 * func(n-1)+1;
}
I can understand recursion in things like factorial and fibonacci, but for this one I cant.
I tried to trace the logic:
if n is 3:
return 3 * func(2) + 1
return 3 * func(1) + 1
return 3 * 2 + 1
return 7
I always end up with 7 with any other number and I know this is wrong because I get different values when I run the program. Can you help me understand how recursion works here?
I think this is self-explanatory, if you need more informations just comment !
if n is 3:
return 3 * func(2) + 1
return 3 * (3 * func(1) + 1) + 1 //func(2) is equals to 3 * func(1) + 1
return 3 * (3 * 2 + 1) + 1 //func(1) is equals to 2
return 22
If n is 1 it returns 2 (so func(1) = 2).
If n is 2 it returns 3 * func(1) + 1, which is 3 * 2 + 1 = 7 (so func(2) = 7).
If n is 3 it returns 3 * func(2) + 1, which is 3 * 7 + 1 = 22 (so func(3) = 22).
If n is 4 it returns 3 * func(3) + 1, which is 3 * 22 + 1 = 67 (so func(4) = 67).
...
And so on. In other words, when n = 1 it simply returns 2 and it all other cases it returns the value for func(n - 1) times three and with one added.
if n is 3
func(3)
=3*func(2)+1
=3*(3*func(1)+1)+1
=3*(3*2+1)+1
=22
if n is 4
func(4)
=3*func(3)+1
=3*22+1
=67
You're close, but missing a key point:
func(3) is: 3 * func(2) + 1
func(2) is: 3 * func(1) + 1
func(1) is: 2
Therefore, func(2) is 3*2+1 = 7.
And func(3) is 3*7+1 = 22
when n=3 you get
func(3) = > return 3 * func(2) + 1
where func(2) is
func(2) = > return 3 * func(1) + 1
where func(1) is
func(1) = > return 2
once you combine them you get that
func(3) => return 3 * (3 * (2) + 1) + 1
func(3) => return 22
You have to reinput that value you get for the deepest recursion call into the previous level and so forth.
func(1) = 2
func(2) = 3 * func(1) + 1 = 7
func(3) = 3 * func(2) + 1 = 22
func(4) = 3 * func(3) + 1 = 67
As a general rule a recursive method has two parts,
The part for solving primitive problem, here in your example is
if(n == 1)
return 2;
The part for dividing the problem into smaller problems so that finally it falls under part 1 (primitive problem)
else
return 3 * func(n-1)+1;
This is the very nature of Divide and Conquer algorithms that tend to divide the problem into smaller pieces in each round until they became solvable. Then by joining the solved pieces, the original problem gets solved.

Categories

Resources