Error in swapping characters in stringbuffer object - java

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

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!

I cannot print value of converted string

I want to reverse a string. I know there are some other methods to do it but I wanted to do in a different way. There is no error but no output when I run my code. I dont understand why "String.valueOf(word.charAt(i)" doesnt return a value? Am I missing something?
String word = "myword";
for (int i = word.length(); i <= 0; i--) {
System.out.print(String.valueOf(word.charAt(i)));
}
The first value of i is out of index. And I also fixed your code. Check below:
String word = "myword";
for(int i=word.length()-1;i>=0;i--){
System.out.print(String.valueOf(word.charAt(i)));}
Just for providing another slightly different solution:
You can use a StringBuilder to reverse a String using its method reverse().
If you have a String, you can use it to initialize the StringBuilder with it and directly reverse it.
This example additionally uses an enhanced for-loop, which always goes through all of the elements. Using that, you can get rid of checking the length of a String and you won't have to use an int i for iterating.
For your requirements, this is a suitable option because you want to reverse the whole String.
String word = "myword";
for (char c : new StringBuilder(word).reverse().toString().toCharArray()) {
System.out.println(c);
}
Note that you can use the reverse() method for printing the reversed word in one line just doing
System.out.println(new StringBuilder(word).reverse().toString());
Your code has 2 issues.
i should be initialized with word.length()-1. Other wise you will get StringIndexOutOfBoundsException
for loop condition should be >= 0.
Below is the corrected code.
String word = "myword";
for(int i=word.length()-1;i>=0;i--) {
System.out.print(word.charAt(i));
}

Why is the second code more efficient than the first one?

I am confused between two codes, why the second one I am going to give here is more efficient than the first one.
Both of the codes just reverse a String, but first code is slower than the other and I am not able to understand why.
The first code is:
String reverse1(String s) {
String answer = "";
for(int j = s.length() - 1; j >= 0; j--) {
answer += s.charAt(j);
}
return answer;
}
The second code is:
String reverse2(String s) {
char answer[] = new char[s.length()];
for(int j = s.length() - 1; j >= 0; j--) {
answer[s.length() - j - 1] = s.charAt(j);
}
return new String(answer);
}
And I'm not able to understand how the second code is more efficient than the first one, I'd appreciate any insight on this.
The first code declares
String answer;
Strings are immutable. Therefore, every append operation reallocates the entire string, copies it, then copies in the new character.
The second code declares
char answer[];
Arrays are mutable, so each iteration copies only a single character. The final string is created once, not once per iteration of the loop.
Your question is perhaps difficult to answer exactly, in part because the answer would depend on the actual implementation of the first version. This, in turn, would depend on what version of Java you are using, and what the compiler decided to do.
Assuming that the compiler keeps the first version verbatim as you wrote it, then yes, the first version might be more inefficient, because it would require allocating a new string for each step in the reversal process. The second version, on the contrary, just maintains a single array of characters.
However, if the compiler is smart enough to use a StringBuilder, then the answer changes. Consider the following first version:
String reverse1(String s) {
StringBuilder answer = new StringBuilder();
for (int j = s.length() - 1; j >= 0; j--)
answer.append(s.charAt(j));
return answer;
}
Under the hood, StringBuilder is implemented using a character array. So calling StringBuilder#append is somewhat similar to the second version, i.e. it just adds new characters to the end of the buffer.
So, if your first version executes using literal String, then it is more inefficient than the second version, but using StringBuilder it might be on par with the second version.
String is immutable. Whenever you do answer += s.charAt(j); it creates a new object. Try printing GC logs using -XX:+PrintGCDetails and see if the latency is caused by minor GC.
String object is immutable and every time you made an add operation you create another object, allocating space and so on, so it's quite inefficient when you need to concatenate many strings.
Your char array method fits your specific need well, but if you need more generic string concatenation support, you could consider StringBuilder
In this code you are creating a new String object in each loop iteration,because String is immutable class
String reverse1(String s) {
String answer = "";
for (int j = s.length() - 1; j >= 0; j--)
answer += s.charAt(j);
return answer;
}
In this code you have already allocated memory to char array,Your code will create only single String at last line, so it is more efficient
String reverse2(String s) {
char answer[] = new char[s.length()];
for (int j = s.length() - 1; j >= 0; j--)
answer[s.length() - j - 1] = s.charAt(j);
return new String(answer);
}
Why is the second code more efficient than the first one?
String is immuable, by answer += s.charAt(j); you are creating a new instance of String in each loop, which makes your code slow.
Instead of String, you are suggested to use StringBuilder in a single thread context, for both performance and readablity(might be a little slower than fix-sized char array but has a better readablity):
String reverse1(String s) {
StringBuilder answer = new StringBuilder("");
for (int j = s.length() - 1; j >= 0; j--)
answer.append(s.charAt(j));
return answer.toString();
}
The JVM treats strings as immutable. Hence, every time you append to the existing string, you are actually create a new string! This means that a new string object has to be created in heap for every loop iteration. Creating an object and maintaining its lifecycle has its overhead. Add to that the garbage collection of the discarded strings (the string created in the previous iteration won't have a reference to it in the next, and hence, it is collected by the JVM).
You should consider using a StringBuilder. I ran some tests and the time taken by the StringBuilder code is not much smaller than that of the fixed-length array.
There are some nuances to how the JVM treats strings. There are things like string interning that the JVM does so that it does not have to create a new object for multiple strings with the same content. You might want to look into that.

Determining if a given string of words has words greater than 5 letters long

So, I'm in need of help on my homework assignment. Here's the question:
Write a static method, getBigWords, that gets a String parameter and returns an array whose elements are the words in the parameter that contain more than 5 letters. (A word is defined as a contiguous sequence of letters.) So, given a String like "There are 87,000,000 people in Canada", getBigWords would return an array of two elements, "people" and "Canada".
What I have so far:
public static getBigWords(String sentence)
{
String[] a = new String;
String[] split = sentence.split("\\s");
for(int i = 0; i < split.length; i++)
{
if(split[i].length => 5)
{
a.add(split[i]);
}
}
return a;
}
I don't want an answer, just a means to guide me in the right direction. I'm a novice at programming, so it's difficult for me to figure out what exactly I'm doing wrong.
EDIT:
I've now modified my method to:
public static String[] getBigWords(String sentence)
{
ArrayList<String> result = new ArrayList<String>();
String[] split = sentence.split("\\s+");
for(int i = 0; i < split.length; i++)
{
if(split[i].length() > 5)
{
if(split[i].matches("[a-zA-Z]+"))
{
result.add(split[i]);
}
}
}
return result.toArray(new String[0]);
}
It prints out the results I want, but the online software I use to turn in the assignment, still says I'm doing something wrong. More specifically, it states:
Edith de Stance states:
⇒     You might want to use: +=
⇒     You might want to use: ==
⇒     You might want to use: +
not really sure what that means....
The main problem is that you can't have an array that makes itself bigger as you add elements.
You have 2 options:
ArrayList (basically a variable-length array).
Make an array guaranteed to be bigger.
Also, some notes:
The definition of an array needs to look like:
int size = ...; // V- note the square brackets here
String[] a = new String[size];
Arrays don't have an add method, you need to keep track of the index yourself.
You're currently only splitting on spaces, so 87,000,000 will also match. You could validate the string manually to ensure it consists of only letters.
It's >=, not =>.
I believe the function needs to return an array:
public static String[] getBigWords(String sentence)
It actually needs to return something:
return result.toArray(new String[0]);
rather than
return null;
The "You might want to use" suggestions points to that you might have to process the array character by character.
First, try and print out all the elements in your split array. Remember, you do only want you look at words. So, examine if this is the case by printing out each element of the split array inside your for loop. (I'm suspecting you will get a false positive at the moment)
Also, you need to revisit your books on arrays in Java. You can not dynamically add elements to an array. So, you will need a different data structure to be able to use an add() method. An ArrayList of Strings would help you here.
split your string on bases of white space, it will return an array. You can check the length of each word by iterating on that array.
you can split string though this way myString.split("\\s+");
Try this...
public static String[] getBigWords(String sentence)
{
java.util.ArrayList<String> result = new java.util.ArrayList<String>();
String[] split = sentence.split("\\s+");
for(int i = 0; i < split.length; i++)
{
if(split[i].length() > 5)
{
if(split[i].matches("[a-zA-Z]+"))
{
result.add(split[i]);
}
if (split[i].matches("[a-zA-Z]+,"))
{
String temp = "";
for(int j = 0; j < split[i].length(); j++)
{
if((split[i].charAt(j))!=((char)','))
{
temp += split[i].charAt(j);
//System.out.print(split[i].charAt(j) + "|");
}
}
result.add(temp);
}
}
}
return result.toArray(new String[0]);
}
Whet you have done is correct but you can't you add method in array. You should set like a[position]= spilt[i]; if you want to ignore number then check by Float.isNumber() method.
Your logic is valid, but you have some syntax issues. If you are not using an IDE like Eclipse that shows you syntax errors, try commenting out lines to pinpoint which ones are syntactically incorrect. I want to also tell you that once an array is created its length cannot change. Hopefully that sets you off in the right directions.
Apart from syntax errors at String array declaration should be like new String[n]
and add method will not be there in Array hence you should use like
a[i] = split[i];
You need to add another condition along with length condition to check that the given word have all letters this can be done in 2 ways
first way is to use Character.isLetter() method and second way is create regular expression
to check string have only letter. google it for regular expression and use matcher to match like the below
Pattern pattern=Pattern.compile();
Matcher matcher=pattern.matcher();
Final point is use another counter (let say j=0) to store output values and increment this counter as and when you store string in the array.
a[j++] = split[i];
I would use a string tokenizer (string tokenizer class in java)
Iterate through each entry and if the string length is more than 4 (or whatever you need) add to the array you are returning.
You said no code, so... (This is like 5 lines of code)

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.

Categories