How Does This Palindrome Function Work? - java

I was give the following snippet of code to help me with a problem that involves the palindrome of a number. I am at a loss to figure out how this works exactly. I understand that it involves the while loop but am unable to follow the logic.
public static boolean isPalindrome(int nr) {
int rev = 0;
int x = nr;
while (x > 0) {
rev = 10 * rev + x % 10;
x /= 10;
}
return rev == nr;
}
Can someone please explain how this works?

If the number is a palindrome, then rev will equal the number after the loop finishes. Here's how it works, with a sample iteration where nr is 121:
public static boolean isPalindrome(int nr) {
int rev = 0;
int x = nr; // 121
while (x > 0) {
rev = 10 * rev + x % 10; // x % 10 is the last digit of x when in base 10. multiplying the previous value of rev by 10 and adding x % 10 is adding the last digit of x to the next digit of rev
// step 1: rev = 10*0 + 1 = 1
// step 2: rev = 10*1 + 2 = 12
// step 3: rev = 10*12 + 1 = 121
x /= 10; // truncates the last digit of x
}
so the return statement should be return rev == nr;

A palindrome is a number which reads same whether you read it from left to right or from right to left.
For Example - 1221
Now the execution
Suppose you have entered 1221 as the number.
Your calling method statement will look like
isPalindrome(1221);
Step 1 - Here we have three variables nr = 1221 , rev = 0 and x which will hold the original value which is 1221.
As soon as while loop begins it checks whether x is greater than zero or not, in our case 1221 is greater than 0 which is true so the program will go inside the loop.
Then rev = 10 * rev + x % 10;
This expression will change the initial value of rev which is zero.
10* 0 + 1221 % 10 will give 1 as the answer. since % modulus operator gives the remainder so 1221 when divided by 10 will give 1 as the remainder.
Now rev has 1 as its value.
Program will go to next statement to update the value of x as we have already stored one digit of our palindrome entry.
x / = 10 ;
This is a shorthand statement which is equivalent to
x = x / 10;
So here when x is divided by 10 we will get 122 as the quotient and 122 will be stored in x.
Step 2 - Now program flow will agin go to the first statement, ( thats the beauty of loops) to check for the condition whicha gain willl be true as x = 122 is greater than 0.
and now the value of rev will be
rev = 10 * 1 ( remember value of rev is 1 at the moment) + 122% 10 ;
the new value of rev will be
rev = 10 * 1 + 2 ( since modulus or remainder of 122 when divided by 10 is 2 )
final value according to first statement would be
rev = 12.
and program will be ahead to change the value of x since we are done with last two digit of our entered number.
x = x / 10; which will result us the quotient of 12.
Step 3 - 12 is greater than 0 condition true program will move to next statement.
rev = 10 * rev (12) + x (12) % 10;
new rev value
rev = 120 + 2 ;
rev = 122
the next statement will give us another changed value of x so that we can complete our palindrome digit.
x = x / 10;
x = 12/10; will give us 1 as quotient
Step 4 - while condition will again be satisfied which is 1 is greater than 0
and the updated rev value would be
rev = 10* rev (122) + 1% 10;
since diving 1 with ten will give us the remainder 1 , so the final expression will be
rev = 1221
and now the last change is value of x
x = x(1) \ 10 ;
x will be zero as there will be no quotient when dividing 1 with ten.
Step 5- 0 is greater than 0 condition will be false and program will exit the while and the final values of all the variables will be
nr = 1221
rev = 1221
x = 0
few statements inside your method will justify the return type Boolean.
if(nr==rev)
return true ;
else
return false;
I hope I could explain you the flow, also would like you to dry run the same program for non palindrome digit.

Original fragment of code when input parameter nr (later x, x>0) makes two things:
public static boolean isPalindrome(int nr) {
int rev = 0;
int x = nr;
while (x > 0) {
rev = 10 * rev + x % 10; // impl., for examp. 13 / 10 = 1
x /= 10; // f truncation of x
}

Related

Java:Three digit Sum - Find out all the numbers between 1 and 999 where the sum of 1st digit and 2nd digit is equal to 3rd digit

Problem statement: Three digit sum - Find all the numbers between 1 and 999 where the sum of the 1st digit and the 2nd digit is equal to the 3rd digit.
Examples:
123 : 1+2 = 3
246 : 2+4 = 6
Java:
public class AssignmentFive {
public static void main(String[] args) {
int i=1;
int valuetwo;
int n=1;
int sum = 0;
int valuethree;
int valueone = 0;
String Numbers = "";
for (i = 1; i <= 999; i++) {
n = i;
while (n > 1) {
valueone = n % 10;/*To get the ones place digit*/
n = n / 10;
valuetwo = n % 10;/*To get the tens place digit*/
n = n / 10;
valuethree = n;/*To get the hundreds place digit*/
sum = valuethree + valuetwo;/*adding the hundreds place and
tens place*/
}
/*Checking if the ones place digit is equal to the sum and then print
the values in a string format*/
if (sum == valueone) {
Numbers = Numbers + n + " ";
System.out.println(Numbers);
}
}
}
}
I got my result :
1
10
100
1000
10000
100000
1000000
10000000
100000000
1000000000
10000000001
100000000011
1000000000111
10000000001111
100000000011111
1000000000111111
10000000001111111
100000000011111111
1000000000111111111
Process finished with exit code 0
The result is not showing the actual result like it should be which should show values like: 123, 246 (Please refer to the problem statement above.)
Please let me know what seems to be the issue with the code and how to tweak it.
Don't know what you're trying to do with that while loop, or why you are building up a space-separated string of numbers.
Your code should be something like:
for (int n = 1; n <= 999; n++) {
int digit1 = // for you to write code here
int digit2 = // for you to write code here
int digit3 = // for you to write code here
if (digit1 + digit2 == digit3) {
// print n here
}
}
So basically your question is how to calculate the numbers, right?
My first hint for you would be how to get the first, second and third value from a 2 or 3 digit number.
For example for 3 digits you can do int hundretDigit = (n - (n % 100)) % 100. Of course this is really inefficient. But just get code working before optimizing it ;)
Just think about a way to get the "ten-digit" (2nd number). Then you add them and if they equal the third one you write System.out.println(<number>);
EDIT:
For 2 digit numbers I will give you the code:
if(i >= 10 && i <= 99) {
int leftDigit = (i - (i % 10)) / 10;
if(leftDigit == (i % 10)) {
//Left digit equals right digit (for example 33 => 3 = 3
System.out.println(i);
}
}
Try again and edit your source code. If you have more questions I will edit my (this) answer to give you a little bit more help if you need!

How can I multiply all the digits in an integer (between 000 & 1000 exclusive) without using control statements or loops?

I'm trying to write a program that can multiply all the digits of a number from 0 to 1000 exclusive using only math expressions in Java. My program works fine as long as the user types in a 3-digit number, but results in 0 if they type in anything less than 100.
I have tried getting the last digit of the input with '%10' and removing the last digit with '/10' but without a control statement to detect if the input has been reduced to zero, the program ends up multiplying by 0 when a 2-digit number has been reduced to zero, giving an incorrect result.
public class MultiplyDigits {
public static void main(String[] args){
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.print("Enter a number between 0 and 1000: ");
int number = input.nextInt();
int product = 1;
product*=number%10;
number/=10;
product*=number%10;
number/=10;
product*=number%10;
System.out.println(product);
}
}
An input of 55 should result in 25, but my program does 5 x 5 x 0 = 0
An input of 999 results in 729, which is correct. 9 x 9 x 9 = 729
Some more clarification, this is a problem out of the 2nd chapter of a textbook for complete novices. The author has not covered selection statements, loops, writing our own methods or classes, or anything more advanced than elementary programming, so the implication is that this is doable without those. The book has covered invoking methods in classes built into Java, although the author has only mentioned methods in the Math and System classes. For example, Math.max(), Math.min(), Math.pow(), System.currentTimeMillis();
What about this variant. To find the first number, you can decrease, first of all, the entered number by 100 and add 1 to avoid 0 during multipication. And , as recomended NVioli, the second number should be the same updated to have a possibility to enter number lower then 10. Thus, the final variant is:
int number = input.nextInt();
int t1 = 1 + (number-100) / 100;
int t2 = (1 + (number-10) / 10) % 10; \\By NVioli
int t3 = number % 10;
int product = t1 * t2 * t3;
System.out.println(product);
The first part is to extract the essential code into a separate Java method. I'm calling it dprod, which is short for "digit product".
static int dprod(int x) {
int hun = x / 100 % 10;
int ten = x / 10 % 10;
int one = x / 1 % 10;
return hun * ten * one;
}
The above code is the naive version that only works for numbers >= 100.
To treat numbers less than 100 as expected, you need to replace the hun or ten with 1 if it is 0.
static int dprod(int x) {
int hun = x < 100 ? 1 : x / 100 % 10;
int ten = x < 10 ? 1 : x / 10 % 10;
int one = x / 1 % 10;
return hun * ten * one;
}
The ?: operator is called a conditional operator, therefore it is probably not allowed under your rules. There is a possible workaround by using the ?: operator without writing it explicitly, by using the Math.max function.
static int dprod(int x) {
int hun = Math.max(100, x) / 100 % 10;
int ten = Math.max(10, x) / 10 % 10;
int one = x / 1 % 10;
return hun * ten * one;
}
The Math.max function uses the ?: operator internally, therefore it might be forbidden, too. This is subject to discussion though, since it depends on the exact wording of the rules and their intention.
If Math.max is forbidden, it is possible to implement it entirely without branches or conditions, see this C++ question, which can be translated to Java by replacing int32 with int and by replacing inline with static.
The complete code, including automatic tests, is:
package de.roland_illig.so;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
public class DprodTest {
static int dprod(int x) {
int hun = Math.max(x, 100) / 100 % 10;
int ten = Math.max(x, 10) / 10 % 10;
int one = x / 1 % 10;
return hun * ten * one;
}
#Test
public void testDprod() {
assertThat(dprod(999)).isEqualTo(729);
assertThat(dprod(123)).isEqualTo(6);
assertThat(dprod(99)).isEqualTo(81);
assertThat(dprod(9)).isEqualTo(9);
}
}
You could just initialize the program with a length 1000 array, initialize it with the value of each number, and then your real problem simplifies to:
System.out.println(calculatedArray[number]);
Your initialization could even take advantage of the fact that a leading 0 doesn't matter according to your rules (55 and 155 are the same result.)
calculatedArray[55] = calculcate(155);
there are some ways which can help you but all of them has a simple loop or if:
You can use digits = Logarithm of your number(10 base) and then you have number of digits, then you can use a loop to calculate the result. your loop will be repeated digit times so no matter how many digits your number has, it will always work.
You can check if your number is less than 100 and then just add 100 to that, then calculate the result, because of 1 * digit1 * digit2 there will be no error.

Print numerals in order in a sine wave

Background:
I've successfully written code that generates a sine wave from 0 to 2pi. Adjusting the constants xPrecision and yPrecision, you can stretch the graph horizontally or vertically.
I gain this neat output (in Eclipse), when xPrecision = yPrecision = 10:
My query:
I now wish to display digits 0 to 9 instead of the stars. So, the leftmost star is replaced by 0, the second left-most star is replaced by 1, and so on. When you reach 9, the next digit is again zero.
I am clueless as to how to do this. I have looked at wave patterns like this, but they are fixed width patterns, while mine is scalable.
The only way I can think of is converting my output to a 2D character array, then scraping the *s manually from left to right, and replacing them with the digits, and then printing it. However, this is extremely memory consuming at bigger values of x/yPrecision.
What is the most optimized way to achieve this output?
Code to print sine wave:
class sine {
static final double xPrecision = 10.0; // (1/xPrecision) is the precision on x-values
static final double yPrecision = 10.0; // (1/yPrecision) is the precision on y-values
static final int PI = (int) (3.1415 * xPrecision);
static final int TPI = 2 * PI; // twice PI
static final int HPI = PI / 2; // half PI
public static void main(String[] args) {
double xd;
for(int start = (int) (1 * yPrecision), y = start; y >= -start; y--){
double x0 = Math.asin(y / yPrecision),
x1 = bringXValueWithinPrecision(x0),
x2 = bringXValueWithinPrecision(x0 + TPI / xPrecision),
x3 = bringXValueWithinPrecision(PI/xPrecision - x0);
// for debug
//System.out.println(y + " " + x0 + " " + x1 + " " + x2 + " " + x3);
for(int x = 0; x <= TPI; x++){
xd = (x / xPrecision);
if(x1 == xd || x2 == xd || x3 == xd)
System.out.print("*");
else System.out.print(" ");
}
System.out.println();
}
}
public static double bringXValueWithinPrecision(double num){
// obviously num has 16 floating points
// we need to get num within our precision
return Math.round(num * xPrecision) / xPrecision;
}
}
"Draw" the graph in memory first, then assign digits to its vertical points, and print them in a separate pass.
01
9 2
8 3
7 4
6 5
5 6
4 7
3 8
2 9
1 0
0 1 2
2 1
3 0
4 9
5 8
6 7
7 6
8 5
9 4
0 3
12
See comments in the code for an explanation of how this works:
static final double xPrecision = 10.0; // (1/xPrecision) is the precision on x-values
static final double yPrecision = 10.0; // (1/yPrecision) is the precision on y-values
static final int PI = (int) (3.1415 * xPrecision);
static final int TPI = 2 * PI; // twice PI
static final int HPI = PI / 2; // half PI
public static void main(String[] args) {
// This part is the same as OP's code, except that instead of printing '*'
// it stores the corresponding row number in the array of rows
double xd;
int[] row = new int[100];
Arrays.fill(row, -1);
int r = 0;
int maxc = 0; // Mark the rightmost column of all iterations
for(int start = (int) (1 * yPrecision), y = start; y >= -start; y--){
double x0 = Math.asin(y / yPrecision),
x1 = bringXValueWithinPrecision(x0),
x2 = bringXValueWithinPrecision(x0 + TPI / xPrecision),
x3 = bringXValueWithinPrecision(PI/xPrecision - x0);
int c = 0;
for(int x = 0; x <= TPI; x++, c++){
xd = (x / xPrecision);
// This is where the asterisk used to go
if(x1 == xd || x2 == xd || x3 == xd)
row[c] = r;
}
maxc = Math.max(c, maxc);
r++;
}
// Walk the assigned rows, and give each one a consecutive digit
int[] digit = new int[100];
int current = 0;
for (int i = 0 ; i != 100 ; i++) {
if (row[i] != -1) {
digit[i] = (current++) % 10;
}
}
// Now walk the rows again, this time printing the pre-assigned digits
for (int i = 0 ; i != r ; i++) {
for (int c = 0 ; c != maxc ; c++) {
if (row[c] == i) {
System.out.print(digit[c]);
} else {
System.out.print(' ');
}
}
System.out.println();
}
}
public static double bringXValueWithinPrecision(double num){
// obviously num has 16 floating points
// we need to get num within our precision
return Math.round(num * xPrecision) / xPrecision;
}
The first part of the code fills row[i] array, which contains row for the asterisk in column i. First few numbers from row[] array would look like this:
10 9 8 7 6 5 4 - 3 2 - 1 - - - 0 0 - - - 1 - 2 3 - 4 5 6 7 8 9 10
- denotes cells with -1, which represents a missing value. The array says that the left-most asterisk is on row 10, the next asterisk is on row 9, then 8, 7, 6, and so on. Asterisks 11 and 12 are on row zero, which is at the top.
The second loop walks rows, skips -1s, and assign consecutive digits to all non-negative positions.
The third loop walks the entire field again going row-by-row, printing values from pre-assigned digit[] array when the current row matches the value in the row[] array.
Demo.
If you replace:
System.out.print("*");
with
System.out.print(""+(x%10));
it seems to nearly work.
56
1 0
9 2
8 3
6 5
5 6
4 7
3 8
2 9
1 0
0 1 2
2 1
3 0
4 9
5 8
6 7
7 6
9 4
0 3
2 1
67
Perhaps some further adjustments might get it perfect.
Doing it in a completely different way produces a different picture but achieves your effect.
Essentially,
for each y
for each x
calculate fx = sin(x)
if fx == y print * else print space
It's very inefficient as it calculates sin(x) x*y times when, if you filled a matrix, you could calculate sin(x) just x times.
static final double xPrecision = 10.0; // (1/xPrecision) is the precision on x-values
static final double yPrecision = 10.0; // (1/yPrecision) is the precision on y-values
private void sine() {
for (double y = 1; y >= -1; y -= 1.0 / yPrecision) {
int n = 0;
for (double x = 0; x < 2.0 * Math.PI; x += 1.0 / xPrecision, n++) {
double fx = Math.sin(x);
boolean star = Math.round(fx*xPrecision) == Math.round(y*yPrecision);
System.out.print((star ? ""+(n%10) : " "));
}
System.out.println();
}
}
public void test(String[] args) {
sine();
}
Gives you:
345678
12 901
90 2
8 34
67 5
5 6
4 7
3 8
2 9
1 0
0 1
2 2
3 1
4 0
56 9
7 8
8 67
9 5
01 34
23 12
4567890
Since this is Java, how about let's actually use some objects as objects rather than just as places to define a couple of functions.
Treat your wavy graph as if it is a composition of several different "branches" of the inverse sine function. (Mathematically, that's how we explain the way your version of the program uses Math.asin to produce multiple coordinates for stars.)
Branch 0 is the initial rising part of the curve,
Branch 1 is the falling part of the curve after Branch 0,
Branch 2 is the rising part of the curve after Branch 1, and so forth.
The branches cross the middle line of the output at x values 0,
PI, 2*PI, 3*PI, and so forth.
Depending on how far you want the graph to extend to the right, it is easy to determine how many branches you need.
For example, to plot from 0 to 8*PI you need nine branches
(Branch 0, Branch 8, and the seven branches between those two).
You can implement each branch using an object of some class,
let's call it ArcSineBranch.
It has a constructor, ArcSineBranch(int), that takes the branch number as a parameter.
Create some sort of ordered list (which could just be an ArcSineBranch[] array) and put these branch objects in it,
making sure the branch numbers go in sequence from 0 up to the largest number needed.
You'll also want to implement some way to tell the first ArcSineBranch where its leftmost end is--in the example in the question, the leftmost end of first branch is at y == 0, whereas for all other rising branches it is at y == -start and for all falling branches it is at y == start.
Now you call a mutator function of the first ArcSineBranch that tells it its leftmost symbol is 0. Treat this as an integer (rather than a string) for now to make the arithmetic easier.
You then query the first ArcSineBranch for the rightmost symbol it will write, which it can compute from the leftmost symbol and the number of lines it will write symbols on.
You also query it for the x coordinate of that rightmost symbol.
(The object computes the x-coordinate of the symbol for any y-coordinate by either adding or subtracting a rounded multiple of Math.asin(y / yPrecision) from a multiple of PI.)
Now for each ArcSineBranch in the list, you pass to it the rightmost symbol and x coordinate written by the previous branch.
This ArcSineBranch uses that information to determine the leftmost symbol it writes and the y coordinate of that symbol.
(I am being careful here about the y coordinate in case you choose a value of xPrecision that causes the rightmost x coordinate of one branch to be the same as the leftmost x coordinate of the next; we should only write one symbol at that place in the output, so we want the later branch to skip its leftmost x coordinate and write its leftmost symbol in the next place, one line up or down. But if the x coordinates are different we want the later branch to write a symbol on the same line.)
Now that the later ArcSineBranch "knows" the leftmost symbol it will print and thata symbol's y coordinate, you can query it for its rightmost symbol and x coordinate, and pass those to the next ArcSineBranch, and so forth.
Once you have traversed all the ArcSineBranch objects in this way,
so that each object knows what symbols need to be written for its branch and where to write them, you can loop for (y = start; y >= -start; y--);
within that loop you loop over the list of ArcSineBranch objects;
for each object you query whether it requires a symbol to be written at
y-coordinate y.
If the object requires a symbol to be written,
you query which symbol to write at which x-coordinate,
then space the output to the right until you reach that x-coordinate and write that symbol there.
But of course, first check that this would not plot a symbol beyond the
right-hand edge of the desired graph.
(This check really only applies to the last ArcSineBranch, so you can optimize the code a bit by looping over the other branches first and then dealing with the last ArcSineBranch separately.)
I've already described this algorithm in more detail than I initially wanted to. There should be enough information here to code this into Java in a relatively straightforward way, though there are still some localized details to be worked out.
Note that the design in this answer is intended to use the same mathematical ideas as the code in the question uses to decide where to plot the points.
Specifically, ArcSineBranch(0) produces the x1 values from the original code, ArcSineBranch(1) produces the x3 values, and ArcSineBranch(2) produces the x2 values.
The implementation of this design should plot a digit at the location of each star plotted by the original code, and should plot no other digits.
Care about a different approach?
3030
28 28
26 26
22 22
18 18
12 12
06 06
00 00 00
06 06
12 12
18 18
22 22
26 26
28 28
3030
Solution:
import static java.lang.Math.sin;
import static java.lang.Math.PI;
import static java.lang.Math.abs;
public class Sine {
static final Integer points = 30; // points on x and y axis
public static void main(String[] args) {
// contains graph points
Boolean[][] graph = new Boolean[points + 1][points + 1];
for (Double x = 0.0; x <= points; x++) {
// x axis pi value
Double pi = (x / points) * 2 * PI;
// sin(x) plot for x
Integer sinx = (int) Math.round((sin(pi) * points / 2) + points / 2);
graph[sinx][x.intValue()] = true;
}
for (Integer i = 0; i <= points; i++) {
for (Integer j = 0; j <= points; j++) {
// space characters on x axis
Integer pt = (int) Math.floor(Math.log10(points) + 1);
String space = String.format("%" + pt + "s", " ");
// padding for p
String p = String.format("%0" + (pt) + "d", abs(i - points / 2) * 2);
System.out.print(graph[i][j] != null ? p : space);
}
System.out.println();
}
}
}
Approach:
points contains the number of characters on x and y axis.
graph contains true or null for each x and y characters.
1st for loop:
Since the value of x in sine graph is from 0 to 2π, we need to convert x accordingly. So pi contains the value of the same range but according to x.
sinx is the Integer value according to x.
No need to explain graph[sinx][x.intValue()] = true;.
2nd for loops:
1st for loop
Execute LOOPLABEL.
Break to next line at the end.
2nd for loop(LOOPLABEL)
pt holds the number for padding on y axis.
space is the space characters to be printed on y axis.
p is the converted range between 0 to points.
Printing graph[i][j]
DEMO
By using the fact that each row has one point (on each slope), you can calculate which digit to display at each point without using extra memory or loops. Here's my example. Note that I only checked that this example only works if xPrecision and yPrecision are integers. You'll have to modify it if you want to use doubles.
class sine {
static final double xPrecision = 10.0; // (1/xPrecision) is the precision on x-values
static final double yPrecision = 10.0; // (1/yPrecision) is the precision on y-values
static final int PI = (int) Math.round(Math.PI * xPrecision);
static final int TPI = 2 * PI; // twice PI
static final int HPI = PI / 2; // half PI
static final int cycles = 2; // prints from x=0 to 2*cycles*pi
public static void main(String[] args) {
double xd;
int cycleoffset, cycleoffset2, topbottomoffset = 1;
for (int start = (int) (1 * yPrecision), y = start; y >= -start; y--) {
double x0 = Math.asin(y / yPrecision), x1 = bringXValueWithinPrecision(x0),
x2 = bringXValueWithinPrecision(x0 + TPI / xPrecision),
x3 = bringXValueWithinPrecision(PI / xPrecision - x0), tmp;
if (y == start) {
if (x1 == x3) // when there is only one point at the top/bottom
topbottomoffset = 0;
else if (x1 > x3) // swap x1 and x3
{
tmp = x1;
x1 = x3;
x3 = tmp;
}
} else if (y == -start) {
// I don't think this is needed, but just for safety make sure there is only one point on the bottom if there was only one point at the top
if (topbottomoffset == 0)
x2 = x3;
else if (x2 < x3) // swap x2 and x3
{
tmp = x2;
x2 = x3;
x3 = tmp;
}
}
cycleoffset = (int) (4 * yPrecision + 2 * topbottomoffset);
cycleoffset2 = -cycleoffset;
int start1 = topbottomoffset + 2 * (int) yPrecision, start2 = 2 * topbottomoffset + 4 * (int) yPrecision;
for (int x = 0, lim = cycles * TPI; x <= lim; x++) {
xd = ((x % TPI) / xPrecision);
if (x % TPI == 0)
cycleoffset2 += cycleoffset;
// x = 0 to pi/2
if (x1 == xd)
System.out.print((cycleoffset2 + y) % 10);
// x = 3pi/2 to 2pi
else if (x2 == xd)
System.out.print((cycleoffset2 + start2 + y) % 10);
// x = pi/2 to 3pi/2
else if (x3 == xd)
System.out.print((cycleoffset2 + start1 - y) % 10);
else
System.out.print(" ");
}
System.out.println();
}
}
public static double bringXValueWithinPrecision(double num) {
// obviously num has 16 floating points
// we need to get num within our precision
return Math.round(num * xPrecision) / xPrecision;
}
}
EDIT
The digits for the different ranges are calculated as follows
0 < x < π/2 : This one is simplest since it is the first range. Since the middle row is y=0 and that is where the sine wave starts, we can just use y to find the digit.
π/2 < x < 3π/2 : The digits here count up as we go down, but y decreases as we go down. So we have to use a -y term. On the top row, y=yPrecision, and the last digit from the previous range was yPrecision. So we use 2*yPrecision - y, because that includes the -y, and is equal to yPrecision at the first term (where y=yPrecision).
3π/2 < x < 2π : The digits here count down as we go down, so we need a +y term, but the tricky part is figuring where to start. Since the sine wave by this point has gone from 0 to yPrecision to 0 to -yPrecision, the bottom point (x=3π/2) should start at 3*yPrecision. Since y=-yPrecision at the bottom point, we use 4*yPrecision + y, since that includes a +y and is equal to 3*yPrecision at the first term (where y=-yPrecision).
The topbottomoffset term : Depending on the values used for xPrecision and yPrecision, there can be one or two points plotted on the top and bottom rows. If there are two points, we need to add one to digits in the π/2 to 3π/2 range, and two to the digits in the 3π/2 to 2π range.
The cycleoffset term : If multiple cycles of the sine wave are plotted, additional cycles need to start from the last digit used in the previous cycle. Each cycle goes from 0 to yPrecision to 0 to -yPrecision to 0, which is equal to 4*yPrecision. So each new cycle needs to start at 4*yPrecision*[the number of previous cycles]. If there are two points on the top and bottom rows, those need to be factored in as well.
Swapping values: When there are two points on the top row, then x1>x3. This happens because when y=yPrecision, we're taking Math.asin(1), which happens to be exactly pi/2=1.5707963267948966 in Java's double system. On lower xPrecision (<100.0), the rounding done by bringXValueWithinPrecision brings x1 up to 1.58 while x3 down to nearly 1.56. Hence, they need to be swapped in order to get the correct numerical order.
Here's my solution, which basically uses the half of the sine in 4 for loops:
from half to 0
from 0 to half
from half to the end
from the end to the half
And in each loop replace only the first asterisk.
class sine {
static final double xPrecision = 14.0; // (1/xPrecision) is the precision on x-values
static final double yPrecision = 14.0; // (1/yPrecision) is the precision on y-values
static final int PI = (int)(3.1415 * xPrecision);
static final int TPI = 2 * PI; // twice PI
static final int HPI = PI / 2; // half PI
public static void main(String[] args) {
double xd;
String str = "";
for (int start = (int)(1 * yPrecision), y = start; y >= -start; y--) {
double x0 = Math.asin(y / yPrecision),
x1 = bringXValueWithinPrecision(x0),
x2 = bringXValueWithinPrecision(x0 + TPI / xPrecision),
x3 = bringXValueWithinPrecision(PI / xPrecision - x0);
// for debug
//System.out.println(y + " " + x0 + " " + x1 + " " + x2 + " " + x3);
for (int x = 0; x <= TPI; x++) {
xd = (x / xPrecision);
if (x1 == xd || x2 == xd || x3 == xd)
str += "*";
else str += " ";
}
str += "\n";
}
String[] rows = str.split("\n");
int half = (int)(1 * yPrecision);
// we use this half in for loops, from half to 0, from 0 to half, from half to the end and from the end to the half, and replace only the first asterisk.
int val = 0;
for (int i = half; i >= 0; i--) {
if (val == 10) val = 0;
rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
}
for (int i = 0; i <= half; i++) {
if (val == 10) val = 0;
rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
}
for (int i = half + 1; i < rows.length; i++) {
if (val == 10) val = 0;
rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
}
for (int i = rows.length - 1; i >= half; i--) {
if (val == 10) val = 0;
rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
}
System.out.println(String.join("\n", rows));
}
public static double bringXValueWithinPrecision(double num) {
// obviously num has 16 floating points
// we need to get num within our precision
return Math.round(num * xPrecision) / xPrecision;
}
}
Result:
01
9 2
8 3
7 4
6 5
5 6
4 7
3 8
2 9
1 0
0 1 2
2 1
3 0
4 9
5 8
6 7
7 6
8 5
9 4
0 3
12
Add a counter in your loop and reset it when 9 is reached:
for(int x = 0, counter = 0; x <= TPI; x++, counter++){
xd = (x / xPrecision);
if(x1 == xd || x2 == xd || x3 == xd) {
System.out.print("" + counter);
if (counter == 9) {
counter = 0;
}
} else {
System.out.print(" ");
}
}

Java recursive method to find complement

I'm trying to think of how to use recursion to find complement of a number.
For example each digit x of a number must become 9 - x, so 1234 -> 8765.
I can't really think how to do that. This is my code so far:
public static int complement(int n){
int x = n % 10;
x = x - 9;
n = (n / 10)
return complement(n,x);
}
public static int complement(int n ,int times){
}
When you are dealing with recursion, it is important to write the algoritm first in English (or your native tongue :) ).
For this task, consider the following:
I have an number n. Let's take the last digit and subtract this digit to 9.
Do this again for the rest of the digits, i.e. n / 10. With the result obtained, we need to make a number again: so we multiply the result by 10 and add the digit we calculated before. In other words, complement(n / 10) returns the complement of the number n without the last digit, so we need to append the complement of the last digit to this.
When the number is less than 10, we have nothing more to do and we can just return 9 - n (this is the base case, the number is only one digit long).
In code, this is implemented as:
public static int complement(int n) {
if (n < 10) {
return 9 - n;
}
int x = n % 10;
x = 9 - x;
return 10 * complement(n / 10) + x;
}
and then:
System.out.println(complement(1234)); // prints 8765
This can be written a bit shorter with:
public static int complement(int n) {
if (n < 10) {
return 9 - n;
}
return 10 * complement(n / 10) + 9 - n % 10;
}

Credit Card Validation in Java with Luhn Algorithm with a string

I'm trying to create a method to validate a credit card number, but we have to process it as a string
heres some information about my task...
Credit card numbers follow certain patterns. A credit card must have between 13 and 16 digits.
In 1954, Hans Luhn of IBM proposed an algorithm for validating credit card numbers. The algorithm is useful to determine if a card number is entered correctly or if a credit card is scanned correctly by a scanner. Almost all credit card numbers are generated following this validity check, commonly know as the Luhn check or the Modulus 10 check, which can be described as follows. For illustration, consider the card number 4388576018402625.
Double every second digit from right to left. If doubling of a digit results in a 2-digit number, add up the two digits to get a single-digit number.
2 x 2 = 4
2 x 2 = 4
4 x 2 = 8
1 x 2 = 2
6 x 2 = 12 (1+2= 3)
5 x 2 = 10 (1+0= 1)
8 x 2 = 16 (1+6= 7)
4 x 2 = 8
Add all the single digit numbers from step 1 4 + 4 +8 + 2 +3 + 1 + 7 + 8 = 37
Add all digits in the odd places from right to left in the card number
5 + 6 + 0 + 8 + 0 + 7 + 8 + 3 = 37
Sum the results from step 2 and step 3 37 + 37 = 74
If the result from step is divisible by 10, the card number is valid; otherwise, it’s invalid. For example, the number 4388576018402625 is invalid, but the number 4388576018410707 is a valid Visa card; the number 6011000593748745 is invalid, but the number 6011000593748746 is a valid Discover card.
here's what I have so far
static void CreditCardValidator() {
System.out.println("enter a credit card number");
String temp = options.nextLine();
if (temp.length() < 13 || temp.length() > 16) {
System.out.println("Input is invalid");
}
// inside loop with char at command do all the math
int tmpdouble;
int sum = 0;
int counter = temp.length() - 1;
for (int i = temp.length(); i != 0; i--) {
char tmp = temp.charAt(i);
//tmp converted to int
tmpdouble = tmp * 2;
int firstDigit;
int secondDigit;
if (tmpdouble >= 10) {
firstDigit = i / 10;
secondDigit = i % 10;
sum = sum + firstDigit + secondDigit;
}
else if(tmpdouble <= 9) {
sum = sum + tmpdouble;
}
HELP HERE{
// need to have it do the same thing as above but for odd numbers
}
where do I go from there? ^^
Thanks
Don't roll your own. This algorithm is already provided via commons.
https://commons.apache.org/proper/commons-validator/apidocs/org/apache/commons/validator/routines/CreditCardValidator.html

Categories