credit card numbers need to be added without the dash - java

So one of the conditions for the credit card number to be valid is that "the sum of first 4 digits must be 1 less than the sum of the last 4 digits" I believe the problem could be it's counting the dashes as a digit but not sure. the rule 4 is that the sum of all digits must be divisible by 4, which seems to work, but rule 5 doesn't.
int sum = ccNumber.chars().filter(Character::isDigit).map(Character::getNumericValue).sum();
if(sum%4!=0){
valid = false;
errorCode = 4;
return;
}
// set values and for loop for fifth rule.
String digits = ccNumber.replaceAll("[ˆ0-9]","");
int firstfourdigits = 0;
int lastfourdigits = 0;
for(int i=0; i<4; i++)
firstfourdigits = firstfourdigits + Character.getNumericValue(ccNumber.charAt(i));
for (int i=0, m = ccNumber.length()-1; i<4; i++, m--)
lastfourdigits = lastfourdigits + Character.getNumericValue(ccNumber.charAt(m));
// mutator for fifth rule
if(lastfourdigits!= firstfourdigits -1){
valid = false;
errorCode = 5;
return;
}
sorry I'm lost and new to coding.

Edit since you altered your question. Original anwser to the original question is at the bottom part
Checking if first part and last part have a difference of one
The code you currently have is close, but there are some mistakes here and there.
Filtering out only digits: The code you use to filter out all characters that are not numeric should work, but in your following code you are no longer using this filtered value in your loop.
firstfourdigits + Character.getNumericValue(ccNumber.charAt(i));
This should use the variable with only your numeric values => digits
firstfourdigits = firstfourdigits + Character.getNumericValue(digits.charAt(i));
Difference in first group vs last group: The -1 should be replaced by +1 here. When you are experiencing problems with this type of checks, it's always adviced to try and calculate it on a piece of paper. Lets assume the sum of the first 4 digits is 8 and the sum of the last 4 digits is 9. As per the requirement, this is a valid number, and should result to false in your check if(lastfourdigits!= firstfourdigits -1)
Let's fill it in: 9 != 8-1 => 9 != 7 so this returns false, and marks it as invalid. If we base it on the requirement, you could write the sum of the first 4 digits should be one less then the last 4 digits as: firstfourdigits = lastfourdigits - 1. This is mathmatically the same as lastfourdigits = firstfourdigits + 1. However, in our check we want to know if this check is not correct, so we should change the statement to: if(lastfourdigits != firstfourdigits + 1)
These 2 changes should give you the results you asked for. Combining these changes, we come to the following code example
String digits = ccNumber.replaceAll("[ˆ0-9]", "");
int firstfourdigits = 0;
int lastfourdigits = 0;
for (int i = 0; i < 4; i++)
firstfourdigits = firstfourdigits + Character.getNumericValue(digits.charAt(i));
for (int i = 0, m = ccNumber.length() - 1; i < 4; i++, m--)
lastfourdigits = lastfourdigits + Character.getNumericValue(digits.charAt(m));
if(lastfourdigits!= firstfourdigits + 1){
valid = false;
errorCode = 5;
return;
}
Other recommendations
The above example should work for what you asked, and is based on your code. However there are some optimalisations possible to the code to make everything more readable
Use brackets on your for loop: To make it clearer what is inside the for loop, and what isn't, I would advise you to make use of curly brackets. Though they are not required, they will make it very clear what is and isn't in the for loop and will prevent hard to spot issues when you add something extra in the for loop
Use the short notation for addition: Instead of writing firstfourdigits = firstfourdigits + Character.getNumericValue(digits.charAt(i));, You could use a shorter notation of +=. This will take the value on the left side of your equals, and will calculate the sum of that value on the right side. firstfourdigits += Character.getNumericValue(digits.charAt(i));
The code looks like this then:
String digits = ccNumber.replaceAll("[ˆ0-9]", "");
int firstfourdigits = 0;
int lastfourdigits = 0;
for (int i = 0; i < 4; i++){
firstfourdigits += Character.getNumericValue(digits.charAt(i));
}
for (int i = 0, m = ccNumber.length() - 1; i < 4; i++, m--) {
lastfourdigits += Character.getNumericValue(digits.charAt(m));
}
if(lastfourdigits!= firstfourdigits + 1){
valid = false;
errorCode = 5;
return;
}
Anwser to original question to calculate the sum of all digits
You could make use of Character.isDigit(char). To simplify the for loop, you can even make use of a stream to get the sum
int sum = ccNumber.chars().filter(Character::isDigit).map(Character::getNumericValue).sum();
if (sum % 4 != 0) {
valid = false;
errorCode = 4;
return;
}
.chars(): This will create a stream of all the characters in the provided string so that we can loop over them one by one
.filter(Character::isDigit): This will filter out every character that is not a digit
.map(Character::getNumericValue): This will map the stream from Characters to their numeric values so that we can use those further
sum() will calculate the sum of the numeric values that we currently have in the Stream

The difference is always a positive value e.g. the difference between 4 and 5 or between 5 and 4 is the same i.e. 1. In other words, you need to compare the absolute value of the subtraction with 1.
Therefore, replace
if(lastfourdigits!= firstfourdigits -1)
with
if(Math.abs(lastfourdigits - firstfourdigits) != 1)
Another mistake in your code is that you have used ccNumber, instead of digits in your loops.
Some recommendations to make your code easier to understand:
Replace for (int i=0, m = digits.length()-1; i<4; i++, m--) with for (int m = digits.length() - 1; m >= digits.length() - 4; m--). Note that I've already replaced ccNumber, with digits in these statements.
Replace ccNumber.replaceAll("[^0-9]","") with ccNumber.replaceAll("\\D", "").
Replace firstfourdigits = firstfourdigits + Character.getNumericValue(digits.charAt(i)) with firstfourdigits += Character.getNumericValue(digits.charAt(i)). Note that I've already replaced ccNumber, with digits in these statements.
Always enclose the body of if and loop statements within { } even if there is just one statement inside the body.
Demo:
public class Main {
public static void main(String[] args) {
System.out.println(isValidOnDiffCriteria("1234-5678-9101-1213"));
System.out.println(isValidOnDiffCriteria("1234-5678-9101-1235"));
System.out.println(isValidOnDiffCriteria("1235-5678-9101-1234"));
}
static boolean isValidOnDiffCriteria(String ccNumber) {
String digits = ccNumber.replaceAll("\\D", "");
int firstfourdigits = 0;
int lastfourdigits = 0;
for (int i = 0; i < 4; i++) {
firstfourdigits += Character.getNumericValue(digits.charAt(i));
}
for (int m = digits.length() - 1; m >= digits.length() - 4; m--) {
lastfourdigits += Character.getNumericValue(digits.charAt(m));
}
if (Math.abs(lastfourdigits - firstfourdigits) != 1) {
return false;
}
return true;
}
}
Output:
false
true
true

Try the code above. Should be what you asked. You don't need a try catch.
static boolean isCardValid(String creditCard) {
// group digits in a string array
String[] cards = creditCard.split("-");
int sumAll = 0;
// for every group of digits we convert it to char[]
for (String card : cards) {
sumAll += sum(card.toCharArray());
}
int firstGroupOfDigits = sum(cards[0].toCharArray()) ;
int lastGroupOfDigits = sum(cards[cards.length-1].toCharArray());
if( firstGroupOfDigits == lastGroupOfDigits -1){
if (sumAll % 4 == 0) {
return true;
}
}
return false;
}
// sum the group of digits separated by "-"
static int sum(char[] chr) {
int sum = 0;
for (char c : chr) {
sum += Character.getNumericValue(c);
}
return sum;
}

Well, your program is not that bad and as far as I can tell there is only one problem and that is the you simply reversed the required test on the first and last groups. I would advise you to ensure the valid is initialized to true as the default. Then if none of the error codes are set, it will return true.
Presently you have the following:
if (lastfourdigits != firstfourdigits - 1) {
valid = false;
errorCode = 5;
}
But what you need is this
if (lastfourdigits != firstfourdigits + 1) {
valid = false;
errorCode = 5;
}
Your also have the following, unnecessary code.
String digits = ccNumber.replaceAll("[ˆ0-9]","");
The reason being is that you are simply using ccNumber starting at the beginning for the first four characters and starting at the end for the last four. In this way you are not encountering dashes so you don't need to get just the digits.
Another recommendation is that as soon as you find an error you set the error code and return immediately. What's the use in continuing to process a card that has already been found to be flawed?
Other considerations and an alterative approach
It may not be a part of the assignment but I would also consider the following:
What if you have more or less than 16 digits?
What if you have more than three dashes giving more than four groups of numbers.
Checking the above would require additional logic and would complicate your effort. But it is something to consider. What follows demonstrates one way to check on those particular format issues and report them. This uses basic techniques and avoids streams so as not to repeat unnecessary operations.
This example throws selective errors based on problems found. Those may be changed or eliminated altogether as explained later. Credit card validation is a task where the most straightforward solution is best and should require low overhead.
First, declare a special exception to catch credit card errors.
class BadCreditCardException extends Exception {
public BadCreditCardException(String message) {
super(message);
}
}
Now declare some test data.
String[] testData = {
"1234-4566-9292-0210",
"1500-4009-2400-1600",
"1500-4009-2400-160000",
"1234-45669292-0210",
"1#34-45-66-9292-0210",
"1234-45B6-9292-0210",
"1234-4566-9292-2234",
"1234-4566-9292-021022",
"1234-4566-9292-0210",
"4567-4566-92!2-6835",
"1234-4566-9292-0210",
"1234-45+6-9292-0210",
"1234-4566-92x2-0210",
"1234-4566-9292-0210",
};
Test the credit cards and report errors. Note that only first encountered errors are reported. There may be multiple errors in the number.
String fmt = "%-23s - %s%n";
for(String card : testData) {
try {
validate(card);
System.out.printf(fmt,card, "Valid");
} catch (BadCreditCardException bce) {
System.out.printf(fmt,card, bce.getMessage());
}
}
The above prints.
1234-4566-9292-0210 - Invalid credit card checksum
1500-4009-2400-1600 - Valid
1500-4009-2400-160000 - Non group of 4 digits
1234-45669292-0210 - Insufficient or too may dashes
1#34-45-66-9292-0210 - Insufficient or too may dashes
1234-45B6-9292-0210 - Non digit found.
1234-4566-9292-2234 - Valid
1234-4566-9292-021022 - Non group of 4 digits
1234-4566-9292-0210 - Invalid credit card checksum
4567-4566-92!2-6835 - Non digit found.
1234-4566-9292-0210 - Invalid credit card checksum
1234-45+6-9292-0210 - Non digit found.
1234-4566-92x2-0210 - Non digit found.
1234-4566-9292-0210 - Invalid credit card checksum
The Explanation
The validate method. The method works as follows.
split the card into groups using the dash (-) as a delimiter.
If there are not four groups, throw an exception.
Otherwise, sum each of the groups as follows each of these is checked during the summation process.
first check that the group is of size four, if not throw an exception.
as the group characters are iterated, if a non-digit is encountered, throw an exception.
otherwise, continue computing the sum for the current group as follows:
If the character is a digit, subtract 0 to convert it to an int
and add to the current sums array element.
when completed, add that group sum to the totalSum of all digits.
if the totalSum is divisible by four and the first group is one less than the last group, it is a valid card. Otherwise, throw an exception.
Alternative error handling modification
If the exceptions are not wanted, but just a pass or fail indication, then make the following changes.
change the void return type to boolean
if an exception was throw, simply return false
if all tests pass, then the last statement should return true
public static void validate(String cardNumber) throws BadCreditCardException {
int [] groupSums = new int[4];
int totalSum = 0;
String [] groups = cardNumber.split("-");
if (groups.length != 4) {
throw new BadCreditCardException("Insufficient or too may dashes");
}
for (int i = 0; i < groupSums.length; i++) {
if (groups[i].length() != 4) {
throw new BadCreditCardException("Non group of 4 digits");
}
for(int digit : groups[i].toCharArray()) {
if (!Character.isDigit(digit)) {
throw new BadCreditCardException("Non digit found.");
}
groupSums[i]+= digit -'0';
}
totalSum += groupSums[i];
}
if (groupSums[0]+1 != groupSums[3] || totalSum % 4 != 0) {
throw new BadCreditCardException("Invalid credit card checksum");
}
}

A separate class for Credit card and its parts
Add a Part class that manages a portion of the credit card
Add a CreditCard class that manages these portions
Valid each portion
In addition to validating each potion individually, validate additional check
Depending on the number of times, the valid & sumDigits method will be called, validation/sum can be added in respective methods or in constructor.
import java.util.Arrays;
public class CreditCard {
private final String input;
private final Part[] parts;
private final boolean valid;
CreditCard(String card) {
this.input = card;
if (card == null || card.length() != 19) {
valid = false;
parts = null;
} else {
parts = Arrays.stream(card.split("-")).map(Part::new).toArray(Part[]::new);
final int totalSum = Arrays.stream(parts).mapToInt(Part::sumDigits).sum();
valid = totalSum % 4 == 0 && parts.length == 4
&& parts[0].sumOfDigits + 1 == parts[3].sumOfDigits
&& Arrays.stream(parts).allMatch(Part::isValid);
}
}
static class Part {
final int num;
final boolean valid;
final int sumOfDigits;
Part(String part) {
int localNum = 0;
try {
localNum = Integer.parseInt(part);
} catch (Throwable ignored) {
}
this.num = localNum;
valid = part.length() == 4 && part.equals(String.format("%04d", num));
if (valid) {
sumOfDigits = part.chars().map(Character::getNumericValue).sum();
} else {
sumOfDigits = -1;
}
}
boolean isValid() {
return valid;
}
int sumDigits() {
return sumOfDigits;
}
}
public static void main(String[] args) {
String[] creditCards = {
"1000-0000-0001-0002",
"0000-0000-0000-0000",
"10000-0000-0001-0002",
"10000000-0001-0002",
"1a00-0000-0001-0002",
"1234-4826-6535-1235",
};
Arrays.stream(creditCards).map(CreditCard::new)
.forEach(c -> System.out.println(c.input + " is " + c.valid));
}
}

Everything is fine except the second for loop and your if condition.
Replace your code with the following changes and it should work fine:
int firstfourdigits = 0, lastfourdigits = 0;
for(int i=0; i<4; i++)
firstfourdigits = firstfourdigits + Character.getNumericValue(ccNumber.charAt(i));
for (int m = ccNumber.length()-1; m>ccNumber.length()-5; m--)
lastfourdigits = lastfourdigits + Character.getNumericValue(ccNumber.charAt(m));
if(firstfourdigits != lastfourdigits - 1){
valid = false;
errorCode = 5;
return;
}
You do not need to extract digits at all.

public boolean ccnCheck(String ccn){
String iccn = ccn.replaceAll("-","");
int length = iccn.length();
int fsum = 0;
int lsum = 0;
int allsum = 0;
for( int i = 0; i < length; i++){
int val = Character.getNumericValue(iccn.charAt(m))
if( i < 4)
fsum += val;
if( i >= length-4)
lsum += val;
allsum += val;
}
if( (allsum % 4) != 0)
return false;
if( fsum != lsum-1 )
return false;
return true;
}

In your rule five check, you're using ccNumber instead of your digits string.
For example, shouldn't
Character.getNumericValue(ccNumber.charAt(i));
be this instead:
Character.getNumericValue(digits.charAt(i));

Related

word length in Java

I am having trouble with understanding some of the codes in my assignment of finding the word lengths in a file. NB: the Environment I am using is Blue J with a library from dukelearntoprogram.com, this is the link for downloading Blue J, http://www.dukelearntoprogram.com/course3/index.php. I have created a void method called countWordLength, with parameter FileResource called resource, and an integer array called counts. this method should return the number words at a specific length in a file. For instance: 2 words of length 2: My as.
They have given me the code for this assignment but I am not understanding the following code, in my countWordLength method.
for (String word : resource.words()) {
int finalLength = 0;
int totalLength = word.length();
if (Character.isLetter(word.charAt(0)) == false) {
finalLength = totalLength-1;
}
else {
finalLength = totalLength;
}
if (Character.isLetter(word.charAt(totalLength-1)) == false && totalLength > 1) {
finalLength = finalLength-1;
}
if (finalLength >= counts.length) {
counts[counts.length-1] += 1;
}
else {
counts[finalLength] += 1;
}
The specific part that I don't understand is the meaning or usefulness of
if (finalLength >= counts.length) {
counts[counts.length-1] += 1;
}
else {
counts[finalLength] += 1;
}
if my question is not clear, and you may want more parts of my code please let know. Any help
will be highly appreciated.
Explanation:
int finalLength = 0;
int totalLength = word.length();
if (Character.isLetter(word.charAt(0)) == false) {
finalLength = totalLength-1;
}
else {
finalLength = totalLength;
}
Above lines are initiating lengths. If 1st character is not alphabet, then reducing length.
if (Character.isLetter(word.charAt(totalLength-1)) == false && totalLength > 1) {
finalLength = finalLength-1;
}
If last character is not alphabet, removing one more character but a special condition added here that it is we reduce word length only if it's length > 1
if (finalLength >= counts.length) {
counts[counts.length-1] += 1;
}
This might be bit tricky for you. If calculated length is greater than array we assigned, we are adding count to last one. Ex: Let's say they assigned array with 20 and if got word length as 30, then we will assign this word count to last index (19).
else {
counts[finalLength] += 1;
}
If length is less than size allowed than we will add to that respective index.

Assistance with a java program that counts up to a number, in binary

I've recently taken up a computer organization course in where we learn binary hex etc, I took it upon myself to attempt to create a program that will count from 0 up to an input number, however the counting is done in binary. I've run into some trouble and confused myself beyond belief, some clarification and assistance would be greatly appreciated. Specifically speaking, how can I efficiently and effectively replace the values of a string containing the previous binary number, with 0's and 1's using some sort of for-loop. I'm aware that there is some method for directly converting a string to binary, however; I wanted to do this more complicated method for practice.
package counting;
import java.util.Scanner;
public class counting
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.println("Hello, this is a number counter, please enter the integer you would like to count to");
int number = input.nextInt();
String start = "0000000000";
// 000~etc is used as the start simply because i'm not sure how to calculate how many digit places
//the number input by the user will have
StringBuilder cont = new StringBuilder(start);
System.out.println(start);
/*What i intend to do is have the binary loop counter continue until it reaches
* the number input by the user, afterwards, working in a right to left manner, start counting from
* 0 up to the number given by the user, starting with 0. then using another loop, still using
* the right to left manner, if there is a 0, it should be replaced with a 1, and if there is a
* 1, it should be replaced with a 0, and the character before it should be replaced with a 1, if there
* is no room, continue to the left until there is a space available for a 1 and then reset all values
* after the 1 back to zero, and resume counting. the way i see it is requires a for loop to be used
* as the current position of a cursor used to determine what changes must be made
*/
for(int i = 0; i < number; i++)
{
int l = start.length();
for(int n = 0; n <= number; n++)
{
for(int w = 1; w <= l; w++)
{
if (cont.charAt(l-w) == '0')
{
cont.setCharAt((cont.length()-w), '1');
System.out.println(cont);
}
else if (cont.charAt(l-w) == '1')
{
cont.setCharAt((cont.length()-w), '0');
cont.setCharAt((cont.length()-(w+1)), '1');
System.out.println(cont);
}
}
}
System.out.println(cont);
}
}
}
Here is a little loop that will do what you are looking for. You just have to remember powers of 2 to count in binary.
public static char flip(char c){
if(c == '0')
return '1';
else
return '0';
}
public static void main(String[] args) {
String start = "0000000000";
StringBuilder cont = new StringBuilder(start);
int number = (int)Math.pow(2,10);
for(int i = 0; i < number; i++)
{
if(i != 0){
int val = (int)Math.floor(i/2);
for(int j = 0; j <= val; j++){
// Flip any bit that when modded by 2^j == 0
if(i % Math.pow(2,j) == 0){
cont.setCharAt((cont.length() - (j + 1)), flip(cont.charAt(cont.length() - (j + 1))));
}
}
}
System.out.println(cont);
}
}

Reversal of an Integer to check for Palindromic Number

I've looked at a few different stack questions and googled, but nothing I've read really has dealt with reversal of integers, but just strings.
So right now my code may or may not work at all, and it may be the dumbest thing you've ever seen, and that's okay and corrections are welcomed, but from what I hope my code will be doing is going through 100 - 999 multiplying the two ints and then checking whether it's palindromic or not. The if with reverse.equals(sum) is totally pseudocode and obviously won't work, however I can't figure out how to do a check for a palindromic int. Is there a simple way to do this? I've read some pretty lengthy and complicated ways, but I'm sure there's gotta be a simple way. Maybe not. :/. Anyway, here's my code.
public class PalandromicNum {
public static void main(String[] args){
int numOne = 100;
int numTwo = 100;
int toteVal;
int counter = 1000;
int sum = 0;
int finalSum = 0;
for(int i=0; i<counter; i++){
toteVal = numOne * numTwo;
numTwo++;
if(numTwo == 999){
numOne++;
numTwo = 100;
}
if(toteVal < sum){
sum += toteVal;
if(reverse.equals(sum)){
finalSum = sum;
System.out.println(finalSum);
}
}
}
}
}
Thanks again in advance!
This is on my phone so sorry for any errors.
Convert your number to a String and:
public static boolean isPalindrome(String str)
{
// base recursive case
if (str.length <= 1) {
return true;
}
// test the first and last characters
char firstChar = str.charAt(0);
char lastChar = str.charAt(str.length - 1) // subtract 1 as indexes are 0 based
if (!firstChar.equals(lastChar)) {
return false;
}
// if the string is longer than 2 chars and both are equal then recursively call with a shorter version
// start at 2nd char, end at char before last
return isPalindrome(str.substring(1,str.length);
}
Reversing integers is quite easy. Remember mod 10 gives u last digit. Loop over it, chopping off last digit of the number one at a time and adding it to reverse to new number. Then its matter of simple integer equality
int rev = 0;
int n = sum;
while(n)
{
rev = rev*10 + n%10;
n /= 10;
}
if(sum==rev)
//palindrome
else
//no no no no.
You can create a function named isPalindrome to check whether a number is a palindrome.
Use this function in your code.
You just need to pass the number you want to check into this function.
If the result is true, then the number is a palindrome.
Else, it is not a palindrome.
public static boolean isPalindrome(int number) {
int palindrome = number; // copied number into variable
int reverse = 0;
while (palindrome != 0) {
int remainder = palindrome % 10;
reverse = reverse * 10 + remainder;
palindrome = palindrome / 10;
}
// if original and reverse of number is equal means
// number is palindrome in Java
if (number == reverse) {
return true;
}
return false;
}
}
I believe that this code should help you out if you are trying to find out how many palindromes are between 100-999. Of course, it will count palindromes twice since it looks at both permutations of the palindromes. If I were you I would start creating methods to complete a majority of your work as it makes debugging much easier.
int total = 100;
StringBuilder stringSumForward;
StringBuilder stringSumBackward;
int numberOfPals = 0;
for(int i = 100; i < 999; i++){
for(int j = 100; j < 999; j++){
total = i * j;
stringSumForward = new StringBuilder(String.valueOf(total));
stringSumBackward = new StringBuilder(String.valueOf(total)).reverse();
if(stringSumForward.toString().equals(stringSumBackward.toString())){
numberOfPals++;
}
}
}

Using for loop to get the Hamming distance between 2 strings

In this task i need to get the Hamming distance (the Hamming distance between two strings of equal length is the number of positions at which the corresponding symbols are different - from Wikipedia) between the two strings sequence1 and sequence2.
First i made 2 new strings which is the 2 original strings but both with lowered case to make comparing easier. Then i resorted to using the for loop and if to compare the 2 strings. For any differences in characters in these 2 pair of string, the loop would add 1 to an int x = 0. The returns of the method will be the value of this x.
public static int getHammingDistance(String sequence1, String sequence2) {
int a = 0;
String sequenceX = sequence1.toLowerCase();
String sequenceY = sequence2.toLowerCase();
for (int x = 0; x < sequenceX.length(); x++) {
for (int y = 0; y < sequenceY.length(); y++) {
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else if (sequenceX.charAt(x) != sequenceY.charAt(y)) {
a += 1;
}
}
}
return a;
}
So does the code looks good and functional enough? Anything i could to fix or to optimize the code? Thanks in advance. I'm a huge noob so pardon me if i asked anything silly
From my point the following implementation would be ok:
public static int getHammingDistance(String sequence1, String sequence2) {
char[] s1 = sequence1.toCharArray();
char[] s2 = sequence2.toCharArray();
int shorter = Math.min(s1.length, s2.length);
int longest = Math.max(s1.length, s2.length);
int result = 0;
for (int i=0; i<shorter; i++) {
if (s1[i] != s2[i]) result++;
}
result += longest - shorter;
return result;
}
uses array, what avoids the invocation of two method (charAt) for each single char that needs to be compared;
avoid exception when one string is longer than the other.
your code is completely off.
as you said yourself, the distance is the number of places where the strings differ - so you should only have 1 loop, going over both strings at once. instead you have 2 nested loops that compare every index in string a to every index in string b.
also, writing an if condition that results in a+=0 is a waste of time.
try this instead:
for (int x = 0; x < sequenceX.length(); x++) { //both are of the same length
if (sequenceX.charAt(x) != sequenceY.charAt(x)) {
a += 1;
}
}
also, this is still a naive approach which will probbaly not work with complex unicode characters (where 2 characters can be logically equal yet not have the same character code)
public static int getHammingDistance(String sequenceX, String sequenceY) {
int a = 0;
// String sequenceX = sequence1.toLowerCase();
//String sequenceY = sequence2.toLowerCase();
if (sequenceX.length() != sequenceY.length()) {
return -1; //input strings should be of equal length
}
for (int i = 0; i < sequenceX.length(); i++) {
if (sequenceX.charAt(i) != sequenceY.charAt(i)) {
a++;
}
}
return a;
}
Your code is OK, however I'd suggest you the following improvements.
do not use charAt() of string. Get char array from string using toCharArray() before loop and then work with this array. This is more readable and more effective.
The structure
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else if (sequenceX.charAt(x) != sequenceY.charAt(y)) {
a += 1;
}
looks redundant. Fix it to:
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else {
a += 1;
}
Moreover taking into account that I recommended you to work with array change it to something like:
a += seqx[x] == seqY[x] ? 0 : 1
less code less bugs...
EDIT: as mentionded by #radai you do not need if/else structure at all: adding 0 to a is redundant.

Finding specific number in prime number array

I'm trying to find prime numbers with a specific condition in Java.
The challenge is to show all the prime numbers (under 100.000) which contain a '3' four times.
I already have a code which shows all the prime numbers under 100.000, but I can't seem to figure out how to count the ones that contain the number '3' four times.
I can however count all the prime numbers.
Can someone help me with this?
Here's the code I have, where am I going to put the numbers into strings?
package Proeftentamen;
import java.util.regex.*;
/**
*
* #author Stefan
*/
public class Vraag_6 {
/// priemgetallen waar 4x een 3 in voor komt???? wtf...
public static void main(String[] args) {
boolean[] lijst = new boolean[1000000]; // hoeveelheid getallen
vularray(lijst);
lijst = zeef(lijst);
drukaf(lijst);
}
public static void vularray(boolean[] lijst) {
for (int i = 2; i < lijst.length; i++) {
lijst[i] = true;
}
}
public static boolean[] zeef(boolean[] lijst) {
for (int i = 2; i < lijst.length / 2; i++) {
if (lijst[i]) {
for (int j = 2 * i; j < lijst.length; j += i) {
lijst[j] = false;
}
}
}
return lijst;
}
public static void drukaf(boolean[] lijst) {
int count = 0;
for (int i = 2; i < lijst.length; i++) {
if (lijst[i] == true) {
System.out.println(i + " " + lijst[i]);
count++;
}
}
System.out.println("Aantal priemgetallen: " + count);
}
}
This question really sounds like a homework, so you should write down what you have come up with and what you tried so far.
There are a lot of ways to count numbers. Just to give you a clue, you can use the reminder operation (in Java - %):
56 % 10 = 6
25 % 5 = 0
So, when you divide by 10 and use a reminder operation you can get the last digit of your number. Now use a loop and counter and you'll be fine.
Another option (very ugly, so don't really use it :) ) - to turn your number into a String and iterate (loop) over its characters.
Hope this helps and good luck!
This code generate 50 permutation of numbers that has four '3' in it's digits
so check each number that is prime or not
public void generateNumbers() {
StringBuilder s = new StringBuilder();
s.append("3333");
for (int i = 0; i < 5; i++) {
for (int j = 0; j <= 9; j++) {
if (j%3==0) continue;
s.insert(i,String.valueOf(j));
int number=Integer.parseInt(s.toString());
System.out.println(number);
s.delete(i,i+1);
}
}
}
Iterate across each prime number.
For each prime number, convert it to a string using the Integer.toString(int) static method.
With this string, iterate over every character (use a for loop and the non-static method String.charAt(int index)) and count the number of times that method returns '3'. (The character '3', not the String "3").
Unless you have some other purpose for an array of prime-number Strings, don't bother to store them anywhere outside the loop.
Please refer below code to validate all such prime numbers.
void getPrimes(int num ,int frequency,char digit) {
int count = 0;
String number=Integer.toString(num);
for (int i = 0; i < number.length(); i++) {
if (count < frequency) {
if (number.charAt(i) == digit)
count++;
}
if (count == frequency)
{
System.out.println(number);
return ;
}
}
}
Using the primes function from an exercise on the Sieve of Eratosthenes, as well as the digits and filter functions from the Standard Prelude, this Scheme expression finds the seven solutions:
(filter
(lambda (n)
(= (length
(filter
(lambda (d) (= d 3))
(digits n)))
4))
(primes 100000))
The outer filter runs over all the primes less than 100000 and applies the test of the outer lambda to each. The inner filter computes the digits of each prime number and keeps only the 3s, then the length function counts them and the equality predicate keeps only those that have 4 3s. You can run the program and see the solution at http://codepad.org/e98fow2u.
you only have at most five digits, four of which must be 3. So what can you say about the remaining digit?
It's not hard to just write out the resulting numbers by hand, and then test each one for primality. Since there are no more than 50 numbers to test, even the simplest trial division by odds will do.
But if you want to generate the numbers programmatically, just do it with 5 loops: add 10,000 to 03333 9 times; add 1,000 to 30333 9 times; add 100 to 33033 9 times; etc. In C++:
int results[50];
int n_res = 0;
int a[5] = {13333, 31333, 33133, 33313, 33331};
for( int i=0, d=10000; i<5; ++i, d/=10)
for( int j=1; j<9; ++j, a[i]+=d )
if( is_prime(a[i]) )
results[n_res++] = a[i];

Categories