public class CreditCardNumber {
private String issuerId;
private String accountNum;
private int checkDigit = 9;
private StringBuilder builder;
public CreditCardNumber(String id, String accNum) {
this();
if (id != null && accNum != null && id.length() == 6 && accNum.length() == 9 && isDigit(id) == true
&& isDigit(accNum) == true) {
accountNum = accNum;
issuerId = id;
}
setCheckDigit();
}
public CreditCardNumber() {
issuerId = "000000";
accountNum = "999999999";
}
public String getId() {
return issuerId;
}
public String getAccNum() {
return accountNum;
}
public int getCheckDigit() {
return checkDigit;
}
// A
private void setCheckDigit() {
int sum = checkSum();
int temp = sum + checkDigit;
if(temp%10 != 0) {
int num = temp%10;
checkDigit = checkDigit - num;
}
}
// Method to check if each character in string is a digit
public boolean isDigit(String s) {
boolean condition = true;
for (int i = 0; i < s.length(); i++) {
if (Character.isDigit(s.charAt(i))) {
condition = true;
}
}
return true;
}
// B
public void changeId(String id) {
int max = 9;
int min = 0;
if (id != null && id.length() == 6 && isDigit(id) == true) {
issuerId = id;
}
builder = new StringBuilder();
for (int i = 0; i <= 9; i++) {
int randomNum = (int) (Math.random() * (max - min + 1)) + min;
builder.append(randomNum);
accountNum = builder.toString();
}
setCheckDigit();
}
// C
private int checkSum() {
int sum = 0;
builder = new StringBuilder();
builder.append(issuerId);
builder.append(accountNum);
for (int i = 0; i < builder.length(); i++) {
// In each of the chars with an EVEN index
if (i % 2 == 0) {
int x = Integer.parseInt(Character.toString(builder.charAt(i))); //// get the int value from the char
int y = x * 2; // multiply it by 2
if (y >= 10) {
int z = y % 10;
z += 1; //// if doubling it has 2 digits, add those digits
builder.setCharAt(i, Character.forDigit(z, 10)); // put above result back into the StringBuilder at
// the same index
}
}
}
// Add the values of each digit in the StringBuilder
for (int i = 0; i < builder.length(); i++) {
sum += Integer.parseInt(Character.toString(builder.charAt(i)));
}
return sum;
}
//D
}
/* public String toString() {
a public method called toString (NO PARAMETERS) that returns (in a
return
statement) the issuerID, accountNum and checkDigit , BUT WITH A ' '
(space)
BETWEEN EVERY 4 CHARACTERS! (don't change any of the instance variables
here!)
}
}
*/
So my main issue here is, the directions say that I have to return these variables (all more than 4 digits) but with a delimiter ' ' between every 4 characters. I need some guidance into figuring out how to implement the "every 4 digits" part. Maybe using a StringBuilder? Please help.
To return a String with ' ' delimiters in between every four characters, use these methods:
// Takes a String as input and outputs a formatted String:
public String toFormattedString(String inputString){
StringBuilder returnStringBuilder = new StringBuilder();
for(int i = 0; i < inputString.length(); i++) {
returnStringBuilder.append(inputString.charAt(i));
if(i%4==3) {
returnStringBuilder.append(' ');
}
}
return new String(returnStringBuilder);
}
// Takes a int as input and outputs a formatted String:
public String toFormattedString(int inputInt){
return toFormattedString(Integer.toString(inputInt));
}
You can use these methods in your public String toString() method. I'm just not sure how you want the three Strings to be returned in one String return value. Do you want them appended to each other or returned in a different way?
Related
To shrink a string "abbcccbfgh" by removing consecutive k characters till no removal can be done.
e.g. for k=3 output for the above string will be "afgh".
Please note that K and string both are dynamic i.e provided by the user.
I wrote the below program but I couldn't complete it. Please help.
public class Test {
public static void main(String[] args) {
String str = "abbcccbfgh";
int k = 3;
String result = removeConsecutive(str, k);
System.out.print("result is " + result);
}
private static String removeConsecutive(String str, int k) {
String str1 = str + "";
String res = "";
int len = str.length();
char c1 = 0, c2 = 0;
int count = 0;
for (int i = 0; i < len - 1; i++) {
c1 = str.charAt(i);
c2 = str.charAt(i + 1);
if (c1 == c2) {
count++;
} else {
res = res + String.valueOf(c1);
count = 0;
}
if (count == k-1) {
//remove String
}
}
return res;
}
I suggest to do it with regex:
int l = 0;
do {
l = str.length();
str = str.replaceAll("(.)\\1{" + n + "}", "");
} while (l != str.length());
n = k - 1
(.)\1{2} means any character followed by n same characters. \1 means the same character as in group #1
Is it okey to have recursion ?
public class Test {
public static void main(String[] args) {
String str = "abbcccbfgh";
int k = 3;
String result = removeConsecutive(str, k);
System.out.print("result is " + result);
}
private static String removeConsecutive(String str, int k) {
String ret = str;
int len = str.length();
int count = 0;
char c1 = 0 ;
char c2 = 0;
char last = 0 ;
for (int i = 0; i < ret.length()-1; i++) {
last = c1 ;
c1 = str.charAt(i);
c2 = str.charAt(i + 1);
if (c1 == c2 ) {
if( count > 0 ) {
if( last == c1 ) {
count ++ ;
}
else {
count = 0;
}
}
else {
count++;
}
} else {
count = 0;
}
if (count == k-1) {
int start = ((i+1) - k) + 1 ;
String one = str.substring(0, start) ;
String two = str.substring(start+k);
String new1 = one + two ;
//recursion
ret = removeConsecutive(new1, k) ;
count = 0;
}
}
return ret;
}
}
You can do it with a stack. For each character ch in the string, push it to the stack, if there's 3 consecutive same characters, pop them all. In the end, convert the stack to a string. You can improve the program a little by using a special stack that remembers the number of occurrences of each element.
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
public class Reduce implements Function<String, String> {
private final int k;
public Reduce(final int k) {
if (k <= 0) {
throw new IllegalArgumentException();
}
this.k = k;
}
#Override
public String apply(final String s) {
Stack<Character> stack = new Stack<>();
for (Character ch : s.toCharArray()) {
stack.push(ch);
if (stack.topCount() == k) {
stack.pop();
}
}
return stack.toString();
}
public static void main(String[] args) {
Reduce reduce = new Reduce(3);
System.out.println(reduce.apply("abbcccbfgh"));
}
private static class Stack<T> {
private class Node {
private T value;
private int count;
Node(T value) {
this.value = value;
this.count = 1;
}
}
private List<Node> nodes = new ArrayList<>();
public void push(T value) {
if (nodes.isEmpty() || !top().value.equals(value)) {
nodes.add(new Node(value));
} else {
top().count++;
}
}
public int topCount() {
return top().count;
}
public void pop() {
nodes.remove(nodes.size()-1);
}
private Node top() {
return nodes.get(nodes.size()-1);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
nodes.forEach(n->{
for (int i = 0; i < n.count; i++) {
sb.append(n.value);
}
});
return sb.toString();
}
}
}
The following code is from Java mooc that is supposed to find all genes in a given file. The problem is that my getAllGenes method is not returning any genes for a given string of dna. I simply don't know what is wrong with the code.
The file I'm testing against (brca1line.fa) is located here https://github.com/polde-live/duke-java-1/tree/master/AllGenesFinder/dna
Thank you.
This is my java code.
public class AllGenesStored {
public int findStopCodon(String dnaStr,
int startIndex,
String stopCodon){
int currIndex = dnaStr.indexOf(stopCodon,startIndex+3);
while (currIndex != -1 ) {
int diff = currIndex - startIndex;
if (diff % 3 == 0) {
return currIndex;
}
else {
currIndex = dnaStr.indexOf(stopCodon, currIndex + 1);
}
}
return -1;
}
public String findGene(String dna, int where) {
int startIndex = dna.indexOf("ATG", where);
if (startIndex == -1) {
return "";
}
int taaIndex = findStopCodon(dna,startIndex,"TAA");
int tagIndex = findStopCodon(dna,startIndex,"TAG");
int tgaIndex = findStopCodon(dna,startIndex,"TGA");
int minIndex = 0;
if (taaIndex == -1 ||
(tgaIndex != -1 && tgaIndex < taaIndex)) {
minIndex = tgaIndex;
}
else {
minIndex = taaIndex;
}
if (minIndex == -1 ||
(tagIndex != -1 && tagIndex < minIndex)) {
minIndex = tagIndex;
}
if (minIndex == -1){
return "";
}
return dna.substring(startIndex,minIndex + 3);
}
public StorageResource getAllGenes(String dna) {
//create an empty StorageResource, call it geneList
StorageResource geneList = new StorageResource();
//Set startIndex to 0
int startIndex = 0;
//Repeat the following steps
while ( true ) {
//Find the next gene after startIndex
String currentGene = findGene(dna, startIndex);
//If no gene was found, leave this loop
if (currentGene.isEmpty()) {
break;
}
//Add that gene to geneList
geneList.add(currentGene);
//Set startIndex to just past the end of the gene
startIndex = dna.indexOf(currentGene, startIndex) +
currentGene.length();
}
//Your answer is geneList
return geneList;
}
public void testOn(String dna) {
System.out.println("Testing getAllGenes on " + dna);
StorageResource genes = getAllGenes(dna);
for (String g: genes.data()) {
System.out.println(g);
}
}
public void test() {
FileResource fr = new FileResource();
String dna = fr.asString();
// ATGv TAAv ATG v v TGA
//testOn("ATGATCTAATTTATGCTGCAACGGTGAAGA");
testOn(dna);
// ATGv v v v TAAv v v ATGTAA
//testOn("ATGATCATAAGAAGATAATAGAGGGCCATGTAA");
}
}
The data in the file is like "acaagtttgtacaaaaaagcagaagggccgtcaaggcccaccatgcctattggatccaaagagaggccaacatttttt". You are searching for uppercase characters in a string containing only lower case characters. String.indexOf will therefore never find TAA, TAG or TGA. Change the strings to a lower case.
int startIndex = dna.indexOf("atg", where);
...
int taaIndex = findStopCodon(dna,startIndex,"taa");
int tagIndex = findStopCodon(dna,startIndex,"tag");
int tgaIndex = findStopCodon(dna,startIndex,"tga");
Responding to the comment below: if you want to be able to handle mixed case, like you do in your text, you need to lowercase() the string first.
I have this method:
public static int parseInt(String str) {
if (isValidNumber(str)) {
int sum = 0;
int position = 1;
for (int i = str.length() - 1; i >= 0; i--) {
int number = str.charAt(i) - '0';
sum += number * position;
position = position * 10;
}
return sum;
}
return -1;
}
which converts a string into a integer. And as you can see it is (at the moment) in a if-statement with a method which checks if the input is a valid input for my purpose:
public static boolean isValidNumber(String str) {
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(c >= '0' && c <= '9'){
return true;
}
}
return false;
}
I want the string to be number only (negative and positive) no other is allowed. At that time a string i.e 1a1a will be converted to a integer which it shouldn't whereas -1 will not be converted. I think you guys understand what I mean. I don't know how to do that.
Please help!
Try this:
CODE:
public class validNumbers {
public static void main(String[] args) {
System.out.println(parseInt("345"));
System.out.println(parseInt("-345"));
System.out.println(parseInt("a-345"));
System.out.println(parseInt("1a5b"));
}
public static int parseInt(String str) {
String numberWithoutSign = removeSign(str);
if (isValidNumber(numberWithoutSign)) {
int sum = 0;
int position = 1;
for (int i = numberWithoutSign.length() - 1; i >= 0; i--) {
int number = numberWithoutSign.charAt(i) - '0';
sum += number * position;
position = position * 10;
}
if(isNegative(str)){
return -(sum);
}else{
return sum;
}
}
return -1;
}
/**
* Removes sign in number if exists
*/
public static String removeSign(String number){
if(number.charAt(0) == '+' || number.charAt(0) == '-'){
return number.substring(1);
}else{
return number;
}
}
/**
* Determines if a number is valid
*/
public static boolean isValidNumber(String number) {
for (int i = 0; i < number.length(); i++) {
char c = number.charAt(i);
if(c >= '0' && c <= '9'){
continue;
}else{
return false;
}
}
return true;
}
/**
* Determines if a number is negative or not
*/
public static boolean isNegative(String number){
if(number.charAt(0) == '-'){
return true;
}else{
return false;
}
}
}
OUTPUT:
345
-345
-1
-1
To check if a string is a real number you can use a method like this:
public static boolean isInteger(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException nfe) {}
return false;
}
The problem is with your function isValidNumber. It should return a false on first occurrence of a non numeric value, as follows:
public static boolean isValidNumber(String str) {
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(!(c >= '0' && c <= '9')){
if (i > 0) {
return false;
}
//This will only be invoked when `i == 0` (or less, which is impossible in this for loop), so I don't need to explicitly specify it here, as I have checked for `i > 0` in the above code...
if (c != '-' && c != '+') {
return false;
}
}
}
return true;
}
I was asked this question in an interview recently (Java programming que)
Return the sum of all integers from a random String.
Just iterate over the string, handle one digit at a time. This is pretty much exactly what the regex would do anyway:
String testStrings[] = { "-1a2b3c", "123ab!45c", "abcdef", "0123.4",
"dFD$#23+++12##T1234;/.,10" };
for (String testString : testStrings) {
String currentNumber = "";
int sum = 0;
for (int i = 0; i < testString.length(); i++) {
char currentChar = testString.charAt(i);
// Add digits or a leading minus to "currentNumber"
if (Character.isDigit(currentChar)
|| (currentNumber.equals("") && currentChar == '-')) {
currentNumber += currentChar;
} else {
// We've stumbled across a non-digit char.
//Try to parse the "currentNumber" we have so far
if (!currentNumber.equals("") && !currentNumber.equals("-"))
sum += Integer.parseInt(currentNumber);
currentNumber = "";
}
}
// Add the last "currentNumber" in case the string ends with a
// number
if (!currentNumber.equals("") && !currentNumber.equals("-"))
sum += Integer.parseInt(currentNumber);
System.out.println(sum);
}
Output:
4
168
0
127
1279
public class Random {
public int SumofNumbers(String s){
char[] str = s.toCharArray();
String answer="";
int sum = 0;
List<String> al = new ArrayList();
for (int i=0;i< str.length;i++){
if (checkNumber(str[i])){
answer=answer+str[i];
}
else
{
if(!answer.isEmpty()){
al.add(answer);
answer = "";
}
}
if (i == str.length -1 && !answer.isEmpty()) {
al.add(answer);
}
}
for (String a1 : al){
sum = sum + Integer.valueOf(a1);
}
return sum;
}
private boolean checkNumber(char c) {
if ((int)c > 47 && (int)c < 58){
return true;
}else if ((int)c == 45){
return true;
}
return false;
}
public static void main(String [] args){
Random r = new Random();
String test = "123ab!45c";
System.out.println(r.SumofNumbers(test));
}
}
public class StringToIntAddition {
public static void main(String[] args) throws Exception {
String str = "2e40 ssdf 23-9", number="";
int sum=0;
for(int i=0; i<str.length() ;i++){
if(Character.isDigit(str.charAt(i))){
number += str.charAt(i);
}
else if(!number.isEmpty()){
sum += Integer.parseInt(number);
number= "";
}
if (str.charAt(i) == '-'){
number = "-" ;
}
}
if(!number.isEmpty()){
sum += Integer.parseInt(number);
}
System.out.println("number= " + sum);
}
}
I've got a slightly 'cute' way to do this in Java 8: implement it as a Collector
public DigitCollector {
private boolean negative = false;
private int current = 0;
private int total = 0;
public int getTotal() {
if (negative) {
total -= current;
} else {
total += current;
}
current = 0;
negative = false;
return total;
}
public void accept(Character ch) {
if (Character.isDigit(ch)) {
current = 10 * current + Integer.parseInt(ch.toString());
} else if (ch.equals('-')) {
negative = true;
} else {
getTotal();
}
}
}
Now you can collect a stream of characters:
text.chars().map(ch -> new Character((char)ch))
.collect(DigitCollector::new, DigitCollector::accept, null)
.getTotal();
I realise the mapping ch -> new Character((char)ch)) looks strange but .chars() returns a stream of integers instead of characters. See here for reasons why (though pretty much everyone agrees it was a mistake).
This is a slightly longwinded way of doing it but it's pretty flexible: you could take a stream of Character from anywhere and do any sort of manipulation you wanted before collecting them. It seems to me to be a natural representation of the problem and, mostly, I just reckon streams are cooler than traditional iteration :-)
There's already quite a few answers, but this one seemed fun. I have a different solution that should be pretty efficient:
public static int countString(String input) {
if (input == null) return 0;
int sum = 0;
int accumulator = 0;
boolean lastCharWasDigit = false;
for (int i = 0, len = input.length(); ++i) {
char c = input.charAt(i);
// If a non-digit character is found, clear the
// accumulator and add it to the sum.
if (c < '0' || c > '9') {
sum += accumulator;
accumulator = 0;
lastCharWasDigit = false;
continue;
}
// If the previous character was a digit, that means
// this is a continuation. Multiply by ten to shift
// it over one power of ten before adding the new value
if (lastCharWasDigit) {
accumulator *= 10;
}
// Add the integer value of the character
int charValue = c - '0';
accumulator += charValue;
lastCharWasDigit = true;
}
// Finally, clear the accumulator for any ending digits,
// and return the sum
sum += accumulator;
return sum;
}
Here's my application
"Textform", take value from the searchbox.
"listKamus", take value from the array. Then "player name", change it value to string.
"KMP.knutMorris(textform, playerName)", send textform, playerName value to knutMorris class
MAIN CLASS
public void onTextChanged(CharSequence s, int arg1, int arg2, int arg3)
{
String textform = s.toString();
searchResults.clear();
for(int i=0;i<listKamus.size();i++)
{
String playerName=listKamus.get(i).toString();
KMP.knutMorris(textform, playerName);
if(KMP.value==1){
searchResults.add(listKamus.get(i));
}
}
adapter.notifyDataSetChanged();
}
KMP CLASS
public class KMP {
/** Failure array **/
private int[] failure;
public static int value;
/** Constructor **/
public KMP(String text, String pat)
{
/** pre construct failure array for a pattern **/
failure = new int[pat.length()];
fail(pat);
/** find match **/
int pos = posMatch(text, pat);
if (pos >= 0)
{
KMP.value = 1;
}
}
/** Failure function for a pattern **/
private void fail(String pat)
{
int n = pat.length();
failure[0] = -1;
for (int j = 1; j < n; j++)
{
int i = failure[j - 1];
while ((pat.charAt(j) != pat.charAt(i + 1)) && i >= 0)
i = failure[i];
if (pat.charAt(j) == pat.charAt(i + 1))
failure[j] = i + 1;
else
failure[j] = -1;
}
}
/** Function to find match for a pattern **/
private int posMatch(String text, String pat)
{
int i = 0, j = 0;
int lens = text.length();
int lenp = pat.length();
while (i < lens && j < lenp)
{
if (text.charAt(i) == pat.charAt(j))
{
i++;
j++;
}
else if (j == 0)
i++;
else
j = failure[j - 1] + 1;
}
return ((j == lenp) ? (i - lenp) : -1);
}
/** Main Function **/
public static void knutMorris(String textform, String isidatabase)
{
String text = textform;
String pattern = isidatabase;
KMP kmp = new KMP(text, pattern);
}
I want when people type on the searchbox it shows the right list of array.
I think the error one is here
MAIN CLASS
if(KMP.value==1){
searchResults.add(listKamus.get(i));
}
Or here
KMP CLASS
if (pos >= 0)
{
KMP.value = 1;
}
Can anyone tell me how to fix this ?