Hi can some one please explain me the below derangement/permutation program in a simple way.
From past one week I am banging my head to understand the program. I have understood all the methods but I am not able to understand the "else part". I have tried debugging the program but didn't get clarity to what is happening in the else part.
import java.util.Scanner;
public class Deranged {
public static void main(String args[]) {
Scanner s = new Scanner(System.in);
System.out.println("Enter a number");
int num = s.nextInt();
System.out.println("Number :" + num);
int size = digitSize(num);
System.out.println("Size :" + size);
System.out.println("Permutation :" + fact(size));
int swap = fact(size);
int array[] = digitArray(num, size);
if (size < 3) {
if (size < 2) {
System.out.print(num);
} else {
System.out.println(array[0] + "" + array[1]);
System.out.println(array[1] + "" + array[0]);
}
} else { // NEED CLARITY FROM HERE
int i = 2;
for (int outer = 0; outer <= size - 1; outer++) {
int fix = array[0];
for (int j = 1; j <= swap / size; j++) {
if (i == size) {
i = 2;
}
int temp = array[i - 1];
array[i - 1] = array[i];
array[i] = temp;
i++;
int uniqueNo = fix;
for (int k = 1; k < size; k++) {
uniqueNo = (uniqueNo * 10) + array[k];
}
System.out.println(j + ": " + uniqueNo);
}
int t = array[0];
if ((outer + 1) > size - 1) {
array[0] = array[outer];
array[outer] = t;
} else {
array[0] = array[outer + 1];
array[outer + 1] = t;
}
}
}
}
public static int fact(int num) {
int factNo = 1;
for (int i =num; i > 0; i--)
{
factNo = factNo * i;
}
return factNo;
}
public static int digitSize(int num) {
//int count = String.valueOf(num).length();
// return count;
int count = 0;
while(num>0)
{
num/=10;
count++;
}
return count;
}
public static int[] digitArray(int num, int size) {
int count[] = new int[size];
int i = size - 1, rem;
while (num > 0) {
rem = num % 10;
count[i] = rem;
num = num / 10;
i--;
}
return count;
}
}
In the code size is the number of digits in your number and swap is the factorial of the number of digits. For example, if you enter a 5 digit number the fact function calculates 5 * 4 * 3 * 2 * 1. array is just a list of the digits you entered, ordered from the least significant digit to the most significant.
So here is the pseudo code for the case where the number of digits is 3 or greater. I've interleaved the code to make it clearer.
i = 2
For each digit in the array of digits indexed by outer
- Set fix to the digit currently stored in the first element of the array
int i = 2;
for (int outer = 0; outer <= size - 1; outer++) {
int fix = array[0];
For each index j from 1 to the factorial of the number of digits divided by number of digits
- If i is equal to the number of digits, set i equal to 2
- Swap digit i-1 with digit i in the digit array
- Increment I
int fix = array[0];
for (int j = 1; j <= swap / size; j++) {
if (i == size) {
i = 2;
}
int temp = array[i - 1];
array[i - 1] = array[i];
array[i] = temp;
i++;
Set uniqueNo to the decimal number that the digit array currently represents, except that fix is the least significant digit
Print the uniqueNo for the current value of j
int uniqueNo = fix;
for (int k = 1; k < size; k++) {
uniqueNo = (uniqueNo * 10) + array[k];
}
System.out.println(j + ": " + uniqueNo);
If the current value of outer is the last element in the digit array
- Swap the first digit with the last digit in the array
Else
- Swap the first digit of the array with the digit at outer+1
int t = array[0];
if ((outer + 1) > size - 1) {
array[0] = array[outer];
array[outer] = t;
} else {
array[0] = array[outer + 1];
array[outer + 1] = t;
}
The code is basically iterating factorial/number of digit times for each digit of the number that was input and rearranging the digits with each iteration in a way that wraps around from the last digit to the first. It's difficult to understand partly because the variable names are uninformative.
The number of permutations of n distinct objects is n! (factorial), so the code is just listing all possible permutations of the digits of the number that was input. If there are only 2 digits, there are only two permutations, and of course 1 digit has only one permutation, so those are special cases. If you iterate through each digit, the maximum number of permutations keeping one digit "fixed" is factorial/number of digits.
Related
I wrote a code in java for school to compute the median of an array.
We have some test cases for this. The first column is the input, the second the expected and the third the actual output. Is anything special on the case that does not work? I've worked so long on this code now and slowly but surely i am getting frustrated. I really don't know where or why my code does not work in this specific scenario. the code is the following:
/**
* This class calculates the median of a list to use it in quicksort for a runtime of O(log(n));
* #author Niklas
*
*/
public class Median {
/**
* The position i.
*/
private static int positionI = -1;
/**
* a help array for the quicksort algorithm.
*/
private static int[] quicksortArray;
/**
* Computes and retrieves the lower median of the given array of numbers using
* the Median algorithm presented in the lecture.
*
* #param input numbers.
* #return the lower median.
* #throw IllegalArgumentException if the array is {#code null} or empty.
*/
public static int lowerMedian(int[] numbers) {
if (numbers.length == 0 || numbers == null) {
throw new IllegalArgumentException("Array must contain values");
}
// avoiding that positionI is part of the recursion
if (positionI == -1) {
positionI = (int) Math.floor((double) ((numbers.length + 1) / 2));
}
// Step 1: dividing the list into groups.
int[] medians = new int[(int) Math.ceil((float) numbers.length / 5)];
int[] subArray = new int[5];
int positionForMedianArray = 0;
// the end case that the array is < 5.
if (numbers.length <= 5) {
sortArray(numbers);
if (positionI <= numbers.length) {
return numbers[positionI - 1];
}
return numbers.length % 2 == 0 ? numbers[(numbers.length / 2) - 1] : numbers[numbers.length / 2];
}
for (int i = 0; i < numbers.length; i += 5) {
if (numbers.length < i + 5) {
subArray = Arrays.copyOfRange(numbers, i, numbers.length);
} else {
subArray = Arrays.copyOfRange(numbers, i, i + 5);
}
// Step 2: calculate the median of each subArray.
sortArray(subArray);
medians[positionForMedianArray] = subArray.length % 2 == 0 ? subArray[subArray.length / 2 - 1]
: subArray[subArray.length / 2];
positionForMedianArray += 1;
}
// Step 3: calculate x recursively
int x = lowerMedian(medians);
// Step 4: partioniate the lists.
// computing how big the arrays have to be because arraylists doesnt work as
// good in this code.
int countS = 0;
int countG = 0;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] < x) {
countS += 1;
} else if (numbers[i] > x) {
countG += 1;
}
}
// creating the arrays with the right size.
int[] smaller = new int[countS];
int[] greater = new int[countG];
countS = 0;
countG = 0;
// filling the Arrays (L1 and L2).
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] < x) {
smaller[countS] = numbers[i];
countS += 1;
} else if (numbers[i] > x) {
greater[countG] = numbers[i];
countG += 1;
}
}
int k = smaller.length + 1;
// for testing
// System.out.println("\nnumbers: " + Arrays.toString(numbers));
// System.out.println("position i: " + positionI);
// System.out.println("SubArray " + (positionForMedianArray) + ": " + Arrays.toString(subArray));
// System.out.println("Median Array im Durchlauf " + (positionForMedianArray) + ": " + Arrays.toString(medians));
// System.out.println("x: " + x);
// System.out.println("L1: " + Arrays.toString(smaller));
// System.out.println("L2: " + Arrays.toString(greater));
// System.out.println("Position k: " + k);
if (positionI < k) {
return lowerMedian(smaller);
} else if (positionI > k) {
positionI -= k;
return lowerMedian(greater);
}
return x;
}
/**
* Sorts the given array in an inefficent way.
*
* #param numbers the array to sort.
*/
private static void sortArray(int[] numbers) {
for (int i = 0; i < numbers.length; i++) {
for (int j = 0; j < numbers.length; j++) {
if (numbers[i] < numbers[j]) {
int tempVar = numbers[j];
numbers[j] = numbers[i];
numbers[i] = tempVar;
}
}
}
}
I would appreciate any kind of help!
I'm not sure why your approach for calculating low median is so complicated. All you need to do is sort the list of number and if the list has odd number of values then just return value at <array length> / 2 and if the list has even number of values then return value at (<array_length> / 2) - 1. Regarding the sorting the input list, you can either implement your own quicksort algorithm or use Arrays.sort. Below is a potential approach to calculate lower median using Java built-in sort method.
public static int lowerMedian(int[] numbers) {
Arrays.sort(numbers, 0, numbers.length);
int length = numbers.length;
if (length == 0) {
return 0;
} else if (length % 2 == 0) {
return numbers[(length / 2) - 1];
} else {
return numbers[length / 2];
}
}
I have an assignment of which a part is to generate n random numbers between 0-99 inclusive in a 1d array, where the user enters n. Now, I have to print out those numbers formatted like this:
What is your number? 22 //user entered
1 2 3 4 5 6 7 8 9 10
----random numbers here---------
11 12 13 14 15 16 17 18 19 20
-----random numbers here--------
21 22
---two random numbers here---
Using those numbers, I have find lots of other things, (like min, max, median, outliers, etc.) and I was able to do so. However, I wasn't able to actually print it out in the format shown above, with no more than 10 numbers in one row.
Edit: Hello, I managed to figure it out, here's how I did it:
int counter = 0;
int count2 = 0;
int count3 = 0;
int add = 0;
int idx = 1;
int idx2 = 0;
if (nums > 10)
{
count3 = 10;
count2 = 10;
}
else
{
count3 = nums;
count2 = nums;
}
if (nums%10 == 0) add = 0;
else add = 1;
for (int i = 0; i < nums/10 + add; i++)
{
for (int j = 0; j < count3; j++)
{
System.out.print(idx + "\t");
idx++;
}
System.out.println();
for (int k = 0; k < count2; k++)
{
System.out.print(numbers[idx2] + "\t");
idx2++;
counter++;
}
System.out.println("\n");
if (nums-counter > 10)
{
count3 = 10;
count2 = 10;
}
else
{
count3 = nums-counter;
count2 = nums-counter;
}
}
Thank you to everyone who helped! Also, please let me know if you find a way to shorten what I have done above.
*above, nums was the number of numbers the user entered
I'd use a for-loop to make an array of arrays: and then formatting the lines using those values:
var arr_random_n = [1,2,3,4,5,6,7,8,9,0,1,2,3,6,4,6,7,4,7,3,1,5,7,9,5,3,2,54,6,8,5,2];
var organized_arr = [];
var idx = 0
for(var i = 0; i < arr.length; i+=10){
organized_arr[idx] = arr.slice(i, i+10); //getting values in groups of 10
idx+=1 //this variable represents the idx of the larger array
}
Now organized_arr has an array of arrays, where each array in index i contains the values to be printed in line i.
There's probably more concise ways of doing this. but this is very intuitive.
Let me know of any improvements.
Something like this might be what you're looking for.
private static void printLine(String msg)
{
System.out.println("\r\n== " + msg + " ==\r\n");
}
private static void printLine(int numDisplayed)
{
printLine(numDisplayed + " above");
}
public static void test(int total)
{
int[] arr = new int[total];
// Fill our array with random values
for (int i = 0; i < total; i++)
arr[i] = (int)(Math.random() * 100);
for (int i = 0; i < total; i++)
{
System.out.print(arr[i] + " ");
// Check if 10th value on the line, if so, display line break
// ** UNLESS it's also the last value - in that case, don't bother, special handling for that
if (i % 10 == 9 && i != total - 1)
printLine("Random Numbers");
}
// Display number of displayed elements above the last line
if (total < 10 || total % 10 != 0)
printLine(total % 10);
else
printLine(10);
}
To print 10 indexes on a line then those elements of an array, use two String variables to build the lines, then print them in two nested loops:
for (int i = 0; i < array.length; i += 10) {
String indexes = "", elements = "";
for (int j = 0; j < 10 && i * 10 + j < array.length; j++) {
int index = i * 10 + j;
indexes += (index + 1) + " "; // one-based as per example in question
elements += array[index] + " ";
}
System.out.println(indexes);
System.out.println(elements);
}
I'm trying to write a program using Java, that (outputs) the following pattern depending on an input (integer) (n = 5):
0********1
23******45
678****901
2345678901
As you noticed:
input(3) represent 3 rows
single row digits (n * 2)
Digits should start from 0 to 9 and then repeat until the pattern is fully done
First row should have only 2 numbers (start 0 end 1)
(*) will be in between
Next row should have 4 numbers (start 23 end 45) and so on
How can this program written?
Here is my code:
import java.util.Scanner;
public class b_test_2 {
public static void main (String arug[]) {
String star = "*";
int star_count, digit = 0;
Scanner sc = new Scanner(System.in);
System.out.print("Please type a number (int)");
int n = sc.nextInt();
while (n != 0){
star_count = n * 2 - 2;
for (int i=0; i<n; i++) {
System.out.print(star);
i = i + 1;
}
String stars = star;
n = n - 1;
for (int i2=0; i2<n; i2++) {
System.out.print(star);
i2 = i2 + 1;
int x = 0;
x = digit;
x = x + 1;
if (x == 10){
x = 0;
System.out.print(digit + stars + digit);
}
}
}
}
}
There are any parts missing in your code, but you also seem to make it more complicated than it is.
To illustrate, and hopefully help you to go in the right direction, here is compact code to do it. Do not hand in this code unless you fully understand how it works.
static void printPattern(int n) {
for (int row = 1, digit = 0; row <= n; row++) {
for (int i = 0; i < row; i++, digit = (digit + 1) % 10)
System.out.print(digit);
for (int i = (n - row) * 2; i > 0; i--)
System.out.print('*');
for (int i = 0; i < row; i++, digit = (digit + 1) % 10)
System.out.print(digit);
System.out.println();
}
}
Test
printPattern(4);
Output
0******1
23****45
678**901
23456789
I case you haven't learned it yet, the % operator calculates the remainder after division.
What did I do wrong? I'm really not sure what else to try or where my mistake is. Thanks for any help. It's supposed to calculate the sum of integers between two numbers, e.g. between 3 and 6 it would be 3 + 4 + 5 + 6
import java.util.Scanner;
public class TheSumBetweenTwoNumbers {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.println("First:");
int n = Integer.parseInt(reader.nextLine());
System.out.println("Second:");
int max = Integer.parseInt(reader.nextLine());
int sum = 0;
int i = 0;
int difference = max - n;
while (i < difference) {
sum = n + (n + 1);
n++;
i++;
}
System.out.println("Sum is " + sum);
}
}
Why all this you need just a piece of code like this :
public static void main(String args[]) {
int min = 3, max = 6, sum = 0;
for (int i = min; i <= max; i++) {
sum += i;
}
System.out.println(sum);
}
With while loop it should be :
...
int i = min;
while (i <= max) {
sum += i;
i++;
}
...
You don't need to find a difference and loop over it, just running a loop from n to max will do. Also, you need to add the value to sum (+=) instead of assigning a value to it (=, which overwrites previous value)
Try this:
int i = n;
while (i <= max) {
sum += i;
i++;
}
You're overwriting the previous sum value with the most recent n + (n + 1), instead of accumulating the previous sum. Also, your loop is one iteration short. Try this:
int sum = 0;
for (int i = n; i <= max; i++) {
sum += i;
}
System.out.println("Sum is " + sum);
Change this snippet
int sum = 0;
int i = 0;
int difference = max - n;
while (i < difference) {
sum = n + (n + 1);
n++;
i++;
}
In
int sum = 0;
int i = n;
while (i <= max) {
sum = sum + i;
i++;
}
You made it a little bit overcomplicated. All you really need is a for loop that runs from n to max that adds up the incrementing variables:
int sum = 0;
for(int i = n; i <= max; i++){
sum += i;
}
The problem im getting is that with oddSum the value outputted is the same as evenSum, and the value for sum of all elements is 0.
I cant quite see where im going wrong as the loops are pretty similar and if the even one works the others should too?
Here is my code anyway:
int evenData[] = new int [10];
int oddData[] = new int [10];
int sum = 0;
int evenSum = 0;
int oddSum = 0;
int[] data = {3, 2, 5, 7, 9, 12, 97, 24, 54};
for(int index = 0; index < data.length; index++)
{
if (data[index] % 2 == 0)
{
int temp = data[index];
data[index] = evenData[index];
evenData[index] = temp;
}
else
{
int temp = data[index];
data[index] = oddData[index];
oddData[index] = temp;
}
}
for(int evenIndex = 0; evenIndex < evenData.length; evenIndex++)
{
evenSum =evenData[evenIndex] + evenSum;
}
System.out.print("Sum of even elements: " + evenSum);
for(int oddIndex = 0; oddIndex < oddData.length; oddIndex++)
{
oddSum = oddData[oddIndex] + oddSum;
}
System.out.print("Sum of odd elements: " + oddSum);
for(int index = 0; index < data.length; index++)
{
sum = data[index] + sum;
}
System.out.print("Sum of all elements: " + sum);
You are getting same value for even and odd because you are printing the same value: -
System.out.print("Sum of odd elements: " + evenSum);
Also, your final sum is zero because you are making out all the elements of your original array as zero, as you are swapping your elements with the elements in evenData and oddData, which are zero initially.
int temp = data[index];
data[index] = evenData[index]; // This code assigns a value 0 to current index.
evenData[index] = temp;
So, you are iterating your array, and assigning 0 to each of your index, while adding the previous element to the new array.
I would say that you are needlessly using 2 extra array and 3 extra loops. Why not just create a sum in the place where you are iterating your original array?
In fact, all your sums can be computed in a single loop: -
for(int index = 0; index < data.length; index++)
{
sum += data[index];
if (data[index] % 2 == 0)
{
// int temp = data[index];
// data[index] = evenData[index];
// evenData[index] = temp;
evenSum += data[index];
}
else
{
// int temp = data[index];
// data[index] = oddData[index];
// oddData[index] = temp;
oddSum += data[index];
}
}
System.out.println("Even Sum: " + evenSum);
System.out.println("Odd Sum: " + oddSum);
System.out.println("Total Sum: " + sum);
So, you don't need to create extra arrays for even and odd numbers.
And, also your 4 loops have now been condensed to just a single loop.
int temp = data[index];
data[index] = evenData[index];
evenData[index] = temp;
Looking at your above lines, evenDate is empty and in second line you are setting your data array to be empty. You are repeating the same mistake in oddDate line as well.
Why don't you use just try the following?
for(int index = 0; index < data.length; index++)
{
if (data[index] % 2 == 0) {
int temp = data[index];
evenData[index] = temp;
} else {
int temp = data[index];
oddData[index] = temp; }
}
}
for(int evenIndex = 0; evenIndex < evenData.length; evenIndex++)
{
//since length of all 3 data,even, odd arrays are the same
//you can put both sum operation in one for loop
evenSum = evenData[evenIndex] + evenSum;
oddSum = oddData[evenIndex] + oddSum;
sum = data[evenIndex] + sum;
}
System.out.print("Sum of even elements: " + evenSum);
//you have put evenSum for below odeUm printing in ur code
System.out.print("Sum of odd elements: " + oddSum);
System.out.print("Sum of all elements: " + sum);