Jump Encrypt: prompt the user to enter an integer (jump value) that is between 2 and the square root of the length of the current message, inclusive. Now imagine that we are going to write the current message in a table form, using the same number of rows as the jump value. The character order in the original message would be the order of the
first column, followed by the second column, etc. For example, with jump value of 5, the original message would be in table form:
T i e g a
h s i m g
i o n e e
s t r a s .
h i l s
To complete the encryption, display the encrypted message row by row, "Tieg ahs imgi oneestras. hils" for the above. Hint: this can be accomplished in one step with nested loops! No arrays or actual tables are required in the solution,
So I have attached the code that I have used down below, but it seems to be that I am off by one column when it comes to printing the message.
public static String jumpEncrypt(String message, int jumpValue) {
String jencrypt = "";
for (int i = 0; i < jumpValue; i++) {
for (int j = 0; j < (jumpValue); j++) {
jencrypt += message.charAt(i + j*jumpValue);
}
}
return jencrypt;
}
The expected output for the original message with a jumpValue of 5 should be "Tieg ahs imgi oneestras. hils" but I am getting an output of "Tieg hs imi onestras hils"
You are iterating both i and j up to the jumpValue. That means that the maximum message you can encrypt is jumpValue * jumpValue) - or 25 in your case - characters, and your string is already longer (you can see that your "correct" matrix is 6x5).
So you need to iterator j not up to jumpValue, but up to the message length divided by jumpValue - and you need to round it up to the nearest whole number.
That also means that some of the characters in the last column of your matrix come from a position longer than the length of the input string, so you need to check for that.
The below code tackles both:
public static String jumpEncrypt(String message, int jumpValue) {
String jencrypt = "";
for (int i = 0; i < jumpValue; i++) {
for (int j = 0; j < (message.length() + jumpValue - 1) / jumpValue; j++) {
int index = i + j * jumpValue;
if (index < message.length()) {
jencrypt += message.charAt(index);
}
}
}
return jencrypt;
}
Note that the expression (message.length() + jumpValue - 1) / jumpValue (which is message.length() / jumpValue, but rounded up) is constant throughout both loops, so for efficiency, it's better to extract it into a local variable before the loops, to avoid an unnecessary evaluation of the expression for every loop.
So with this for loop code their is not much to go on but a simple fix might be
maybe j should be equal to one so message.charAt(i + j*jumpValue); it should not equal to
0 + 0*jumpValue) since that makes everything 0 and clears everything out to the basic.
so jencrypt = 0; no matter what its initial value was.
so maybe jumpValue - 1 for int i = 0;
Trying doing the math portion of the floor loop and see why its not adding up correctly.
for (int i = 0; i < jumpValue - 1; i++) {
for (int j = 0; j < (jumpValue); j++) {
jencrypt += message.charAt(i + j*jumpValue);
}
}
return jencrypt;
I am not completely sure if I am right but I did my best to understand I am pretty new still to coding! :)
If I use for (int j = 0; j <= (jumpValue); j++), and make no other changes, it works for me.
Related
I'm attempting to solve some Java questions and I came across a question that asked me to print out a diamond of size n.
Since I got stumped on this question, I decided to look up other's solutions to get an idea as to how I could tackle this problem.
A diamond of size 2 should look like this by the way.
##*##
#***#
##*##
However, one part of the code really stumped me out and that is how does the # get printed out in that manner.
Here is what I found for the top left bit of the diamond, basically this bit:
##
#
Here is the code for that:
public static void printDiamond(int k){
for(int i=1; i <= k; i++) {
for(int j = i; j <= k; j++) {
System.out.print("#");
}
System.out.println("");
}
}
and the output when k = 5:
#####
####
###
##
#
From my understanding, int j is looping upwards since it's declared as i which also loops upwards until it reaches k.
Shouldn't that print out 1,2,3,4,5 diamonds instead since the loop goes from 0 to k, which is 5?
I was expecting the output to be like:
#
##
###
####
#####
Can someone explain how does the code snippet I attached returns the output from top to bottom?
A simple pen and paper exercise will uncover the details.
for(int i = 1; i <= k; i++) {
for(int j = i; j <= k; j++) {
...
}
}
When i = 1, j runs from 1 to k. So, it will print the star k times. That is how you get k stars in row 1.
When i = 2, j runs from 2 to k. So, it will print the star k - 1 times. That is how you get k - 1 stars in row 2.
And so on...
When i = k, j runs from k to k which is one time and hence you get only one star in the last row.
Initial value of j is set to incrementing i and the inner loop is limited with the fixed value k. That is, the first run prints # from 1 to 5 (5 times), the second run prints from 2 to 5, etc. and the number of prints is decreasing.
To print the lower part in increasing way, the limit should be set to i: for (int j = 1; j <= i; j++0) System.out.print("#").
Also, the inner loops may be replaced with the method String::repeat available since Java 11:
public static void diamond(int k) {
// upper part, decreasing # increasing *
for (int i = 1; i <= k; i++) {
System.out.println("#".repeat(k - i) + "*".repeat(2 * i - 1) + "#".repeat(k - i));
}
// lower part, decreasing * increasing #
for (int i = 1; i < k; i++) {
System.out.println("#".repeat(i) + "*".repeat(2 * (k - i) - 1) + "#".repeat(i));
}
}
What is printed as a result of executing the code segment that follows?
(I would normally just use the java program on my computer to do this. But, the program is updating, which will take another few hours.) Anyways, here is the code segment:
ArrayList<String> digits = new ArrayList<String>();
for (int k = 0; k <= 9; k++)
{
digits.add("" + k);
}
for (int k = 0; k <= 4; k++)
{
String d1 = digits.remove(k);
String d2 = digits.remove(k);
digits.add(k, d1 + "+" + d2);
}
System.out.println(digits);
I also want to know why the answer occurs going through this code by hand. I know I got an answer that was completely wrong, so I would also like to know why the answer that you guys get is the correct answer.
The output is
[0+1, 2+3, 4+5, 6+7, 8+9]
The numbers ranging from 0 to 9 are added to the array list by the first for-loop.
for (int k = 0; k <= 9; k++) { digits.add("" + k);}
Five times 2 numbers are removed, e.g. in the first iteration the numbers 0 and 1 are removed. Keep in mind that remove shifts subsequent elements to the left.
At the same iteration a string containing the two digits is inserted into the ArrayList at position k.
for (int k = 0; k <= 4; k++){
String d1 = digits.remove(k);
String d2 = digits.remove(k);
digits.add(k, d1 + "+" + d2);
}
Output should be something like this: [0+1, 2+3, 4+5, 6+7, 8+9]. Didn't compile though.
You can use this site to compile your code and run it.
https://www.compilejava.net/
It produces this:
[0+1, 2+3, 4+5, 6+7, 8+9]
I was wondering if I could write this very thing but with one single loop, instead of two?
for (int row = 0; row < matrix.length; row++) {
for (int col = 0; col < matrix[0].length; col++) {
if ((row + col) % 2 == 0) {
System.out.print(matrix[row][col] + ", ");
sum += matrix[row][col];
}
}
System.out.println("with a sum of " + sum);
}
Actually just ignore the body of the loop.. It's totally irrelevant, I have no idea whatsoever why I included it.. How to somehow combine the two for loops is my question.
Just keep it simple, if possible. Thank you!
You can, though it's inefficient:
for(int i = 0 ; i < matrix.length * matrix[0].length ; i++)
sum += matrix[i % matrix.length][i / matrix.length];
The basic idea would be to map each index to a value in a 2d-number space, using the fact that we know the length of each "row" of the array (matrix.length). We can compose a single index, that uniquely identifies two indices matrix[x][y], by z = x + y * matrix.length. The reverse of this would then be:
x = z % matrix.length
y = z / matrix.length
This depiction would be complete, e.g. each z in [0 , matrix.length * matrix[0].length) would identify exactly one pair of indices, thus we can use it here.
Paul's answer is initially how I thought to do it. But there is the slight restriction that you need to have a rectangular two-dimensional array (i.e. the sub-arrays are all the same length). If you're modelling a "matrix", this is likely to be the case, but more generally you may want to sum up non-rectangular arrays.
A way around this is to do something like this:
for (int r = 0, c = 0; r < matrix.length;) {
if (c < matrix[r].length) {
sum += matrix[r][c];
++c;
} else {
c = 0;
++r;
}
}
Although it's getting a bit messy. I'd just go for a nested loop instead.
I had a lot of trouble trying to find a solution to this answer because it's hard to search specifically about it. I will try my best to explain it well though.
Currently I have the following code:
for(int x = 0; x < 10000; x++){
for(int z = 0; z < 10000; z++){
if(!exists(x + ";" + z)){
return x + ";" + z;
}
}
}
This is pretty much what I want to do except the way the numbers will "generate" is like so:
0;0
0;1
0;2
0;3
...
0;9999
1;0
1;1
I would like the numbers to generate in the following way "or similar" while still ensuring that every combination exists.
0;0
1;0
1;1
0;1
I created an image to show how the numbers should generate. It can go from bottom to left or left to bottom. (See image)
Thanks!
int len = 3;
for (int i = 0; i < len; i++) {
for (int j = 0; j <= i; j++) //println(i+";"+j);
for (int k = i-1; k >= 0; k--) //println(k+";"+i);
}
In the code above len serves the purpose of defining the length of a square (len is 3 above which represents a 3 x 3). In your own code you picked 10000 but that is too large for printing values
What you want is easiest to do with two internal loops, one that handles vertical and the other horizontal. Other than that just arbitrarily pick which one handles the corner of each i iteration. In the code above the j loop handles the corner case
The algorithm you seem to be looking for is:
for(int distanceFromCorner = 0; distanceFromCorner < 10000; distanceFromCorner++) {
for(int otherAxis = 0; otherAxis <= distanceFromCorner; otherAxis++) {
if(!exists(distanceFromCorner + ";" + otherAxis))
return distanceFromCorner + ";" + otherAxis;
if(!exists(otherAxis + ";" + distanceFromCorner))
return otherAxis + ";" + distanceFromCorner;
}
}
Note that this (like your original algorithm) will be much slower than necessary if you want to generate a large number of IDs. (Optimizing this is a separate question)
I'm writing a program for a class at school, and when the independents couldn't help, I turn to you...
I encounter my issue when I attempt to find the average - the variables either don't add correctly or they don't divide correctly. For example, an input of [4], [2], [4], [2], will give me 7.0, when it should be 3.0. Similarly, [2], [2], [4], [4], will give 2.0.
As far as I'm aware, the rest of the code functions exactly as it should. I'm including only what should effect it, but I can post the rest if required.
public class ArrayFunctions
{
String elementNumber =
JOptionPane.showInputDialog("How many elements do you want?");
int number = Integer.parseInt(elementNumber);
//assigns how many elements are in the array, based on user input
int[] min_array = new int[number];
int recalculate = 0;
public void arrayValues()
{
for (int i = 1; i < (number + 1); i++)
{
String elementInfo =
JOptionPane.showInputDialog("Input value for element " + i);
int element = Integer.parseInt(elementInfo);
//assigns values for elements, based on user input
min_array[(i - 1)] = element;
}
System.out.println('\u000C'); /*using BlueJ, this clears the console*/
for (int i = 1; i < (number + 1); i++)
{
System.out.println(min_array[(i - 1)]);
}
//prints the values of the elements in the array
}
...
public double avg()
{
for (int i = 1; i < (min_array.length); i++)
{
recalculate = (recalculate + min_array[(i - 1)]);
}
//should add together the values of all the elements
//this may be where it stops working as intended
double array_avg = (recalculate / min_array.length);
return array_avg;
//should divide the sum of all the elements by how many elements there are
//this is the other place where it might stop working.
}
Again, I can post more code if required. Sorry about bad/lacking comments and poor structure at times, I need to get this written, because I've a due date for this. :/
for (int i = 1; i < (min_array.length); i++)
{
recalculate = (recalculate + min_array[(i - 1)]);
}
This loop is going between index 0 (1 - 1) and index min_array.length - 2 due to your boolean condition in the for loop, stating that it should go while i is LESS than the array's length, and then also subtracting it by 1 in the code.
A possible solution would be to simply go until it's less than OR equal to the size, or simply start your loop at 0 and stop the (i - 1) stuff in the average calculation.
for (int i = 0; i < min_array.length; i++)
{
recalculate += min_array[i];
}
Also, on a side note, you're basically making that same mistake in the GUI stuff as well above; I've corrected it (as well as kept your methodology of using 1-based indexing for asking the user to fill in values, rather than 0-based indexing)
for (int i = 0; i < number; i++){
String elementInfo =
JOptionPane.showInputDialog("Input value for element " + (i + 1));
int element = Integer.parseInt(elementInfo);
min_array[i] = element;
}
System.out.println('\u000C'); /*using BlueJ, this clears the console*/
for (int i = 0; i < number; i++){
System.out.println(min_array[i]);
}
I see that you're going from index 0 to index array.length - 2, instead of -1. That's the problem. I hope this helps
public double avg()
{
for (int i = 0; i < (min_array.length); i++)
{
recalculate = (recalculate + min_array[i]);
}
//should add together the values of all the elements
//this may be where it stops working as intended
double array_avg = (recalculate / min_array.length);
return array_avg;
//should divide the sum of all the elements by how many elements there are
//this is the other place where it might stop working.
}
Also always start a for loop with i=0 for counting purposes