Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am trying to make a function that outputs every case possible of a string. The function must output each variation of a string and keep a counter for that variation. For example in no particular order:
C.d
C>d
C>D
C.D
c.d
c.D
c>D
c>d
So far I have this:
public int allCase(String data)
{
int count=0; // counter for the amount of case changes completed
int size= data.length();// length of incoming string
char c[]= data.toLowerCase().toCharArray();
double maxpos=Math.pow(2,size);
System.out.println("Maximum possibilities= "+maxpos);
for(int i=0;i<size;i++)
{
if (c[i]> 33 && c[i]<64) // if the character is special characters !##$%^&*()_<>?,./
{ // prints characters in front and behind of special character
System.out.println( data.substring(0,i)+((char)(c[i]+16))+data.substring(i+1));
}
else{
// output the string variation
}
count++;
}
return count;
}
You can handle the alphabetic characters as a group, adding or subtracting 32, but the rest of the mappings aren't regular enough to beat a table lookup.
Keep two parallel strings:
shifted = "ABCDEFGHIJKLMNOPQRSTUVWXYZ~!##$%^&*()_+|<>?:\"{}";
unshifted = "abcdefghijklmnopqrstuvwxyz`1234567890-=\,./;'[]";
Then, find each character in one or the other string with .indexOf(). Find the opposite shift at the same index in the other string. If a character isn't in either string, then it's a space or another character that isn't part of a shifted/unshifted pair. The total number of strings to generate is then 2^(number of chars found in one of those strings).
Speaking of powers of 2, using Math.pow() is a lousy way to compute small powers of 2. Use 1L<<n instead of Math.pow(n) for integers 0 <= n <= 62, or even 1<<n for 0<=n<=30 if you're able to live with only being able to print out a billion or so strings.
You can make an iterative version, looping from an index value of 0 to (2^n)-1, where n the length of the input string, and then loop for k=0 to (n-1) testing bit k of the outer loop index value to see whether to print upper or lowercase version of the character. I didn't see it before, but Hot Licks has a comment about using this approach. To perform that test, observe that index&(1<<k) is nonzero if and only if bit k is set in (index).
A recursive version is much simpler, but I suspect you'll learn about that later.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
I am trying to solve this problem and I worked out a solution but its too slow, this is my approach:
loop to add all strings in an array
loop to concatenate strings based on inputs
print out final concatenated string
Which works, but I need a faster approach. I am thinking of trying to determine the order of concatenation of each string, then just print strings based on the order. But I have no idea how to determine the order in the first place. Does anyone have any advice? Thank you!
[SOLVED] thank you guys for the help! I was able to pass the test cases.
Don’t implement this task literally.
The entire task is designed such that you end up with all N input strings being concatenated in one string, the order determined by the numbers read from System.in.
But the result is not the concatenated string. The result is the output you produce by printing this concatenated string. So you get the same result, i.e. the same output, when you just print the original strings (without separators or line breaks) in the correct order, as if they were concatenated.
Kattio io = new Kattio(System.in, System.out);
int numStrs = io.getInt();
final class StringNode {
final String s;
StringNode last = this, next;
StringNode(String s) {
this.s = s;
}
void append(StringNode s) {
last.next = s;
last = s.last;
}
}
StringNode[] array = new StringNode[numStrs];
for(int i = 0; i < numStrs; i++) array[i] = new StringNode(io.getWord());
int idx = 0;
for(int j = 0; j < numStrs - 1; j++) {
int a = io.getInt() - 1, b = io.getInt() - 1;
array[a].append(array[b]);
idx = a;
}
for(StringNode n = array[idx]; n != null; n = n.next) System.out.print(n.s);
System.out.println();
The main issue with performing the string concatenation literally, is the copying of the characters, potentially over and over again, depending on the given order. In the worst case, you get an order which let’s you copy again the same data you’ve just copied, for every step, ending up at O(N²) time complexity.
The approach above skips the entire task of creating new strings or copying characters, making each step as cheap as two variable assignments.
Note that even if you’re going back to implement the task literally, i.e. to produce a single String, you can do it by replacing the final printing loop by a loop which appends all strings to a single StringBuilder. This will still be a linear operation, as appending all strings in the already determined final order implies copying each string only once, instead of repeatedly.
But as long as the success is measured by the output written to System.out, you don’t need to construct a final String object.
Java's strings are immutable. This means that each concatenation results in a fully new copy where both a and b are copied.
You need to use Java's StringBuilder and convert the end result to a normal string. StringBuilders truely append one to the other without copying the first one. They work like a dynamic length array under the hood.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
Given two strings, a and b, that may or may not be of the same length, determine the minimum number of character deletions required to make a and b anagrams. Any characters can be deleted from either of the strings.
This is my first time preparing for competitive programming and understanding the logic behind the two for loops is quite hard for me.
String str1 = s.next();
String str2 = s.next();
char []c1 = str1.toCharArray();
char []c2 = str2.toCharArray();
int []cnt1 = new int[26];
int []cnt2 = new int[26];
int len1 = str1.length();
for (int i = 0; i < len1; i++) {
cnt1[c1[i] - 97]++;
}
int len2 = str2.length();
for (int i = 0; i < len2; i++) {
cnt2[c2[i] - 97]++;
}
int cnt = 0;
for (int i = 0; i < 26; i++) {
cnt += Math.abs(cnt2[i] - cnt1[i]);
}
System.out.println(cnt);
This snippet goes over each string and counts the number of occurrences each letter has in it (and store the counters in an array for better performance).
It then goes over the two arrays of counters, and for each letter subtracts the counters for both strings (in absolute value). The difference is the number of that character that should be removed. These differences are summed, and the result is the answer.
Okay, this is what the program is doing with two for loops.
Imagine 'cnt1' as English alphabet 'A' to 'Z' written up on a paper from left to right, and so is 'cnt2'. First for loop is tick marking a letter on the paper should it be found in 'string1', and so does second for 'string2'.
Now, you have two papers with 'A' to 'Z' written up on them from left to right, and after two 'for loops' have executed, each of the paper has tick marks on those letters that were present in respective string inputs.
Now, if a letter is ticked on both the papers, leave it alone, and should you find any of the letter ticked in one paper (i.e. in the array), and is not ticked in the other array, then count it as a letter to be deleted.
By the time you have scanned both the papers like this from left to right, you'd have number of letters that need to be removed in totality from both the papers.
Lets see how it is implemented in code. Default initial values of primitive array is all zeros, and the act of 'tick marking' a letter on paper is achieved by changing that particular index to '1'.
So, by the time the first two for loops end, each of 'cnt1' and 'cnt2' arrays would have '1' in it randomly. If both the arrays have '1' or '0' in it for a given index, you need not count it, should they be different i.e. difference of that particular index for both the arrays is '1' (that's why you see Math.abs being used), then that is a letter to be deleted from first string, or the second.
edit: For competitive exams, you should be able to visualize the solution first, and then find an optimum one. Computers only add speed to the solution found. They don't think, we make them think :)
Hope you could visualize the solution first and are still getting used to programing. All the best!
I am currently a early CS student and have begun to start projects outside of class just to gain more experience. I thought I would try and design a calculator.
However, instead of using prompts like "Input a number" etc. I wanted to design one that would take an input of for example "1+2+3" and then output the answer.
I have made some progress, but I am stuck on how to make the calculator more flexible.
Scanner userInput = new Scanner(System.in);
String tempString = userInput.nextLine();
String calcString[] = tempString.split("");
Here, I take the user's input, 1+2+3 as a String that is then stored in tempString. I then split it and put it into the calcString array.
This works out fine, I get "1+2+3" when printing out all elements of calcString[].
for (i = 0; i <= calcString.length; i += 2) {
calcIntegers[i] = Integer.parseInt(calcString[i]);
}
I then convert the integer parts of calcString[] to actual integers by putting them into a integer array.
This gives me "1 0 2 0 3", where the zeroes are where the operators should eventually be.
if (calcString[1].equals("+") && calcString[3].equals("+")) {
int retVal = calcIntegers[0] + calcIntegers[2] + calcIntegers[4];
System.out.print(retVal);
}
This is where I am kind of stuck. This works out fine, but obviously isn't very flexible, as it doesn't account for multiple operators at the same like 1 / 2 * 3 - 4.
Furthermore, I'm not sure how to expand the calculator to take in longer lines. I have noticed a pattern where the even elements will contain numbers, and then odd elements contain the operators. However, I'm not sure how to implement this so that it will convert all even elements to their integer counterparts, and all the odd elements to their actual operators, then combine the two.
Hopefully you guys can throw me some tips or hints to help me with this! Thanks for your time, sorry for the somewhat long question.
Create the string to hold the expression :
String expr = "1 + 2 / 3 * 4"; //or something else
Use the String method .split() :
String tokens = expr.split(" ");
for loop through the tokens array and if you encounter a number add it to a stack. If you encounter an operator AND there are two numbers on the stack, pop them off and operate on them and then push back to the stack. Keep looping until no more tokens are available. At the end, there will only be one number left on the stack and that is the answer.
The "stack" in java can be represented by an ArrayList and you can add() to push items onto the stack and then you can use list.get(list.size()-1); list.remove(list.size()-1) as the pop.
You are taking input from user and it can be 2 digit number too.
so
for (i = 0; i <= calcString.length; i += 2) {
calcIntegers[i] = Integer.parseInt(calcString[i]);
}
will not work for 2 digit number as your modification is i+=2.
Better way to check for range of number for each char present in string. You can use condition based ASCII values.
Since you have separated your entire input into strings, what you should do is check where the operations appear in your calcString array.
You can use this regex to check if any particular String is an operation:
Pattern.matches("[+-[*/]]",operation )
where operation is a String value in calcString
Use this check to seperate values and operations, by first checking if any elements qualify this check. Then club together the values that do not qualify.
For example,
If user inputs
4*51/6-3
You should find that calcString[1],calcString[4] and calcString[6] are operations.
Then you should find the values you need to perform operations on by consolidating neighboring digits that are not separated by operations. In the above example, you must consolidate calcString[2] and calcString[3]
To consolidate such digits you can use a function like the following:
public int consolidate(int startPosition, int endPosition, ArrayList list)
{
int number = list.get(endPosition);
int power = 10;
for(int i=endPosition-1; i>=startPosition; i--)
{
number = number + (power*(list.get(i)));
power*=10;
}
return number;
}
where startPosition is the position where you encounter the first digit in the list, or immediately following an operation,
and endPosition is the last position in the list till which you have not encountered another operation.
Your ArrayList containing user input must also be passed as an input here!
In the example above you can consolidate calcString[2] and calcString[3] by calling:
consolidate(2,3,calcString)
Remember to verify that only integers exist between the mentioned positions in calcString!
REMEMBER!
You should account for a situation where the user enters multiple operations consecutively.
You need a priority processing algorithm based on the BODMAS (Bracket of, Division, Multiplication, Addition and Subtraction) or other mathematical rule of your preference.
Remember to specify that your program handles only +, -, * and /. And not power, root, etc. functions.
Take care of the data structures you are using according to the range of inputs you are expecting. A Java int will handle values in the range of +/- 2,147,483,647!
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
This program is supposed to count the number of characters "c" and "g" in genes in the DNA string and then take that number and divide it by the length of each gene. The number of cs and gs is always < gene.length(), therefore the output should be something like 0.65555, 0.35657 etc, but I get large numbers like 141, etc. Not sure what is wrong with this loop.
public void testfile(){
String dnaTest = "aaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaacccttaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctcacccttctaact";
int counter = 0;
for(String gene : s1.data()) {
for (char cORg : gene.toCharArray()) {
if ((cORg == 'c') || (cORg == 'g')) {
counter ++;
}
System.out.print(gene +" ");
}
float cgRatioGenes = counter/gene.length();
System.out.println("cgRatio: " + cgRatioGenes);
}
}
}
If you spot the error, let me know. Thanks!
EDIT
Even without the parentesis at the end of the DNA string and with the closing bracket, the loop was not producing the results I expected. Therefore, it is not off topic.
Two problems:
First, you never reinitialize counter when you start the loop again. Move that declaration inside the loop so that each repetition starts with a counter of zero.
If you make that change, all your results will be zero though, because you're diving two integers, which will truncate the results. Cast one to float, so that it keeps the decimal part. See this question for more information on the problem
for(String gene : s1.data()) {
int counter = 0; //Moved inside the for loop, so that it always starts at 0
for (char cORg : gene.toCharArray()) {
if ((cORg == 'c') || (cORg == 'g')) {
counter ++;
}
System.out.print(gene +" ");
}
//Floating point division, instead of integer division
float cgRatioGenes = ((float)counter)/gene.length();
System.out.println("cgRatio: " + cgRatioGenes);
}
One potential problem is here
float cgRatioGenes = counter/gene.length();
As gene.length() is an integer value the ratio is not computed correctly. Instead, you should cast one of them to float like this
float cgRatioGenes = ((float)counter)/gene.length();
In addition, the counter variable should probably be initialized to zero for each gene (unless you want to count the c/g values over all genes).
This probably does not explain the behavior you are observing, but it is not possible to figure it out unless a complete working example is given.
It's a little unclear what the exact intent of this code is, but my guess is that you're using one int counter for every gene in s1.data(). I assume you want to count the number of valid characters per gene, not in the entire pool.
If you do want to count for the entire pool, the problem is that you're peforming gene.length outside of the for, which should honestly throw a compiler error unless you have a gene defined somewhere else as well.
Additionally, you're dividing two ints for your answer, which will yield an int. Case one of your variables to float to get a decimal answer.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to know how to count the occurrences of a particular sub-string in a string without using any of the built in JAVA string functions. For example:
InputString = "knowbutuknow"
subString = "know"
The program should return the result as 2.
EDIT: Re-phrased my question. This is one of those interview questions I came across.
EDIT: Basic string functions like charAt and length can be used here.
Assuming, you already know the keyword you are searching for:
Start at char "0" of Input String
Iterate until "length - keyWordLength" (keyword of length 4 can not match into the last 3 chars)
Inside: Iterate from 0 to keyWord.length -1 and always compare:
Char at Position of outer loop PLUS position of inner loop of the Input string with the char at "inner loops" position of the keyword.
if you find a match, go ahead with the innerloop, if it does not match, advance the outer loop, by simple "breaking" the inner loop.
If you have a match, and completely processed the inner loop, you have a match of that keyword.
Something like this. I'm Assuming String.length to be allowed. Otherwhise you would need to create your own strlen function. (This can be achieved, using a forach loop and simple counting "up")
This is untested and may not work out of the box, but should give you a brief idea.
String inputString = "knowbutuknow";
String subString = "know";
int matches = 0;
for (int outer = 0; outer <= inputString.length() - subString.length(); outer++){
for (int inner = 0; inner < subString.length(); inner++){
if (inputString.charAt(outer + inner) == subString.charAt(inner)){
// letter matched, proceed.
if (inner == subString.length()-1){
//last letter matched, so a word match at position "outer"
matches++;
//proceed with outer. Room for improvement: Skip next n chars beeing
// part of the match already.
break;
}
}else{
//no match for "outer" position, proceed to next char.
break;
}
}
}
edit: Sorry, mixed in some php :) fixed it.