Wrong output from a while loop using indexOf [duplicate] - java

This question already has answers here:
While loop doesn't run a indexOf search
(4 answers)
Closed 8 years ago.
I'm trying to find out how many times one string appears in another. For my testing, I'm using "ea" for wordOne and "Ilikedthebestontheeastbeachleast" for wordTwo. My output is returning 2 for my "appearance" variable, which should store how many times "ea" appears in wordTwo. It should return 3.
I've tried messing with variable initializations, and trying to think of the math differently, but I'm pretty much out of ideas.
Here's the relevant code section:
int wordTwoLength = wordTwo.length();
System.out.println(wordTwoLength);
while (wordTwoLength > 0)
{
positionCount = wordTwo.indexOf(wordOne, positionCount);
appearances++;
wordTwoLength = (wordTwoLength - positionCount);
}
System.out.println(appearances);
Thanks!
Edit: I forgot to add that I tried other test inputs and got crazy outputs. It would return numbers way higher than expected for some, and lower for others.

So now the problem is that .indexOf still returns the true index of "ea" in wordTwo - it doesn't take into account where you start from. Also, setting positionCount equal to where you find the word and then searching from that position again is just going to make you immediately find the same instance of that word, not the next one.
The index of the first instance of "ea" in wordTwo is 18, so wordTwoLength will be set to 32-18, or 14. Then you'll find the same instance of ea in wordTwo, and wordTwoLength will be set to 14-18, or -4. Then you'll exit the while loop, with appearances being 2.

for (int index = 0; (index = wordTwo.indexOf(wordOne, index)) > -1; index ++)
appearances ++;

Try this simpler code:
class Demo{
public static void main(String[] args){
String wordOne = "ea";
String wordTwo = "Ilikedthebestontheeastbeachleast";
String[] arr = wordTwo.split(wordOne);
int cnt = arr.length - 1;
System.out.printf("[%s] has occured for %s time(s) in [%s]", wordOne, cnt, wordTwo);
}
}

You can simplify your above work by "Converting String to Character array".Because it will be more Efficient(I think).I have provided a sample code here,
String wordOne="Ilikedthebestontheeastbeachleast";
String wordTwo="ea";
int count=0;
char[] arrayOne=wordOne.toCharArray();
char [] arrayTwo=wordTwo.toCharArray();
for(int i=0;i<=((arrayOne.length)-1);i++)
{
if(arrayTwo[0]==arrayOne[i]&&arrayTwo[1]==arrayOne[i+1])
count+=1;
}
System.out.println("Pattern found "+count+" times.");
This will suits your need but using For loop.

Related

NZEC error in Hackerearth problem in java

I'm trying the solve this hacker earth problem https://www.hackerearth.com/practice/basic-programming/input-output/basics-of-input-output/practice-problems/algorithm/anagrams-651/description/
I have tried searching through the internet but couldn't find the ideal solution to solve my problem
This is my code:
String a = new String();
String b = new String();
a = sc.nextLine();
b = sc.nextLine();
int t = sc.nextInt();
int check = 0;
int againCheck =0;
for (int k =0; k<t; k++)
{
for (int i =0; i<a.length(); i++)
{
char ch = a.charAt(i);
for (int j =0; j<b.length(); j++)
{
check =0;
if (ch != b.charAt(j))
{
check=1;
}
}
againCheck += check;
}
}
System.out.println(againCheck*againCheck);
I expect the output to be 4, but it is showing the "NZEC" error
Can anyone help me, please?
The requirements state1 that the input is a number (N) followed by 2 x N lines. Your code is reading two strings followed by a number. It is probably throwing an InputMismatchException when it attempts to parse the 3rd line of input as a number.
Hints:
It pays to read the requirements carefully.
Read this article on CodeChef about how to debug a NZEC: https://discuss.codechef.com/t/tutorial-how-to-debug-an-nzec-error/11221. It explains techniques such as catching exceptions in your code and printing out a Java stacktrace so that you can see what is going wrong.
1 - Admittedly, the requirements are not crystal clear. But in the sample input the first line is a number.
As I've written in other answers as well, it is best to write your code like this when submitting on sites:
def myFunction():
try:
#MY LOGIC HERE
except Exception as E:
print("ERROR Occurred : {}".format(E))
This will clearly show you what error you are facing in each test case. For a site like hacker earth, that has several input problems in various test cases, this is a must.
Coming to your question, NZEC stands for : NON ZERO EXIT CODE
This could mean any and everything from input error to server earthquake.
Regardless of hacker-whatsoever.com I am going to give two useful things:
An easier algorithm, so you can code it yourself, becuase your algorithm will not work as you expect;
A Java 8+ solution with totally a different algorithm, more complex but more efficient.
SIMPLE ALGORITM
In you solution you have a tipical double for that you use to check for if every char in a is also in b. That part is good but the rest is discardable. Try to implement this:
For each character of a find the first occurence of that character in b
If there is a match, remove that character from a and b.
The number of remaining characters in both strings is the number of deletes you have to perform to them to transform them to strings that have the same characters, aka anagrams. So, return the sum of the lenght of a and b.
NOTE: It is important that you keep track of what you already encountered: with your approach you would have counted the same character several times!
As you can see it's just pseudo code, of a naive algorithm. It's just to give you a hint to help you with your studying. In fact this algorithm has a max complexity of O(n^2) (because of the nested loop), which is generally bad. Now, a better solution.
BETTER SOLUTION
My algorithm is just O(n). It works this way:
I build a map. (If you don't know what is it, to put it simple it's a data structure to store couples "key-value".) In this case the keys are characters, and the values are integer counters binded to the respective character.
Everytime a character is found in a its counter increases by 1;
Everytime a character is found in b its counter decreases by 1;
Now every counter represents the diffences between number of times its character is present in a and b. So, the sum of the absolute values of the counters is the solution!
To implement it actually add an entry to map whenever I find a character for the first time, instead of pre-costructing a map with the whole alphabet. I also abused with lambda expressions, so to give you a very different sight.
Here's the code:
import java.util.HashMap;
public class HackerEarthProblemSolver {
private static final String a = //your input string
b = //your input string
static int sum = 0; //the result, must be static because lambda
public static void main (String[] args){
HashMap<Character,Integer> map = new HashMap<>(); //creating the map
for (char c: a.toCharArray()){ //for each character in a
map.computeIfPresent(c, (k,i) -> i+1); //+1 to its counter
map.computeIfAbsent(c , k -> 1); //initialize its counter to 1 (0+1)
}
for (char c: b.toCharArray()){ //for each character in b
map.computeIfPresent(c, (k,i) -> i-1); //-1 to its counter
map.computeIfAbsent(c , k -> -1); //initialize its counter to -1 (0-1)
}
map.forEach((k,i) -> sum += Math.abs(i) ); //summing the absolute values of the counters
System.out.println(sum)
}
}
Basically both solutions just counts how many letters the two strings have in common, but with different approach.
Hope I helped!

Error in swapping characters in stringbuffer object

i am trying to sort a string in the alphabetical order, however i am facing an error in the line :
sb.charAt(j)=sb.charAt(j+1);
where the compiler shows an error as expected variable; found value
the rest of the code is as follows :
import java.util.Scanner;
class a
{
public static void main(String[] agrs)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
StringBuffer sb = new StringBuffer();
sb.append(s);
for(int i = 0; i< s.length(); i++)
{
for(int j = 0; j<s.length(); j++)
{
if(s.charAt(j)>s.charAt(j+1)){
char temp = s.charAt(j);
sb.charAt(j)=sb.charAt(j+1);
sb.charAt(j+1)=temp;
}
}
}}}
kindly help me out as i'm a beginner and i cannot figure out why this issue is occurring , thank you .
This looks like a homework assignment where the goal is to sort the characters of a text being entered, so if you enter gfedbca the result should be abcdefg.
You already got a comment telling you what the problem is: StringBuffer#charAt() is not returning a reference to StringBuffer's internal array that you can change the value of. Dependent on the actual assignment you can call StringBuffers setCharAt method or you can go another approach by converting the text to sort to a char array and do the sorting in there. There are actually helper-classes in the JVM, that do that for you, have a look e.g. at the class java.util.Arrays
As already answered by many, the issue is in charAt(index) you are using, as this returns the character at the given index rather than setting a char at the index position.
My answer is to divert your approach of sorting. For simpler solutions, where smaller data sets (like your problem) are used, you should use the predefined sorting algorithms, like Insertion Sort
You may get help for the algo from here: http://www.geeksforgeeks.org/insertion-sort/
StringBuffer's charAt returns just the value of the char at the index, if you want to swap two chars you need to use setter for that, so you possible want to do somtehing like:
for(int j = 0; j < s.length() - 1; j++) {
if(s.charAt(j) > s.charAt(j + 1)) {
char temp = s.charAt(j);
sb.setCharAt(j, sb.charAt(j + 1));
sb.setCharAt(j + 1, temp);
}
}
This method can only return values and can not set values, I guess you might want to use this method:
setCharAt()
It can meet your requirement

Java: Unknown number of 'for' loops [duplicate]

This question already has answers here:
Generating all permutations of a given string
(57 answers)
Closed 7 years ago.
I want to make a program that would un-jumble some words.
I need to try all possible combinations of the words that can be formed, and then check if it is contained in a String variable, named dict.
My code is:
public class UnJumble
{
public static void main(String args[])
{
String dict = "cat, rat, mat dog, let, den, pen, tag, art,";
String t = "tra";
int l = t.length();
for(int i=0; i<l; i++)
{
char a=t.charAt(i);
t = t.replaceFirst(a+"","");
l--;
for(int j=0; j<l; j++)
{
char b = t.charAt(j);
t = t.replaceFirst(b+"","");
l--;
for(int k=0; k<l; k++)
{
char c = t.charAt(k);
if(dict.contains(""+a+b+c+","))
{
System.out.println("\'"+a+b+c+"\' found.");
break;
}
}
l++;
t = new StringBuilder(t).insert(j,b+"").toString();
}
t = new StringBuilder(t).insert(i,a+"").toString();
l++;
}
}
}
The variable t contains the word to be un-jumbled.
With this code, the output is:
'rat' found.
'art' found.
I think that I would need as many for loops as there as characters in the String t.
But I want to make it able to un-jumble words of an unknown length. So how can I achieve this?
I have tried searching on the Internet, and on SO. I found some answers on SO that are written in other programming languages which I don't understand.
You should look for recursive methods.
For example, given a string str of n characters, you can write a function that basicaly do this :
List<String> compute(String str)
// TODO : Handle case where str has only 1 character
List<String> list = compute(str.substring(0,n-2))
// TODO : Compute all combinations of str[n-1] with list
return list;
I guess this can be improved a lot in some cases.
There is a tricky way to do this without a for loop for each letter in your variable t, but it's code-intensive.
You can set up a loop that counts in base n, where n is the length of t. Assume i is your counter: Each pass through that loop you use the individual digits in i as indices into t, then build a ' word' and test that word against your dictionary. You are using i two different ways: as a counter and as a set of digits that represent indices into your t.
For example, if your t has three letters then you want to count in base 3 like this: 012, 020, 021, 022, 100, 101, 110,111, and so forth. Now the logic needs to verify that your combination of digits is unique so you don't use a letter twice when you build a word.
It's a lot of work but the algorithm is correct. The benefit is that it works for strings of any length.
I know I will be voted down, but oh well.

startsWith(String) method and arrays

I have to take a string and convert the string to piglatin. There are three rules to piglatin, one of them being:
if the english word starts with a vowel return the english word + "yay" for the piglatin version.
So i tried doing this honestly expecting to get an error because the startsWith() method takes a string for parameters and not an array.
public String pigLatinize(String p){
if(pigLatRules(p) == 0){
return p + "yay";
}
}
public int pigLatRules(String r){
String vowel[] = {"a","e","i","o","u","A","E","I","O","U"};
if(r.startsWith(vowel)){
return 0;
}
}
but if i can't use an array i'd have to do something like this
if(r.startsWith("a")||r.startsWith("A")....);
return 0;
and test for every single vowel not including y which would take up a very large amount of space, and just personally I would think it would look rather messy.
As i write this i'm thinking of somehow testing it through iteration.
String vowel[] = new String[10];
for(i = 0; i<vowel[]; i++){
if(r.startsWith(vowel[i]){
return 0;
}
I don't know if that attempt at iteration even makes sense though.
Your code:
String vowel[] = new String[10];
for(i = 0; i<vowel[]; i++){
if(r.startsWith(vowel[i]){
return 0;
}
}
Is actually really close to a solution that should work (assuming you actually put some values in the array).
What values do you need to put in it, well as you mentioned you can populate the array with all the possible values for vowels. Those of course being
String[] vowel={"a","A","e","E","i","I","o","O","u","U"};
now you have this you would want to loop (as you worked out) over the array and do your check:
public int pigLatRules(String r){
final String[] vowels={"a","A","e","E","i","I","o","O","u","U"};
for(int i = 0; i< vowels.length; i++){
if(r.startsWith(vowels[i])){
return 0;
}
}
return 1;
}
There are some improvements you can make to this though. Some are best practice some are just choice, some are performance.
As for a best practice, You are currently returning an int from this function. You would be best to change the result of this function to be a boolean value (I recommend looking them up if you have not encountered them).
As for a choice you say you do not like having to have an array with the upercase and lowercase vowels in. Well here is a little bit of information. Strings have lots of methods on them http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/String.html one of them is toLowerCase() which as you can guess lowercases a whole string. if you do this to the work you pass in to your function, you cut the amount of checks you need to do in half.
There is lots more you cam get into but this is just a little bit.
Put all those characters in a HashSet and then just perform a lookup to see if the character is valid or not and return 0 accordingly.
Please go through some example on HashSet insert/lookup. It should be straightforward.
Hope this helps.
Put all the vowels in a string, grab the first char in the word you are testing and just see if your char is in the string of all vowels.

Programming java to a symmetrical word [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Programming java to determine a symmetrical word
am new here, but I am having hard time figuring out how to write a code to determine an input of word and see if the first is matching with the end of the word. You may input abba and get answer it's evenly symmetric and aba is oddly symmetric.
Please show me how:(
Just two main things.
first I want to know if it's oddly or evenly amount of letter(number of letter divided by 2,if it's ending with 0.5, it's oddly symmetric, if is an integer it's evenly symmetric.
second I want to get (i.e 1=n,2=n-1,3=n-2...) position of the letter in the word to be the main idea of the execution.If there is a last letter in the oddly symmetric word, ignore the last remaining letter.
I appreciate any headstart or idea:) Thanks!
Thanks KDiTraglia, I made the code and compiled and here is what I put. I am not getting any further.
Reported problem:
Exception in thread "main" java.lang.Error: Unresolved compilation problems: reverse cannot be resolved or is not a field reverse cannot be resolved or is not a field Syntax error, insert ") Statement" to complete IfStatement
This is what i got from, KDiTraglia's help
public class WordSymmetric {
public static void main(String[] args) {
String word = "abccdccba";
if ( (word.length() % 2) == 1 ) {
System.out.println("They are oddly symmetric");
//odd
}
else {
System.out.println("They are evenly symmetric");
//even
}
int halfLength = word.length() / 2;
String firstHalf = word.substring(0, halfLength);
String secondHalf = word.substring(halfLength, word.length());
System.out.println(secondHalf.reverse());
if (firstHalf.equals(secondHalf.reverse()) {
System.out.println("They match");
//they match
}
} }
String does not have a reverse method. You could use the apache commons lang library for this purpose:
http://commons.apache.org/lang/api-release/org/apache/commons/lang3/StringUtils.html#reverse%28java.lang.String%29
The reverse() approach is very clean and readable. Unfortunately there is no reverse() method for Strings. So you would either have to take an external library (StringUtils from the appache common lang3 library has a reverse method) or code it yourself.
public static String reverse(String inputString) {
StringBuilder reverseString = new StringBuilder();
for(int i = inputString.length(); i > 0; --i) {
char result = inputString.charAt(i-1);
reverseString.append(result);
}
return reverseString.toString();
}
(This only works for characters that can fit into a char. So if you need something more general, you would have to expand it.)
Then you can just have a method like this:
enum ePalindromResult { NO_PALINDROM, PALINDROM_ODD, PALINDROM_EVEN };
public static ePalindromResult checkForPalindrom(String inputStr) {
// this uses the org.apache.commons.lang3.StringUtils class:
if (inputStr.equals(StringUtils.reverse(inputStr)) {
if (inputStr.length % 2 == 0) return PALINDROM_EVEN;
else return PALINDROM_ODD;
} else return NO_PALINDROM;
}
System.out.println(secondHalf.reverse());
There is no reverse() method defined fro String
I would probably loop over word from index 0 to the half (word.length() / 2) and compare the character at the current index (word.charAt(i)) with the correspoding from the other half (word.charAt(word.length() - i).
This is just a rough draft, you probably need to think about the loop end index, depending on oddly or evenly symmetry.
You can adapt this :
final char[] word = "abccdccba".toCharArray(); // work also with "abccccba"
final int t = word.length;
boolean ok = true;
for (int i = t / 2; i > 0; i--) {
if (word[i - 1] != word[t - i]) {
ok = false;
break;
}
System.out.println(word[i - 1] + "\t" + word[word.length - i]);
}
System.out.println(ok);
Console :
c c
c c
b b
a a
true
Use class StringBuffer instead of String

Categories