I'm currently working through "Algorithms in java" by Robert Sedgewick (3rd edition, german version) on my own and I'm trying to solve one of the exercises there.
Problem Statement
The exercise asked to create an int[][] 2D array with \$2^n\$ rows in which each row stores the binary representation of its own index but using \$n\$ cells (so first cell is not always '1'). It also asks to do this recursively.
This can be done 2 ways:
- By writing 2 different recursive methods. One, to access the first cell in each row where it starts and the second method to fill the row
- By writing 1 recursive method that contains both recursions
My Thoughts
I deemed the second one to be more difficult and since I'm still struggling with recursion, I tried to solve the exercise using the harder approach in order to potentially learn more. I'd therefore also ask you to pay special attention to the recursive fill()
and how it is written with that goal in mind. Below is my solution, but first an explanation how the fill method is intended to work.
My Solution
- The variable array is the 2D array that shall contain the binary representations of all numbers between \$0\$ and \$(2^n)-1\$.
toBinary
is a char[] of theInteger.toBinary(num)
string. Each row has their own toBinary due to every row storing the binary representation of a different number.num
is the number whose binary representation is stored in row 'num'array.numBinaryIndex
is used to traverse the binary representation ofnum
and fill the cells in row 'num'
Note: the '0's and '1's from toBinary of num are converted to int and copied over to array[num]
. If toBinary.length of num !=
array[num].length
=\$2^n\$ (e.g. toBinary.length
= 1 for num = 1 and array[num].length
= 8 for n=3), all cells from 0 to
delta_Array_toBinary-1 shall be filled with 0.
Then, starting from array[num][delta_Array_toBinary]
, the rest of the row shall be filled with the contents of toBinary converted into int, starting from 0 to
toBinary.length using numBinaryIndex - delta_Array_toBinary
.
public class Aufgabe5_25 {
static void fill(int[][] array, int num, int numBinaryIndex, char[] toBinary) {
/*-
* - End the recursion filling first cells in rows if the index (num) moves
* past array.length
* - End the recursion filling rest of the rows if the
* index (numBinaryIndex) moves past array[num].length
*/
if (num == array.length || numBinaryIndex == array[num].length) {
return;
}
/*
* Recursively fill all array[num][0] and start recursions to fill all
* cells of array[num]
*/
if (numBinaryIndex == 0) {
toBinary = Integer.toBinaryString(num).toCharArray();
if (toBinary.length == array[num].length) {
array[num][0] = toBinary[0];
} else {
array[num][0] = 0;
}
/* Recursion to go to next row at array[num+1][0] */
fill(array, num + 1, 0, toBinary);
}
/*
* Is accessed after num == array.length happens, recursively fills the
* rows for each recursion that has been started in the
* if(numBinaryIndex == 0) part.
*/
if ((array[num].length) - numBinaryIndex > toBinary.length) {
array[num][numBinaryIndex] = 0;
fill(array, num, numBinaryIndex + 1, toBinary);
} else {
int delta_Array_toBinary = (array[num].length - toBinary.length);
/*-'0' to convert from char to int*/
array[num][numBinaryIndex] = (toBinary[numBinaryIndex - delta_Array_toBinary] - '0');
fill(array, num, numBinaryIndex + 1, toBinary);
}
}
/*
* Hides parameters needed to start recursion that have to be given as
* null/0 in the beginning
*/
static void fill(int[][] array) {
fill(array, 0, 0, null);
}
static void printArray(int[][] array) {
System.out.println("Final Print");
for (int i = 0; i < array.length; i++) {
System.out.print(i + ": ");
for (int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
/*
* Create 2D array of all numbers between 0 and 2^n (excluding 2^n) and
* fill it.
*/
int n = 4;
int[][] array = new int[(int) Math.pow(2, n)][n];
fill(array);
/* Print 2D array for checking purposes */
printArray(array);
}
}
Final Statements
This does produce the intended results (checked for 2,3,4,5), but as you can see, this code seems bloated and not quite that readable. My questions are
Could this solution be written more concisely/elegantly bearing in mind earlier mentioned approach number 1 (meaning the reason it is this bloated is just due to me struggling with recursion still)?
In contrast, could one say that there is a lesson here that double-recursions should never be done using only 1 recursive method (meaning one should always use earlier mentioned approach number 2)?