I'm trying to remove the last char in the string using substring method.
Outside the if statement works normally. But inside it just goes through the if statement and returns original String.
public String getElkon(int p, int zbytek) {
System.out.println(zbytek);
for (int i = 0; i < p; i++) {
vysledek += elkon[i];
vysledek += " ";
System.out.println(vysledek);
}
***if(zbytek != 0){
vysledek = vysledek.substring(0, vysledek.length() - 1);
return vysledek;
}
else{
return vysledek;
}***
}
Your code would be more straightforward if you didn't have to trim the trailing space from appending your String(s). Also, it isn't clear why you expect zbytek to control the trim. I think you wanted if (p != 0) (since that is your loop sentinel). I would use a StringJoiner to implement this like
public String getElkon(int p, int zbytek) {
System.out.println(zbytek);
StringJoiner sj = new StringJoiner(" ");
for (int i = 0; i < p; i++) {
sj.append(elkon[i]);
}
return sj.toString();
}
The last character in the string is a space, since you added it last time in the for loop.
To trim the last space before if statement you could use the code
public String getElkon(int p, int zbytek) {
System.out.println(zbytek);
for (int i = 0; i < p; i++) {
vysledek += elkon[i];
vysledek += " ";
System.out.println(vysledek);
}
if (p > 0)
vysledek = vysledek.substring(0, vysledek.length() - 1);
if(zbytek != 0){
...
}
return vysledek;
}
Related
I am working on this simple program that adds two polynomials. However, I am getting wrong results and could not spot the mistake.
import java.util.LinkedList;
public class Polynomial {
private LinkedList<Term> terms = new LinkedList<Term>();
private class Term {
private int coef;
private int exp;
public Term(int coef, int exp) {
this.coef = coef;
this.exp = exp;
}
public int getCoef() {
return coef;
}
public int getExp() {
return exp;
}
public String toString() {
return (this.coef + "x^" + this.exp);
}
}
public String addPoly(String first, String second) {
LinkedList<Term> otherTerms = new LinkedList<Term>();
String result = "";
String [] termsArray1 = first.split(";");
String [] termsArray2 = second.split(";");
for (int i = 0; i < termsArray1.length; i++) {
String [] temp = termsArray1[i].split("x\\^");
int currentCoef = Integer.parseInt(temp[0]);
int currentExp = Integer.parseInt(temp[1]);
Term currentTerm = new Term(currentCoef, currentExp);
terms.add(currentTerm);
}
for (int i = 0; i < termsArray2.length; i++) {
String [] temp = termsArray2[i].split("x\\^");
int currentCoef = Integer.parseInt(temp[0]);
int currentExp = Integer.parseInt(temp[1]);
Term currentTerm = new Term(currentCoef, currentExp);
otherTerms.add(currentTerm);
}
int i = 0;
int j = 0;
while (true){
if(i == terms.size() || j == otherTerms.size()) {
break;
}
if(terms.get(i).getExp() < otherTerms.get(j).getExp()) {
result += (otherTerms.get(j).toString() + ";");
j++;
}
if(terms.get(i).getExp() > otherTerms.get(j).getExp()) {
result += (terms.get(i).toString() + ";");
i++;
}
if(terms.get(i).getExp() == otherTerms.get(j).getExp()) {
Term temp = new Term((terms.get(i).getCoef() + otherTerms.get(j).getCoef()), terms.get(i).getExp());
result += (temp.toString() + ";");
i++;
j++;
}
}
result = result.substring(0, result.length()-1);
return result;
}
}
::Test::
String s3 = "5x^2;-4x^1;3x^0";
String s4 = "6x^4;-1x^3;3x^2";
Polynomial p = new Polynomial();
System.out.println(p.addPoly(s4, s3));
Expected result: 6x^4;-1x^3;7x^2;-4x^1;3x^0
Actual result: 3x^4;7x^2;-1x^1;10x^0
The problem is that when your loop exits, one of the following can still be true:
i < terms.size()
j < j == otherTerms.size()
And this is the case with your example input. This means that part of one of the terms has not been processed and integrated into the output.
A second problem is that your multiple if statements are not exclusive; after the first if block is executed and j++ has executed, it might well be that j is an invalid index in otherTerms when the second if is evaluated. This should be avoided by turning the second and third if into else if.
Here is a fix for that loop:
while (i < terms.size() || j < otherTerms.size()) {
if(i == terms.size() || j < otherTerms.size() && terms.get(i).getExp() < otherTerms.get(j).getExp()) {
result += (otherTerms.get(j).toString() + ";");
j++;
}
else if(j == otherTerms.size() || i < terms.size() && terms.get(i).getExp() > otherTerms.get(j).getExp()) {
result += (terms.get(i).toString() + ";");
i++;
}
else if(terms.get(i).getExp() == otherTerms.get(j).getExp()) {
Term temp = new Term((terms.get(i).getCoef() + otherTerms.get(j).getCoef()), terms.get(i).getExp());
result += (temp.toString() + ";");
i++;
j++;
}
}
Better approach
Your approach is not really OOP. Ideally, the first expression should serve to create one instance of Polynomial and the other expression should serve to create another instance of Polynomial. Then there should be a method that can add another Polynomial instance to the own instance. Finally there should be a toString method that returns the instance as a string in the required format. Your driver code would then look like this:
Polynomial a = new Polynomial("5x^2;-4x^1;3x^0");
Polynomial b = new Polynomial("6x^4;-1x^3;3x^2");
Polynomial sum = a.addPoly(b);
System.out.println(sum.toString());
This is much more object oriented, and will automatically avoid the code repetition that you currently have.
I have been given a task to create a class that given a String will create a palindrome with minimum number of assertions.
Example Runs:
Input: 123333
Output: 12333321
Input: 789
Output: 78987
Input: 1221
Output: 1221221
**Note a Palindrome should NOT return the same Palindrome.
I tried using a modified KMP algorithm as stated here.
I revert the string and compare it to the reverse + original string and then add the mismatches to the original string.
However my function only works for inputs with trailing digits (first example input) however an input like 1234 will return 1234123, '92837465' will return '928374659283746'
public static int[] computelps(String sample){
int[] lps = new int[sample.length()];
lps[0] = 0;
int i = 1;
int len = 0; // length of previous longest prefix suffix
while (i < sample.length()) {
if (sample.charAt(i) == sample.charAt(len)) {
len++;
lps[i] = len;
i++;
}
else
{
if (len != 0) {
len = lps[len - 1];
}
else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
public static void Solution(File samplefile) throws Exception {
BufferedReader br = new BufferedReader(new FileReader(samplefile));
String firstline = br.readLine();
String line;
while ((line = br.readLine()) != null) {
String reverse_str = "";
String newline = line.replace(".", "");
for (int i = newline.length() - 1; i >= 0; i--) {
reverse_str += newline.charAt(i);
}
int [] lps = computelps(reverse_str); // computes the lps of the pattern string
String tot = reverse_str + newline;
// KMP Algorithm modified.
int x = 0; // index for total_string(tot)
int y = 0; // index for pattern
String palindrome = newline;
while (x < tot.length()){
if(reverse_str.charAt(y) == tot.charAt(x)){
y++;
x++;
}
if(y == reverse_str.length()) {
y = lps[y - 1];
}
else if( x < tot.length() && (reverse_str.charAt(y) != tot.charAt(x))){
palindrome += tot.charAt(x);
if ( y!= 0){
y = lps[y-1];
}
else{
x += 1;
}
}
}
System.out.println(palindrome);
}
}
I would appreciate any help. I find algorithms very challenging so please bear with me if my approach or code is sub-par.
*I fixed sample inputs and outputs as well as added my results.
It helps to split this problem in smaller problems, implement a separate method for each and check to see if each method works as expected. What will really help you will be to learn to use the debugger in your Ide. But until you do that you can test that each part of your code works as expected. So I simplified a little your code and split it up :
public static void main(String[] args){
System.out.println("computelps " + ("[0, 0, 0, 0]".equals(Arrays.toString(computelps("4321"))) ? "works" : "doesn't work" ));
System.out.println("reverse " + ("4321".equals(reverse("1234")) ? "works" : "doesn't work" ));
System.out.println("Solution " + ("1234321".equals(Solution("1234")) ? "works" : "doesn't work" ));
}
public static int[] computelps(String sample){
int[] lps = new int[sample.length()];
lps[0] = 0;
int i = 1;
int len = 0; // length of previous longest prefix suffix
while (i < sample.length()) {
if (sample.charAt(i) == sample.charAt(len)) {
len++;
lps[i] = len;
i++;
}
else
{
if (len != 0) {
len = lps[len - 1];
}
else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
public static String Solution(String line) {
String newline = line.replace(".", "");
String reverse_str = reverse(newline);
int [] lps = computelps(reverse_str); // computes the lps of the pattern string
// KMP Algorithm modified.
return kpmModified(newline, reverse_str, lps);
}
private static String kpmModified(String newline, String reverse_str, int[] lps) {
int x = 0; // index for total_string(tot)
int y = 0; // index for pattern
String tot = reverse_str + newline;
String palindrome = newline;
while (x < tot.length()){
if(reverse_str.charAt(y) == tot.charAt(x)){
y++;
x++;
}
if(y == reverse_str.length()) {
y = lps[y - 1];
}
else if( x < tot.length() && (reverse_str.charAt(y) != tot.charAt(x))){
palindrome += tot.charAt(x);
if ( y!= 0){
y = lps[y-1];
}
else{
x += 1;
}
}
}
return palindrome;
}
private static String reverse(String newline) {
String reverse_str = "";
for (int i = newline.length() - 1; i >= 0; i--) {
reverse_str += newline.charAt(i);
}
return reverse_str;
}
And the result is
computelps works
reverse works
Solution doesn't work
So your bug is in kpmModified method. I can't spend more time and I'm not familiar with the algorithm but you should continue like this and figure our what part of that method has the bug.
I think you overthink the problem. The question is basically adding a string's reversed version back to it's original, but not every character, right? So you might need to find something like a pointer to tell the function where to start to reverse.
One example. Let the string be 12333. If we add every character from the index string.length() to 0, it will be 1233333321, which is not correct, since there are duplicated 3's. We need to ignore those, so we need to add characters from string.length() - numOfDuplicateAtEnd to 0.
public String palindromic(String num) {
int i = num.length() - 1;
while (i > -1 && num.charAt(i) == num.charAt(num.length() - 1))
i--;
for (int k = i; k > -1; --k)
num += num.substring(k, k + 1);
return num;
}
So I had to write a program that mimics a phone keypad, whereas it would convert a string of text to integers: abc(2), def(3), ghi(4), jkl(5), mno(6),
pqrs(7), tuv(8), wxyz(9). Except the output has to have hyphens(-) between the digits.
Example input: Alabama
Output: 2-5-2-2-2-6-2
But I just only output 2522262. How would I go about formatting this correctly?
public class Keypad {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter a string: ");
String s = sc.nextLine();
System.out.println(getNumbers(s));
}
public static String getNumbers(String s) {
String result = new String();
for (int i = 0; i < s.length(); i++) {
if (Character.isLetter(s.charAt(i))) {
result += getNumber(Character.toUpperCase(s.charAt(i)));
}
else {
result += s.charAt(i);
}
}
return result;
}
public static int getNumber(char upperCaseLetter) {
int number = ((upperCaseLetter - 'A') / 3) + 2;
if (number < 7) {
return number;
}
else if (upperCaseLetter - 'A' < 20) {
return 7;
}
else if (upperCaseLetter - 'A' < 23) {
return 8;
}
else {
return 9;
}
}
}
Go to the place you construct the result and add the hyphen:
result += getNumber(Character.toUpperCase(s.charAt(i)));
result += "-";
Then before you return you will have to strip off the last hyphen:
return result.substring(0, result.length() - 1);
So the whole method would look like this:
public static String getNumbers(String s) {
String result = new String();
for (int i = 0; i < s.length(); i++) {
if (Character.isLetter(s.charAt(i))) {
result += getNumber(Character.toUpperCase(s.charAt(i)));
result += "-";
}
else {
result += s.charAt(i);
}
}
return result.substring(0, result.length() - 1);
}
StringJoiner was added to Java 8 for this purpose. Very simple and straightforward to use:
StringJoiner sj = new StringJoiner("-", "", "");
sj.add("1").add("1").add("2");
String desiredString = sj.toString();
or with Stream API, which might be a little more convenient in your case:
List<Integer> integers = Arrays.asList(1,2,3,4,5);
String hyphenSeparatedNumbers = integers.stream()
.map(Object::toString)
.collect(Collectors.joining("-"));
Also String.join is a superb alternative for this task.
There is a method in Java 8 that does just this. Use String.join, docs, to add a dash after each character.
public static String getNumbers(String s) {
String result = new String();
for (int i = 0; i < s.length(); i++) {
if (Character.isLetter(s.charAt(i))) {
result += getNumber(Character.toUpperCase(s.charAt(i)));
}
else {
result += s.charAt(i);
}
}
return String.join("-", result.split("");
}
Note
You should try to avoid using the += with strings, StringBuffer provides better performance. When you concatenate strings you are actually creating new objects for each new string you are concatenating. Imagine a large loop you will have n objects to create the new string.
Change the code in getNumbers(String) to
for (int i = 0; i < s.length(); i++) {
if (Character.isLetter(s.charAt(i))) {
result += getNumber(Character.toUpperCase(s.charAt(i)));
if (i < (s.length-1)
result += '-";
}
}
return result;
}
In the last method I'm trying to call printPattern inside of a for loop, but I have no idea what I'm doing wrong. I'm using BlueJ, so I'm not sure if the code will be different in Eclipse.
Here's the program:
public class recursion
{
private int count;
private String printPattern(int count, int itterations)
{
int i;
String line= "";
for(i=0; i <= count; i++)
{
if (i > itterations)
{
line = line + i;
}
else {line = line + "*";}
}
line = line + reverseLine(line);
return line;
}
private String reverseLine (String line)
{
int size;
String linerev = "";
for (int i = line.length() - 1; i >= 0; i--)
{
linerev= linerev + line.charAt(i);
}
return linerev;
}
private void addLineandReverse (int n)
{
int w= n;
//for loop
//calls function print pattern
//add itteration ++
//prints out
for (n= 9; n <= printPattern; n++)
{
System.out.println();
}
}
}
Here is what I wish the output of the program to look like:
123456789987654321
*2345678998765432*
**34567899876543**
***456789987654***
****5678998765****
*****67899876*****
******789987******
*******8998*******
********99********
******************
You are using the function as limit for the stop condition of the for loop. But that seems wrong as I don't think the function is ment to return the result for a condition, it returns a string.
I'm not sure what you are trying to accomplish with calling the function. and why you are reassigning n to 9.
Either way to call the printPattern method you have to use this syntax:
printPattern(aNumber, anotherNumber)
Code that would work (but probably not output what you want) would be:
public void addLineandReverse (final int n)
{
//for loop
// calls function print pattern
// add itteration ++
//prints out
for (int i = 0; i <= n; ++n) {
System.out.println(printPattern(w, n));
}
}
Ok I took your requirements and adjusted your code and stayed as close as I could to your design (its not the design that I would take to tackle this problem but it works.
public class Recursion {
public static void main(String[] args) {
final Integer count = 9;
final Recursion recursion = new Recursion(count);
recursion.addLineAndReverse();
}
public Recursion(final Integer count) {
this.count = count;
}
private final int count;
public String printPattern(final int lineNumber) {
String line= "";
for(int i = 1; i <= count; ++i){
if (i >= lineNumber) {
line += i;
} else {
line += "*";
}
}
line += reverseLine(lineNumber);
return line;
}
public String reverseLine(final int lineNumber)
{
String line= "";
for(int i = count; i >= 1; --i){
if (i >= lineNumber) {
line += i;
} else {
line += "*";
}
}
return line;
}
public void addLineAndReverse(){
for (int i = 1; i <= count + 1; ++i){
System.out.println(printPattern(i));
}
}
}
Bro as per your description you are only calling by printPattern but function definition is String printPattern(int count, int itterations)
My for loop for my string compression is a bit off. I have been working on this assignment the past 5 days and I can't figure out for the life of me what is wrong. Can someone help me out?
For example, I passed over the string "TTTTrrrEe" and instead of getting T4r3Ee, I'm getting T4r3EeTT. I don't know why it jumps back to the beginning of the string like that, but I am getting closer.We can only use charAt,equals,length, and substring from the string class.
Can someone help guide me in the right direction by helping to correct my logic? I still want to try and code this myself, seeing as how it is an assignment.
public static String compress(String s){
int count = 0;
String temp = s.substring(0,1);
for(int i = 0; i < s.length(); i++){
if(i !=s.length()-1){
if(temp.equals(s.substring(i,i+1))){
count++;
}else{
if(count < 1){
System.out.print(s.substring(i,i+2));
System.out.print(temp.substring(0,1) );
}else{
System.out.print("" + temp.substring(0,1) + count);
i--;
temp = s.substring(count,count+1);
System.out.println(" temp is now " + temp);
count = 0;
//i--;
}
}
}
}
System.out.println(temp);
return temp;
}
Since this is a learning exercise, I wouldn't try fixing your code, just point out a few things to work on to get it right:
The if (i !=s.length()-1) condition inside the loop becomes unnecessary if you change your for loop condition to i < s.length()-1
Comparing individual characters is easier (and faster) than comparing substrings. You get a character at position i by calling char ch1 = s.charAt(i), and compare two characters using == operator, rather than calling equals() on them.
When count is zero (your count < 1 condition is equivalent to count == 0) you print both the current character and the character after it, in addition to the first character of temp followed by the count. This does not look correct.
Rather than growing temp as you go through the loop, you set it on each iteration. This does not look correct.
A better way of growing temp as you go through the loop is using StringBuilder and append(), instead of using a plain String, and performing concatenations.
Try using some logic like this;
int count = 0;
for(int i =0; i < string.length()-1; i++){
if(string.charAt(i) == string.charAt(i + 1)){
count++;
// DO SOME OPERATION
}
}
temp = s.substring(count,count+1); does not relate to a position (i), but a size.
In fact I would try to rewrite it afresh, with externally sensible names:
char repeatedChar = `\u0000`; // Not present.
int repetitions = 0;
Because of the no-namer count you got into trouble.
Working code:
public class HelloWorld {
public static void compress(String s){
StringBuilder buff = new StringBuilder();
char tmp = '\0';
int index = 1;
for(int i = 0; i < s.length(); i++){
char curr = s.charAt(i);
if(buff.length() == 0){
tmp = curr;
buff.append(tmp);
continue;
}
if(curr == tmp){
index++;
}
else{
if(index > 1){
buff.append(index);
index = 1;
tmp = curr;
}
buff.append(curr);
}
}
System.out.println(buff.toString());
}
public static void main(String args[]){
compress("TTTTrrrEe");
}
}
Output: T4r3Ee
For compress("TTsssssssssssTTrrrEe");
Output: T2s11T2r3Ee
String temp = s.substring(0,1);
temp.equals(s.substring(i,i+1))
In case of these 2 sentences you should have used a char instead of String, as such:
char temp = s.charAt(0)
temp == s.charAt(i)
I would start with 3 variables:
char lastCharacter = inputString.charAt(0);
int count = 1;
String result = "";
then proceed to process the input string in a loop:
if (length <= 1) return inputString;
for i = 1 ; i < length;i++
if (inputString.charAt(i) == lastCharacter && i != length-1)
count++
else
if count == 1
result += lastCharacter
else
result = result + lastCharacter + count;
count = 1;
end if
lastCharacter = inputString.charAt(i);
end if
end for
return result;
TRY THIS
public class Compress {
/**
* #param args
* #author Rakesh KR
*/
public static String encode(String source) {
StringBuffer dest = new StringBuffer();
for (int i = 0; i < source.length(); i++) {
int runLength = 1;
while (i+1 < source.length() && source.charAt(i) == source.charAt(i+1)) {
runLength++;
i++;
}
dest.append(source.charAt(i));
dest.append(runLength);
}
return dest.toString();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String example = "aaaaaaBBBBccc";
System.out.println("Encode::"+encode(example));
}
}