Shouldn't these two loops produce the same result? - java

I was solving a programming problem where you get an input and you have to add every number from 1 - input to the input for example lets say the input
is 5 :5+4+3+2+1 = 15.
To solve this I tried these two for loops below.
//This loop worked for most inputs
int input = 12 ;
for(int i = input - 1; i > 0; i--) {
input += i;
}
System.out.println(input);
//This just produced a negative number
int input2 = 12;
for(int i = 1; i < input2;i++){
input2 += i;
}
System.out.println(input2);
Only one loop worked although the seem like they should produce the same result can anyone explain?

Errors are pretty nicely defined in previous answers, I'm just going to add the following:
This could also be solved using ArrayList and summing its members with loop, but it would be an overkill.
That gives you ability to remove/change values of the list you iterating through using Java Iterator class.
As I said before, this solution is overkill for such task, but it could be interesting to research.
More of Java Iterator: https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html

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

Wrong output from a while loop using indexOf [duplicate]

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.

Executing code N times and other code N+1 times

The question is about while-loops in which I need some code to be executed N times and some other code N+1 times. NOT about concatening Strings, I just use this as bad-coded yet short example.
Let me explain my question by providing an example.
Say I want to concatenate N+1 Strings, by glueing them with "\n", for example. I will have N+1 lines of text then, but I only need to add N times "\n".
Is there any boilerplate solution for this type of loop in which you have to execute some code N times and other code N+1 times? I'm NOT asking for solution to concatenate Strings! That is just a (bad) example. I'm looking for the general solution.
The problem I have with this is code duplication, so to code my example I'll do this (bad pseudo code, I know I have to use StringBuilder etc.):
String[] lines = <some array of dimension N+1>;
String total = lines[0];
for (int i = 1; i < N + 1; i++){
total += "\n" + lines[i];
}
The problem becomes worse if the code that has to be executed N+1 times, becomes larger, of course. Then I would do something like
codeA(); // adding the line of text
for (int i = 1; i < N + 1; i++){
codeB(); // adding the "\n"
codeA();
}
To remove the duplication, you can do this different by checking inside the loop, too, but then I find this quite stupid as I know beforehand that the check is pre-determined, as it will only be false the first iteration:
for (int i = 0; i < N + 1; i++){
if (i > 0){
codeB(); // adding the "\n"
}
codeA();
}
Is there any solution for this, a sort of while-loop that initializes once with codeA() en then keeps looping over codeB() and codeA()?
People must have run into this before, I guess. Just wondering if there are any beautiful solutions for this.
To my dissapointment, I believe that there is no such construct that satisfies the conditions as you have stated them and I will attempt to explain why (though I can't prove it in a strictly mathematical way).
The requirements of the problem are:
We have two parts of code: codeA() and codeB()
The two parts are executed a different number of times, N and N+1
We want to avoid adding a condition inside the loop
We want to execute each part only as many times as strictly necessary
2) is a direct consequence of 1). If we didn't have two parts of code we would not need a different number of executions. We would have a single loop body.
4) is again a consequence of 1). There is no redundant execution if we have a single loop body. We can control its execution through the loop's condition
So the restrictions are basically 1) and 3).
Now inside the loop we need to answer two questions on each iteration: a) do we execute codeA()? and b) do we execute codeB()? We simply do not have enough information to decide since we only have a single condition (the condition of the loop) and that condition will be used to decide if both of the code parts would be executed or not.
So we need to break 1) and/or 3) Either we add the extra condition inside the loop or we delegate the decision to some other code (thus not having two parts anymore).
Apparently an example of delegation could be (I am using the string concatenation example):
String [] lines = ...
for (int i = 0; i < N; i++){
// delegate to a utility class LineBuilder (perhaps an extension of StringBuilder) to concatenate lines
// this class would still need to check a condition e.g. for the first line to skip the "\n"
// since we have delegated the decisions we do not have two code parts inside the loop
lineBuilder.addLine( lines[i] );
}
Now a more interesting case of delegation would be if we could delegate the decision to the data itself (this might worth keeping in mind). Example:
List<Line> lines = Arrays.asList(
new FirstLine("Every"), // note this class is different
new Line("word"),
new Line("on"),
new Line("separate"),
new Line("line") );
StringBuffer sb = new StringBuffer();
for (Line l : lines) {
// Again the decision is delegated. Data knows how to print itself
// Line would return: "\n" + s
// FirstLine would return: s
sb.append( l.getPrintVersion() );
}
Of course all of the above does not mean that you couldn't implement a class that tries to solve the problem. I believe though this is beyond the scope of your original question not to mention that would be an overkill for simple loops
Concatenating Strings like this is a bad idea and a much bigger issue IMHO.
However to answer your question I would do
String sep = "";
StringBuilder sb= new StringBuilder();
for(String s: lines) {
sb.append(sep).append(s);
sep = "\n";
}
String all = sb.toString();
Note: there is usually a good way to avoid needing to create this String at all such a processing the lines as you get them. It is hard to say without more context.
This kind of thing is fairly common, like when you build sql. This is the pattern that I follow:
String[] lines ...//init somehow;
String total = lines[0];
boolean firstTime = true;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++){
if(firstTime) firstTime = false;
else sb.append('\n');
sb.append(lines[i]);
}
Note that this is not the same, as the first example and here is why:
String[] lines = <some array of dimension N+1>;
String total = lines[0];
for (int i = 1; i < N + 1; i++){
total += "\n" + lines[i];
}
Assuming you have an array of [0] = 'line1' and [1] = 'line2'
Here you end up with line1line2\n, when the desired output is:
line1\nline2.
The example I provided is clear, and does not perform poorly. In fact a much bigger performance gain is made by utilizing StringBuilder/Buffer. Having clear code is essential for the pro.
Personally i have most of the time the same problem, on the String example i use the StringBuilder as you said, and just delete the characters added to much:
StringBuilder sb = new StringBuilder();
for(int i=0; i<N; i++) {
sb.append(array[i]).append("\n");
}
sb.delete(sb.length-1, sb.length); // maybe check if sb contains something
In the common case i suppose there is no other way than adding the if you suggested. To make the code more clear i would check at the end of the for loop:
StringBuilder sb = new StringBuilder();
for(int i=0; i<N; i++) {
sb.append(array[i]);
if(i < N) {
sb.append("\n");
}
}
But i totally agree this is sad to have this double logic

Arrays not matching correctly

userAnswer[] holds the string of the answer the user types in and is comparing it to answers[] to see if they match up and then spits out correct or wrong. j is equal to the question number. So if j was question 6, answers[j] should refer to answers[6] right?
Then userAnswer[6] should compare to answers[6] and match if its correct. But its giving me wrong answers and displaying the answer I typed as correct.
int abc, loopCount = 100;
int j = quesNum, overValue, forLoop = 100;
for (int loop = 1; loop < loopCount; loop++)
{
aa = r.nextInt(10+1);
abc = (int) aa;
String[] userAnswer = new String[x];
JOptionPane.showMessageDialog(null,abc);
if(abc < x)
{
userAnswer[j] = JOptionPane.showInputDialog(null,"Question "+quesNum+"\n"+questions[abc]+"\n\nA: "+a[abc]+"\nB: "+b[abc]+"\nC: "+c[abc]+"\nD: "+d[abc]);
if(userAnswer[j].equals(answers[j]))
{
JOptionPane.showMessageDialog(null,"Correct. \nThe Correct Answer is "+answers[abc]);
}
else
{
JOptionPane.showMessageDialog(null,"Wrong. \n The Correct Answer is "+answers[abc]);
}//else
}//if
}//for
Your indices are named poorly, and you mix them up yourself. You want to check answers[abc] and not answers[j] against userAnswer[j].
For question 6 you need answers[5] because arrays are indexed starting from 0. 0 would be question 1, 1 would be question 2, etc.
Your userAnswer array is scoped by the for loop. If you mean to use the values outside of this loop, you need to move the defintion outside of the loop. Otherwise, you can just use one answer string as right now you are not accessing the values a second time.

Categories