Series of nested loops without recursion - java

In Java, I have the following general code for integer d equal to 2, 3, 4, ..., dmax - up to a maximum number dmax : d < dmax (so this code is repeated for every value of d in that range):
// d is the number of wrapper loops
int[] ls = new int[d];
...
// let ls array be filled with some arbitrary positive numbers here
...
// first wrapper loop
for (int i1 = 0; i1 < ls[0]; i1++) {
...
// last wrapper loop
for (int id = 0; id < ls[d - 1]; id++) {
// internal loop
for (int j = id + 1; j < ls[d - 1]; j++) {
myCode();
}
}
...
}
In case of d = 3 it looks like:
int ls = new int[3];
ls[0] = 5; ls[1] = 7; ls[2] = 5;
for (int i1 = 0; i1 < ls[0]; i1++) {
for (int i2 = 0; i2 < ls[1]; i2++) {
for (int i3 = 0; i3 < ls[2]; i3++) {
for (int j = i3 + 1; j < ls[2]; j++) {
myCode();
}
}
}
}
I want to gather all that repeated code into a single generalized one. For that purpose I can use the while loop and recursion like below:
int d = 2, dmax = 10;
while (d < dmax) {
// in algorithm ls is pre-filled, here its length is shown for clearance
int[] ls = new int[d];
for (int i = 0; i < ls[0]; i++) {
doRecursiveLoop(1, d, -1, ls);
}
d++;
}
doRecursiveLoop(int c, int d, int index, int[] ls) {
if (c < d) {
for (int i = 0; i < ls[c]; i++) {
// only on the last call we give the correct index, otherwise -1
if (c == d - 1) index = i;
doRecursiveLoop(c + 1, d, index, ls);
}
} else {
for (int j = index + 1; j < ls[d - 1]; j++) {
myCode();
}
}
}
Can anybody shed some light as to how I would approach this problem of dynamically occurred nested loops without recursion?

You effectively have tail recursion here. Any tail-recursive function can trivially be converted to an iterative function using a loop.
For example:
void foo() {
// ... Stuff ...
if (someCondition) {
foo();
} else {
bar();
}
}
becomes:
void foo() {
while (someCondition) {
// ... Stuff ...
}
bar();
}

Related

Non-repeating numbers in 2D array

I have problem with my code, I want to find not repeated numbers in array but I don't know how!
1 2
3 4
1 4
For example in this case, I wan the output to be number 3 and 2:
I used this code for getting array, it's like a matrix
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 2; j++) {
cam[i][j] = in.nextInt();
}
}
And something like this one for comparing for each one:
for (int i = 1; i <= 3; i++) {
if (cam[i][2] != cam[i+1][2]) {
y = cam[i+1][2];
break;
}
}
Update: whole code is down below
int x=0,y=0;
int[][] cam = new int[10][10];
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 2; j++) {
cam[i][j] = in.nextInt();
}
}
for (int i = 1; i <= 3; i++) {
if (cam[i][1] != cam[i+1][1]) {
x = cam[i+1][1];
break;
}
for (int i = 1; i <= 3; i++) {
if (cam[i][2] != cam[i+1][2]) {
y = cam[i+1][2];
break;
}
}
System.out.println(x+" "+y);
Array indices are 0, 1, 2, ..., length-1.
for (int i = 0; i < cam.length; i++) {
for (int j = 0; j <= cam[i].length; j++) {
cam[i][j] = in.nextInt();
}
}
The search code:
for (int i = 0; i < cam.length; i++) {
for (int j = 0; j <= cam[i].length; j++) {
int valueAtIJ = cam[i][j];
boolean found = false;
... walk here through cam using valueAtIJ, set found, skip i, j.
if (!found) {
...
}
}
}
If alread Set/Map is treated in your course there are smarter solutions. But also this kind of for-i2-for-j2 loop can be optimized.
Assuming from your code that you are looking only in column 1 and 2 (do you have other data in column 0?):
for (int i = 1; i <= 3; i++) {
found = false;
for (int i1 = i + 1; i1 <= 3; i1++) {
if (cam[i][1] == cam[i1][1]) {
found = true;
break;
}
}
if (!found) {
x = cam[i][1];
}
}
for (int i = 1; i <= 3; i++) {
found = false;
for (int i1 = i + 1; i1 <= 3; i1++) {
if (cam[i][2] == cam[i1][2]) {
found = true;
break;
}
}
if (!found) {
y = cam[i][2];
}
}
You can collect a map of duplicates from this 2d array, then iterate over this map and apply filter for non-repeating elements:
int[][] arr = {
{1, 2},
{3, 4},
{1, 4}};
Map<Integer, Long> map = Arrays.stream(arr)
.flatMapToInt(Arrays::stream).boxed()
.collect(Collectors.groupingBy(
Integer::intValue, Collectors.counting()));
System.out.println(map); // {1=2, 2=1, 3=1, 4=2}
int[] arr2 = map.entrySet().stream()
.filter(e -> e.getValue() == 1)
.mapToInt(Map.Entry::getKey)
.toArray();
System.out.println(Arrays.toString(arr2)); // [2, 3]
See also: How to find duplicate elements in array in effective way?

How to use LSD String Sort without having to enter a fixed length?

sorry for my bad english. I'm styding LSD String Sorts algorithm and I have a question related to it. Here my code. I want input W not fixed, for example:
String[] a = {"38A", "3TW723", "2IYEA938", "3CI34780720"};
public static void sort(String[] a, int w) { // Sort a[] on leading W characters.
int R = 256;
int N = a.length;
//For each of the character from right to left
for (int d = w - 1; d >= 0; d--) {
//1. count the frequencies
int[] count = new int[R + 1];
for (int i = 0; i < N; i++) {
count[a[i].charAt(d) + 1]++;
}
//2. Transform counts to indices
for (int r = 0; r < R; r++) {
count[r + 1] += count[r];
}
//3. Distribute
String aux[] = new String[N];
for (int i = 0; i < N; i++) {
aux[count[a[i].charAt(d)]] = a[i];
count[a[i].charAt(d)]++;
}
//4. Copyback
System.arraycopy(aux, 0, a, 0, N);
}
}
To develop an implementation of LSD string sort that works for variable-length strings, we need to do many works on the base of your code. We need to find the longest length of string in string[] a, so when d >= a[i].length(), we return 0, which means we add extra 0 to make every string in the same length. This is my code.
// Develop an implementation of LSD string sort
// that works for variable-length strings.
public class LSDForVariableLengthStrings {
// do not instantiate
private LSDForVariableLengthStrings() { }
// find longest length string in string[] a.
public static int findLongestLength(String[] a) {
int longest = 0;
for (int i = 0; i < a.length; ++i) {
if (a[i].length() > longest) {
longest = a[i].length();
}
}
return longest;
}
// if d >= 0 && d < a[i].length(), return a[i].charAt(d);
// else , return 0, which means least value to sort.
public static int findCharAtInString(int i, int d, String[] a) {
if (d < 0 || d >= a[i].length()) {
return 0;
}
return a[i].charAt(d);
}
// Rearranges the array of variable-length strings.
public static void sort(String[] a) {
int n = a.length;
int R = 256; // extended ASCII alphabet size.
String[] aux = new String[n];
int w = findLongestLength(a); // w is the length of longest string in a.
for (int d = w - 1; d >= 0; d--) {
// sort by key-indexed counting on dth character
// compute frequency counts
int[] count = new int[R + 1];
for (int i = 0; i < n; ++i) {
int c = findCharAtInString(i, d, a);
count[c + 1]++;
}
// compute cumulates
for (int r = 0; r < R; ++r) {
count[r + 1] += count[r];
}
// move data
for (int i = 0; i < n; ++i) {
int c = findCharAtInString(i, d, a);
aux[count[c]++] = a[i];
}
// copy back
for (int i = 0; i < n; ++i) {
a[i] = aux[i];
}
}
}
public static void main(String[] args) {
String[] a = {"38A", "3TW723", "2IYEA938", "3CI34780720"};
int n = a.length;
// sort the strings
sort(a);
// prints results
for (int i = 0; i < n; ++i) {
System.out.println(a[i]);
}
}
}
LSD sorts only fixed-length strings. Use MSD instead

Why System.arraycopy() function is not creating copy but returning reference to the same array?

I have written following piece of code to check the behavior of System.arraycopy and clone functions. I expect these functions to return a copy of the array but all they are doing is returning a reference to the original array, which is evident from the later part of program where I change the values of original. The copy should not change but it also changes. Please help why its behaving in this way?
public class Testing {
public static int a[][] = new int[2][2];
public static void setValueOfA() {
a[0][0] = 1;
a[0][1] = 1;
a[1][0] = 1;
a[1][1] = 1;
}
public static int[][] getValueOfA() {
int[][] t = new int[2][2];
// Case 1: Not working
// t = (int[][]) a.clone();
// Case 2: Not working
// System.arraycopy(a, 0, t, 0, 2);
// Case 3: Working
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
t[i][j] = a[i][j];
}
}
return t;
}
public static void main(String[] args) {
int[][] temp;
setValueOfA();
temp = getValueOfA();
System.out.println("Value of a");
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
System.out.print(a[i][j] + " ");
}
System.out.println();
}
System.out.println("Value of temp");
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
System.out.print(temp[i][j] + " ");
}
System.out.println();
}
a[0][0] = 2; a[0][1] = 2; a[1][0] = 2; a[1][1] = 2;
System.out.println("Value of a");
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
System.out.print(a[i][j] + " ");
}
System.out.println();
}
System.out.println("Value of temp");
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
System.out.print(temp[i][j] + " ");
}
System.out.println();
}
}
}
I believe (haven't tested it) that System.arraycopy performs a shallow copy of the source array to the target array.
Your call to System.arraycopy is equivalent to :
t[0] = a[0];
t[1] = a[1];
Since a[0] and a[1] are themselves arrays, if you later change a[i][j], you are also changing t[i][j] (since a[i] and t[i] refer to the same array).
MUN,
You should use Arrays.copyOf() function. See an example:
http://www.tutorialspoint.com/java/util/arrays_copyof_int.htm
/N.
Arrays.copyOf implicitly uses System.arraycopy which does only shallow copy.
To do a deep copy use the traditional way of iterating and assigning.

Can you give me idea on how to code this program using array and for loops?

I was supposed to make a program using for loop and arrays now the output program will need to show something like this
0-1-0-0-1-0-0-0-1-0-0-0-0-1
Notice that the 0 is adding every after the 1's show so far im stuck with this code can you help me please...
int[] binary = new int[150];
int b = 0;
int x = 3;
for(int a = 0; a < binary.length; a=a+2) {
box[a] =1;
}
for(int i =0; i < binary.length; i++){
for(b = 0; b < binary.length; b = b+x){
if(box[b] == 1) {
box[b] =0; // this condition changes the value of 1 to 0 if the binary is already "1".
}
else {
box[b] =1; // if the value of the binary is 0 it changes it to 1.
}
}
x++; // Putting this changes the value of the x making x=4 so that the next time the for loop runs it adds the int b to 4..(NOT SURE IF THIS IS RIGHT THOUGH)
}
for(int c =0; c < binary.length; c++) {
System.out.print(binary[c]); // "this should print the output "
}
My problem is making it show something like this
01001000100001000001
You're mixing multiple variable names, since you assign the values to box you should probably remove binary - so something like,
int[] box = new int[150];
int b = 0;
int x = 3;
for (int a = 0; a < box.length; a = a + 2) {
box[a] = 1;
}
for (int i = 0; i < box.length; i++) {
for (b = 0; b < box.length; b = b + x) {
if (box[b] == 1) {
box[b] = 0;
} else {
box[b] = 1;
}
}
x++;
}
for (int c = 0; c < box.length; c++) {
System.out.print(box[c]); // "this should print the output "
}
Output is
101101111011111101111111101111111111011111111111101111111111111101111111111111111011111111111111111101111111111111111111101111111111111111111111011111
I'm not sure to fully understand what you want. From your post I only understand that your goal is to have an output composed of 0 and 1 only and starting with a 0 immediately followed by a 1. The number of zeros following a 1 is successively increased by 1 : so you have after that 2 zeros followed by a 1 and then 3 zeros followed by a 1, 4 zeros followed by a 1 and so one : 0-1-00-1-000-1-0000-1.
Am I right ?
If that is what you want, try something like that :
int num_zero = 1;
int cptr = 0;
int[] arr = new int[20];
for(int j = 0; j < arr.length; j++){
if(cptr == num_zero){
arr[j] = 1;
num_zero = 1+ cptr;
cptr = 0;
}else{
arr[j] = 0;
++cptr;
}
}
Here is the output :
01001000100001000001
Try this:
int[] binary = new int[150];
int onesNextIndex = 1;
int onesGap = 2;
for(int i = 0; i < binary.length; i++){
if(i == onesNextIndex){
binary[i] = 1;
onesNextIndex += onesGap + 1;
onesGap++;
}else{
binary[i] = 0;
}
}
You can test it with:
for(int x : binary){
System.out.print(x);
}
it will print: 0100100010000100000100000010000000100000000..... etc
if you want it the other way around then :
int[] binary = new int[150];
int zerosNextIndex = 1;
int zerosGap = 2;
for(int i = 0; i < binary.length; i++){
if(i == zerosNextIndex){
binary[i] = 0;
zerosNextIndex += zerosGap + 1;
onesGap++;
}else{
binary[i] = 1;
}
}
this will print: 101101110111101111101111110111111101111111101111.......etc
Hope this helps

Java permutations 2

I asked a question on helping me with this question about a week ago
Java permutations
, with a problem in the print permutation method. I have tidied up my code and have a working example that now works although if 5 is in the 5th position in the array it doesn't print it. Any help would be really appreciated.
package permutation;
public class Permutation {
static int DEFAULT = 100;
public static void main(String[] args) {
int n = DEFAULT;
if (args.length > 0)
n = Integer.parseInt(args[0]);
int[] OA = new int[n];
for (int i = 0; i < n; i++)
OA[i] = i + 1;
System.out.println("The original array is:");
for (int i = 0; i < OA.length; i++)
System.out.print(OA[i] + " ");
System.out.println();
System.out.println("A permutation of the original array is:");
OA = generateRandomPermutation(n);
printArray(OA);
printPermutation(OA);
}
static int[] generateRandomPermutation(int n)// (a)
{
int[] A = new int[n];
for (int i = 0; i < n; i++)
A[i] = i + 1;
for (int i = 0; i < n; i++) {
int r = (int) (Math.random() * (n));
int swap = A[r];
A[r] = A[i];
A[i] = swap;
}
return A;
}
static void printArray(int A[]) {
for (int i = 0; i < A.length; i++)
System.out.print(A[i] + " ");
System.out.println();
}
static void printPermutation(int[] p)
{
int n = p.length-1;
int j = 0;
int m;
int f = 0;
System.out.print("(");
while (f < n) {
m = p[j];
if (m == 0) {
do
f++;
while (p[f] == 0 && f < n);
j = f;
if (f != n)
System.out.print(")(");
}
else {
System.out.print(" " + m);
p[j] = 0;
j = m - 1;
}
}
System.out.print(" )");
}
}
I'm not too crazy about
int n = p.length-1;
followed by
while (f < n) {
So if p is 5 units long, and f starts at 0, then the loop will be from 0 to 3. That would seem to exclude the last element in the array.
You can use the shuffle method of the Collections class
Integer[] arr = new Integer[] { 1, 2, 3, 4, 5 };
List<Integer> arrList = Arrays.asList(arr);
Collections.shuffle(arrList);
System.out.println(arrList);
I don't think swapping each element with a random other element will give a uniform distribution of permutations. Better to select uniformly from the remaining values:
Random rand = new Random();
ArrayList<Integer> remainingValues = new ArrayList<Integer>(n);
for(int i = 0; i < n; i++)
remainingValues.add(i);
for(int i = 0; i < n; i++) {
int next = rand.nextInt(remainingValues.size());
result[i] = remainingValues.remove(next);
}
Note that if order of running-time is a concern, using an ArrayList in this capacity is n-squared time. There are data-structures which could handle this task in n log n time but they are very non-trivial.
This does not answer the problem you have identified.
Rather i think it identifies a mistake with your generateRandomPermutation(int n) proc.
If you add a print out of the random numbers generated (as i did below) and run the proc a few times it allows us to check if all the elements in the ARRAY TO BE permed are being randomly selected.
static int[] generateRandomPermutation(int n)
{
int[] A = new int[n];
for (int i = 0; i < n; i++)
A[i] = i + 1;
System.out.println("random nums generated are: ");
for (int i = 0; i < n; i++) {
int r = (int) (Math.random() * (n));
System.out.print(r + " ");
Run the proc several times.
Do you see what i see?
Jerry.

Categories

Resources