Increasing skips in Josephus - java

Here is one solution to the Josephus problem (where people are arranged in a circle and every other person is killed until only one remains):
import java.util.ArrayList;
public class test {
public static void main(String[] args) {
ArrayList<Integer> chairArr = new ArrayList<Integer>();
for (int i = 1; i <= 10; i++) {
chairArr.add(i);
}
int result = 0;
for (int i = 1; i < chairArr.size() - 1; i = i + 2) {
chairArr.add(chairArr.get(i));
result = i;
}
System.out.print("Result: " + chairArr.get(result));
}
}
But what if, instead of skipping every other person, we increased the number skipped as we went through? That is, if 10 people were arranged in the circle, persons 1, 3, 6, 10, etc. were killed in that order. I think the modification would come in the i = i + 2 in the for loop, but I'm not sure.
I worked it out on paper, and this is the order of elimination, where asterisks denote the number to be removed:
0 *1* 2 3 4 5 6 7 8 9 10
1 2 *3* 4 5 6 7 8 9 10
2 2 4 5 *6* 7 8 9 10
3 2 4 5 7 8 9 *10*
4 2 4 5 7 *8* 9
5 2 4 5 7 *9*
6 2 4 *5* 7
7 *2* 4 7
8 *4* 7
9 7 <-- Result
Thoughts?
Edit: Tried this modification of the for loop:
for (int j = 2; j < chairArr.size() - 1; j++) {
for (int i = 1; i < chairArr.size() - 1; i = i + j) {
chairArr.add(chairArr.get(i));
result = i;
}
}
This won't work because after the initial pass where j = 2, the inner loop will already have narrowed the list down to one candidate so the outer loop never completes.

Related

dividing matrix into four sub-blocks

i want devide matrix into four sub-blocks equally by vertically and horizontallty in java (Here, we suppose that m and nare even numbers) .
for example we have matrix:
1 2 3 4 5 6
7 8 9 1 2 8
1 2 3 4 5 6
4 5 6 7 8 9
1 4 7 2 5 8
3 6 9 7 2 5
I want to display the last block that is:
7 8 9
2 5 8
7 2 5
how i can resolve this problem in java.
Iterate over the lower-right part of the matrix. Here is an example for a square matrix. I am sure you will be able to make it more generic for non-square quadrants or to get other quadrants than the lower-right one.
public int[][] getQuadrantOfSquareMatrix(int[][] matrix) {
int newDimension = matrix.length / 2;
int[][] toReturn = new int[newDimension][newDimension];
for (int i = 0; i < newDimension; i++) {
for (int j = 0; j < newDimension; j++) {
toReturn[i][j] = matrix[i + newDimension][j + newDimension];
}
}
return toReturn;
}

Why is my insertion sort failing this test case?

I'm trying to write an insertion sort, and I pass several test cases, but I fail one. My code is:
static void insertionSort1(int n, int[] arr) {
int copy = arr[n-1];
int i = n - 1;
while (copy < arr[i-1]){
arr[i] = arr[i-1];
for(int k = 0; k < arr.length; k++){
System.out.print(arr[k] + " ");
}
System.out.println();
i--;
}
arr[i] = copy;
for(int m = 0; m < arr.length; m++){
System.out.print(arr[m] + " ");
}
}
where n is the size of the array, and arr is the array. My algo fails this test case in particular:
10
2 3 4 5 6 7 8 9 10 1
I get index out of bounds on that but not on
5
2 4 6 8 3
or others. what's going on?
That is an index out of bound exception of the array because of minus value of the arr. It is not an algorithm issue but a language.
while (i > 0 && copy < arr[i - 1])
Source:
public class InsertionSort {
static void insertionSort1(int n, int[] arr) {
int copy = arr[n - 1];
int i = n - 1;
while (i > 0 && copy < arr[i - 1]) {
arr[i] = arr[i - 1];
for (int k = 0; k < arr.length; k++) {
System.out.print(arr[k] + " ");
}
System.out.println();
i--;
}
arr[i] = copy;
System.out.println("#### RESULT ####");
for (int m = 0; m < arr.length; m++) {
System.out.print(arr[m] + " ");
}
System.out.println("\n#### END ####\n");
}
public static void main(String[] args)
{
//10
//2 3 4 5 6 7 8 9 10 1
int[] arr ={2, 3, 4, 5, 6, 7, 8, 9, 10, 1};
int n = arr.length;
insertionSort1(n, arr);
//5
//2 4 6 8 3
arr= new int[5];
n = arr.length;
arr[0] = 2;
arr[1] = 4;
arr[2] = 6;
arr[3] = 8;
arr[4] = 3;
insertionSort1(n, arr);
}
}
Result:
2 3 4 5 6 7 8 9 10 10
2 3 4 5 6 7 8 9 9 10
2 3 4 5 6 7 8 8 9 10
2 3 4 5 6 7 7 8 9 10
2 3 4 5 6 6 7 8 9 10
2 3 4 5 5 6 7 8 9 10
2 3 4 4 5 6 7 8 9 10
2 3 3 4 5 6 7 8 9 10
2 2 3 4 5 6 7 8 9 10
#### RESULT ####
1 2 3 4 5 6 7 8 9 10
#### END ####
2 4 6 8 8
2 4 6 6 8
2 4 4 6 8
#### RESULT ####
2 3 4 6 8
#### END ####
Have a good day.
First, you should review what an insertion sort is. You should be building a sorted list on one end of the array, expanding it one element at a time by "inserting" the next value in the correct place. It should be much like sorting a hand of cards if you are given them one at a time. You will need a nested loop to do it correctly.
Carefully consider what your program is really doing and see why it fails -- a shorter test case that fails in the same way would be [3, 2, 1]. Or [2, 1], for that matter.

Sorting even and odd numbers inside an array

I'm trying to split the array into odd and even numbers. Note that sorting numbers in the final result does not matter. I'm compiling the code and the output contains some bug. My code arranges odd numbers correctly while the even numbers are giving me some trouble. Could somebody please help me out with the arrangement of even numbers?
Basically, I arrange odd numbers in the left side of the array and have oddPos = 0 in the beginning; even numbers are in the right side and the positioning starts from the very end of the array evenPos = myArray.length - 1.
public class EvenOddArray {
public static void main(String[] args){
int[] myArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int oddPos = 0;
int evenPos = myArray.length - 1;
for(int i = 0; i < myArray.length; i++){
if(myArray[i] % 2 == 0){
myArray[evenPos] = myArray[i];
evenPos--;
}
else{
myArray[oddPos] = myArray[i];
oddPos++;
}
}
for(int i = 0; i < myArray.length; i++){
System.out.print(myArray[i] + " ");
}
}
}
Output:
1 3 5 7 2 4 6 6 4 2
int current = 0;
int evenPos = myArray.Length - 1;
while (current < evenPos) {
if (myArray[current] % 2 == 0) {
swap(myArray, evenPos, current);
evenPos--;
} else {
current++;
}
}
A squeezed funny version:
for (int curPos=0, evenPos=myArray.length-1; curPos < evenPos;)
if (myArray[curPos] % 2 == 0)
swap(myArray, evenPos--, curPos);
else
curPos++;
More fun version:
for (int curPos=0, evenPos=myArray.length-1; curPos < evenPos;)
swap(myArray, curPos, myArray[curPos]%2==0 ? evenPos-- : curPos++);
explanation:
You don't have to swap values when the number is odd. you only
increase the current counter.
you can't use the for loop counter as an index to the array too. to
not miss the numbers that gets swapped to the counter index not
processed. this is the mistake that other answers didn't cover.
Actually you are editing the same myArray array while reading from it. So what happens is,
You insert 6 into the myArray[7] th position, in the 6th iteration of the loop. So, during the 7th iteration when you read the myArray[7], it is 6. Not 8. Because, you have over written 8 with 6 in the previous iteration.
Therefore, use a separate array to hold the results. Hope you get the point.
You can do something like this,
int[] myArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] resultArray = new int[myArray.length];
int oddPos = 0;
int evenPos = myArray.length - 1;
for(int i = 0; i < myArray.length; i++){
if(myArray[i] % 2 == 0){
resultArray[evenPos] = myArray[i];
evenPos--;
}
else{
resultArray[oddPos] = myArray[i];
oddPos++;
}
}
Lets see what happens with each Iteration of your for loop.
Original: 1 2 3 4 5 6 7 8 9 10
1st Iter: 1 2 3 4 5 6 7 8 9 10
2nd Iter: 1 2 3 4 5 6 7 8 9 2
3rd Iter: 1 3 3 4 5 6 7 8 9 2
4th Iter: 1 3 3 4 5 6 7 8 4 2
5th Iter: 1 3 5 4 5 6 7 8 4 2
6th Iter: 1 3 5 4 5 6 7 6 4 2
7th Iter: 1 3 5 7 5 6 7 6 4 2
8th Iter: 1 3 5 7 5 6 6 6 4 2
9th Iter: 1 3 5 7 5 4 6 6 4 2
10th Iter: 1 3 5 7 2 4 6 6 4 2
As you can see, you are modifying the array "inplace". You are modifying the array without using all the values. For example, look at 9, It gets over written before it is ever accessed. So, your algo is wrong.
Suggestions:
Use a new array to hold the results as in tibzon's answer
Use swapping instead of overwriting. You have to update your algo accordingly. I was going to provide one. But Murenik already provided one.
Here is my optimized version, which uses around half of the swaps compared to the #hasan83 version.
int n = myArray.length;
int oddPos = 0;
int evenPos = n - 1;
while (true) {
while (oddPos < n && myArray[oddPos] % 2 == 1) {
oddPos++;
}
while (evenPos >= 0 && myArray[evenPos] % 2 == 0) {
evenPos--;
}
if (oddPos >= evenPos) break;
swap(myArray, oddPos, evenPos);
}

Nested Loops - A Third One?

Write a program that prints the following on the Screen:
1 2 3 4 5 6 7 8 9 10
2 3 4 5 6 7 8 9 10
3 4 5 6 7 8 9 10
4 5 6 7 8 9 10
5 6 7 8 9 10
6 7 8 9 10
7 8 9 10
8 9 10
I'm having a little trouble correcting the nested loops - I have it to look like that, the numbers won't stop at 10 though. The code prints this:
1 2 3 4 5 6 7 8 9 10
2 3 4 5 6 7 8 9 10 11
3 4 5 6 7 8 9 10 11 12
4 5 6 7 8 9 10 11 12 13
5 6 7 8 9 10 11 12 13 14
6 7 8 9 10 11 12 13 14 15
7 8 9 10 11 12 13 14 15 16
8 9 10 11 12 13 14 15 16 17
I'm a beginner programmer and need help with this - do you need a third loop inside of the nested loop already? Any help is appreciated! Here is my code so far:
import java.util.Scanner;
public class LoopProgram
{
public static void main(String args [])
{
for (int e=0; e<8; e++)
{
for (int f=1; f<=10; f++)
{
System.out.print(f + e + " ");
}
System.out.println();
}
}
}
Two loops are enough.
The outer loop runs eight times, you've got that working already.
Your inner loop, however, always runs ten times, which is not what you want. You want the inner loop to run 10 times first, then only 9 times, then only 8 times etc. The trick here is to change the start or end value of that inner loop, like this:
for (int e=0;e<8;e++) {
for (int f=e+1; f<=10; f++) {
...
}
}
I think this is what you are looking for.
for(int e=1;e<9;e++) {
for(int f=e;f<=10;f++) {
System.out.print(f+" ");
}
System.out.println();
}
This ouputs exactly what you asked.
Try this for the second loop:
for(int f=e;f<=10;f++)
and for output
System.out.print(f+" ");
Here's how I would do it
for (int i = 1; i <= 8; i++) {
for (int j = i; j <= 10; j++)
System.out.print(j + " ");
System.out.println();
}
Three loops is severe overkill. This can be done with a single loop and two counters.
public class LoopProgram {
static final int LIMIT_1 = 8;
static final int LIMIT_2 = 10;
public static void main(String[] args) {
int a = 1, b = 2;
while(b <= (LIMIT_1 + 1)) {
System.out.print(a);
if(a < LIMIT_2) {
System.out.print(" ");
a++;
} else {
System.out.println();
a = b;
b++;
}
}
}
}
You only need two loops:
The outer one will run eight times and the inner one will begin at the value of the outer counter (thats what makes each line count up to ten but always start at the first value of last line + 1) and run while it's counter is less than 10.
Something like that:
for (int i = 0; i < 8; i++) {
for (int e = i; e < 10; e++) {
//print e + 1
}
}
You have to print e + 1 so that your lines do not begin at 0, but at one, going up to 10.
This is more of an explanation of how to work this sort of thing out for yourself. In the commonest cases of a for-loop, you should ask yourself three questions about the index variable:
What is the first value I want it to have?
Under what conditions do I want to do another iteration?
How should it change from iteration to iteration?
For your inner loop, the answers are:
e
f <= 10
f++
From that, it is easy to construct the loop, and you already have several examples of it written for you.

How to find element number from either a single, or a range of values in an array

This is the code for an upcoming university practical I have:
import java.util.Random;
public class Practical4_Assessed
{
public static void main(String[] args)
{
Random numberGenerator = new Random ();
int[] arrayOfGenerator = new int[100];
int[] countOfArray = new int[10];
int count;
for (int countOfGenerator = 0; countOfGenerator < 100; countOfGenerator++)
{
count = numberGenerator.nextInt(10);
countOfArray[count]++;
arrayOfGenerator[countOfGenerator] = count + 1;
}
int countOfNumbersOnLine = 0;
for (int countOfOutput = 0; countOfOutput < 100; countOfOutput++)
{
if (countOfNumbersOnLine == 10)
{
System.out.println("");
countOfNumbersOnLine = 0;
countOfOutput--;
}
else
{
if (arrayOfGenerator[countOfOutput] == 10)
{
System.out.print(arrayOfGenerator[countOfOutput] + " ");
countOfNumbersOnLine++;
}
else
{
System.out.print(arrayOfGenerator[countOfOutput] + " ");
countOfNumbersOnLine++;
}
}
}
System.out.println("");
System.out.println("");
String occurrencesReport = "";
String graph = "";
for (int countOfNumbers = 0; countOfNumbers < countOfArray.length; countOfNumbers++)
{
occurrencesReport += "The number " + (countOfNumbers + 1) +
" occurs " + countOfArray[countOfNumbers] + " times.";
if (countOfNumbers != 9)
graph += (countOfNumbers + 1) + " ";
else
graph += (countOfNumbers + 1) + " ";
for (int a = 0; a < countOfArray[countOfNumbers]; a++)
{
graph += "*";
}
occurrencesReport += "\n";
graph += "\n";
}
System.out.println(occurrencesReport);
System.out.println(graph);
int max = 0;
int test = 0;
for (int counter = 0; counter < countOfArray.length; counter++)
{
if (countOfArray[counter] >= max)
{
max = countOfArray[counter];
test = counter + 1;
}
}
System.out.println("The number that appears the most is " + test + ".");
}
}
The program creates an array that will store 100 integers (all of which are between 1 and 10), which are generated by a random number generator, and then print out ten numbers of this array per line. It then scans these integers, counts up how often each number appears and store the results in a second array.
Following this, it outputs a horizontal bar chart of asterisks showing how often each number appears before finally outputting the number that appears the most often.
I thought I had the code totally and completely done, but I've just realised that if multiple numbers occur the same amount of times, the last part of my code can't handle this, e.g. if the numbers 3 and 5 both appears 12 times, the code can only produce one of them.
Does anyone have a way around this?
Thanks,
Andrew
There are a couple of ways to address this, which range from quick to complex. The easiest way is to brute force it like such:
int max = 0;
//int test = 0;
for (int counter = 0; counter < countOfArray.length; counter++)
{
if (countOfArray[counter] >= max)
{
max = countOfArray[counter];
//test = counter + 1;
}
}
System.out.print("The number that appears the most is");
boolean first = true;
for(int i = 0; i < countOfArray.length; i++)
{
if(countOfArray[i] == max)
{
if(first)
first = false;
else
System.out.print(",");
System.out.print(" " + (i+1) );
}
}
System.out.println(".");
Here's the output:
6 2 6 5 6 8 9 3 5 8
9 8 10 10 4 5 8 9 8 5
1 7 8 5 6 7 10 4 5 4
2 7 9 2 3 3 1 2 10 3
5 2 10 1 1 6 3 3 8 10
2 6 10 2 5 1 4 10 8 7
7 8 7 3 7 8 3 4 5 5
7 8 9 8 6 6 8 1 10 3
2 5 4 6 9 9 10 10 1 10
9 4 10 9 7 3 4 3 2 4
The number 1 occurs 7 times.
The number 2 occurs 9 times.
The number 3 occurs 11 times.
The number 4 occurs 9 times.
The number 5 occurs 11 times.
The number 6 occurs 9 times.
The number 7 occurs 9 times.
The number 8 occurs 13 times.
The number 9 occurs 9 times.
The number 10 occurs 13 times.
1 *******
2 *********
3 ***********
4 *********
5 ***********
6 *********
7 *********
8 *************
9 *********
10 *************
The number that appears the most is 8, 10.
There are much cleaner ways to go about it, but hopefully that gives you a decent start!
I am assuming this is not some kinda homework, so i am providing you another approach than this.
- Use Collection like ArrayList instead of Array.
- Use method like Collections.frequency(Object o) to know the number of time the value got occurred in that Collection.
Instead of just doing
System.out.println("The number that appears the most is " + test + ".");
Again loop through countOfArray, do the print for each element that has the same value as max.

Categories

Resources