Rot13 Java what's wrong? [duplicate] - java

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 4 years ago.
I have been trying to find my own way of making a Rot13 algorithm in java, but when I try a phrase, it gives me this error:
java.lang.ArrayIndexOutOfBoundsException: 41
So this is my code:
:Update with whole names,
public class Rot13
{
char[] translated;
String abc = "abcdefghijklmnopjrstuvwxyzabcdefghijklmnopqrstuvwxyz";
public String ROT13(String input){
input = input.toLowerCase();
char[] sentence = input.toCharArray();
char[] ABC = abc.toCharArray();
int x = input.length();
int y = 0;
char[] translated = new char[x];
for(int i = 0; i<x;i++){
int z = 0;
if(sentence[i] == ' '){
translated[i] = ' ';
}
else {
while(y==0){
if (sentence[i] == ABC[z]){
y =1;
}
else{
z += 1;
}
}
translated[i] = ABC[z+12];
}
}
String rot13string = new String(translated);
return rot13string;
}
}
: Update 2
I just tested this version again and it translates the it. But in the wrong way, for example, "Hello" becomes "tmmmm" The first letter seems to be right but then the next ones are always 'm'.
Update 3: Thanks for your answers guys, here is my final code, I just duplicated my alphabet a "few" times. :
public class ROT13
{
char[] translated;
String ab = "abcdefghijklmnopjrstuvwxyzabcdefghijklmnopqrstuvwxyz";
String abc = String.format("%0" + 1000 + "d", 0).replace("0",ab);
public String ROT13(String input){
input = input.toLowerCase();
char[] sentence = input.toCharArray();
char[] ABC = abc.toCharArray();
int length = input.length();
char[] translated = new char[length];
for(int i = 0; i<length;i++){
int y = 0;
int h = 0;
if(sentence[i] == ' '){
translated[i] = ' ';
}
else {
while(y==0){
int z = 0;
if (sentence[i] == ABC[h]){
y +=1;
}
else{
z += 1;
h += 1;
}
}
translated[i] = ABC[h+13];
}
}
String rot13string = new String(translated);
return rot13string;
}
}

Currently, think about what happens when there is a 'z' in the sentence. Then, you make     t[i] = ABC[z (26) + 12] //which is larger than ABC's length.
Personally, I would do rot13 like so:
public char rot13(char s){
if (c >= 'a' && c <= 'm') return c += 13;
else if (c >= 'A' && c <= 'M') return c += 13;
else if (c >= 'n' && c <= 'z') return c -= 13;
else if (c >= 'N' && c <= 'Z') return c -= 13;
else return c;
}

Related

How to add 0 in front of every single digit string?

How can I add 0 in front of every single digit number? I mean 1 to 01 etc.
I have tried to add ifs like
if(c >='A' && c<= 'I')
str = "0"+str;
but it just adds 0 in front of everything like abcd converts to 00001234 not 01020304.
This is my code.
String A[] = new String[size];
for (int i = 0; i < size; i++) {
A[i] = jList1.getModel().getElementAt(i);
String[] Text = A[i].split("");
String s = jList1.getModel().getElementAt(i);
String str = ("");
for (int z = 0; z < Text.length; z++) {
for (int y = 0; y < Text[z].length(); y = y + 1) {
char c = s.charAt(z);
if (c >= 'A' && c <= 'Z') {
str += c - 'A' + 1;
} else if (c >= 'a' && c <= 'z') {
str += c - 'a' + 1;
} else {
str += c;
}
}
str = str + "";
}
}
This Worked for me
public String addZero(int number)
{
return number<=9?"0"+number:String.valueOf(number);
}``
One way to do this would be to use a StringJoiner with Java 8:
String s = "abcdABCD";
s = s.chars()
.mapToObj(i -> Integer.toString((i >= 'a' && i <= 'z' ? i - 'a' : i - 'A') + 1))
.collect(Collectors.joining("0", "0", "")));
System.out.println(s);
>> 0102030401020304
String str = "abcd-zzz-AAA";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char ch = str.toLowerCase().charAt(i);
if (ch >= 'a' && ch <= 'z') {
sb.append('0');
sb.append(ch - 'a' + 1);
} else {
sb.append(ch);
}
}
Result: abcd-zzz-AAA -> 01020304-026026026-010101
Final fix :-)
use String#chars to get a stream of its characters, then for each one do the manipulation you want.
public class Example {
public static void main(String[] args) {
String s = "aBcd1xYz";
s.chars().forEach(c -> {
if (c >= 'a' && c <= 'z')
System.out.print("0" + (c - 'a' + 1));
else if (c >= 'A' && c <= 'Z')
System.out.print("0" + (c - 'A' + 1));
else
System.out.print(c);
});
}
}
Ouput:
0102030449024025026
You can add zero in front of single digit number using String.format.
System.out.println(String.format("%02d",1));
System.out.println(String.format("%02d",999));
The first line will print 01, second line prints 999 no zero padding on the left.
Padding zero with length of 2 and d represents integer.
I hope this helps.

why isn't this caesarian shift working

private static String shift(String p, int shift){
String s = "";
int len = p.length();
for(int x = 0; x < len; x++){
char c = (char)(p.charAt(x) + shift);
if (c == ' '){ // this right here isn't working
s += " ";
} else if (c > 'z'){
s += (char)(p.charAt(x) - (26-shift));
}
else {
s += (char)(p.charAt(x) + shift);
}
}
return s;
}
example output: qer$hyhi ( the "$" used to be a space ). Why doesn't the space simply stay a space like it should? instead it still follows the conversion process.
The problem is that you are comparing the already shifted character to space.
There are several ways to fix this bug, one of them is the following (fixing some other minor issues):
private static String shift(String p, int shift){
StringBuilder s = new StringBuilder(); //better using a mutable object than creating a new string in each iteration
int len = p.length();
for(int x = 0; x < len; x++){
char c = p.charAt(x); //no need for casting
if (c != ' '){ // this should work now
c += shift;
if (c > 'z'){ //we assume c is in the 'a-z' range, ignoring 'A-Z'
c -= 'z';
}
}
s.append(c);
}
return s.toString();
}

How to find number of distinct characters in a string

I have to count the number of distinct characters alphabet in the string, so in this case the count will be - 3 (d, k and s).
Given the following String:
String input;
input = "223d323dk2388s";
count(input);
My Code :
public int count(String string) {
int count=0;
String character = string;
ArrayList<Character> distinct= new ArrayList<>();
for(int i=0;i<character.length();i++){
char temp = character.charAt(i);
int j=0;
for( j=0;j<distinct.size();j++){
if(temp!=distinct.get(j)){
break;
}
}
if(!(j==distinct.size())){
distinct.add(temp);
}
}
return distinct.size();
}
Output : 3
Are there any native libraries which return me the number of characters present in that string ?
With java 8 it is much easy. You could use something like this
return string.chars().distinct().count();
One way is to maintain an array and then fill it up and get the total. This checks for all characters including special characters and numbers.
boolean []chars = new boolean[256];
String s = "223d323dk2388s";
for (int i = 0; i < s.length(); ++i) {
chars[s.charAt(i)] = true;
}
int count = 0;
for (int i = 0; i < chars.length; ++i) {
if (chars[i]) count++;
}
System.out.println(count);
Here's an alternative if you want to calculate the count only of letters, not including numbers and special symbols. Note that capital and small alphabets are different.
boolean []chars = new boolean[56];
String s = "223d323dk2388szZ";
for (int i = 0; i < s.length(); ++i) {
char ch = s.charAt(i);
if (ch >=65 && ch <= 90) {
chars[ch - 'A'] = true;
} else if (ch >= 97 && ch <= 122) {
chars[ch - 'a' + 26] = true; //If you don't want to differentiate capital and small differently, don't add 26
}
}
int count = 0;
for (int i = 0; i < chars.length; ++i) {
if (chars[i]) count++;
}
System.out.println(count);
Another way of doing it is using a Set.
String s = "223d323dk2388s";
Set<Character> set = new HashSet<Character>();
for (int i = 0; i < s.length(); ++i) {
set.add(s.charAt(i));
}
System.out.println(set.size());
If you don't want numbers and special symbols.
String s = "223d323dk2388s";
Set<Character> set = new HashSet<Character>();
for (int i = 0; i < s.length(); ++i){
char ch = s.charAt(i);
if ((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122))
set.add(s.charAt(i));
}
System.out.println(set.size());
String s="InputString";
String p="";
char ch[]=s.toCharArray();
for(int i=0;i<s.length();i++)
{
for(int j=i+1;j<s.length();j++)
{
if(ch[i]==ch[j])
{
ch[j]=' ';
}
}
p=p+ch[i];
p = p.replaceAll("\\s","");
}
System.out.println(p.length());
To those coming here looking for a solution in Kotlin:
val countOfDistinctCharacters = string.toCharArray().distinct().size

Evaluate a Math Expression given in string form without using API

I want to evaluate an expression like -4-12-2*12-3-4*5 given in a String form without using API as I am a beginner and want to grasp the logic.
Given below is my unsuccessful attempt to this problem which, if you may like, ignore and suggest appropriate logic.And of course your codes are also welcome :-)
public class SolveExpression3 {
static String testcase1 = "-4-12-2*12-3-4*5";
public static void main(String args[]){
SolveExpression3 testInstance= new SolveExpression3();
int result = testInstance.solve(testcase1);
System.out.println("Result is : "+result);
}
public int solve(String str){
int sum = 1;
int num1 = 0;
int num2 = 0;
String num = "";
int len = str.length();
System.out.println(str);
for (int i = len-1 ; i >= 0; i--)
{
char ch = str.charAt(i);
if(ch == '*')
{
String s = "";
num1 = num2 = 0;
//to get the number on left of *
for (int j = i; j >= 0; j--)
{
char c = str.charAt(j);
if(c == '+' || c == '-' || j == 1)
{
num1 = stringToInt(s);
s = "";
break;
}
else
{
s = c + s;
}
}
//to get the number on right of *
for (int j = i; j <= len; j++)
{
char c = str.charAt(j);
if(c == '+' || c == '-' || j == len-1)
{
num2 = stringToInt(s);
s = "";
break;
}
else
{
s = c + s;
}
}
sum = sum + num1*num2;
}
else
{
num = ch + num;
}
}
len = str.length();
for (int i = len-1; i >= 0; i--)
{
char ch = str.charAt(i);
if(ch==' ')
{}
else if(ch=='+')
{
sum = sum + stringToInt(num);
num = "";
}
else if(ch=='-')
{
sum = sum - stringToInt(num);
num = "";
}
else
{
num = ch + num;
}
}
return sum;
}
public int stringToInt(String str)
{
int number=0;
for(int i = 0; i < str.length(); i++)
{
int num = str.charAt(i) - 48;
number = number*10+num;
}
return number;
}
}
found=true;
static String testcase1 = "-4-12-2*12-3-4*5";
Pattern SEGMENT_PATTERN = Pattern.compile("(\\d+(\\.\\d+)?|\\D+)");
/*\\d-means digit,
\\.-point,
+-one or more times,
?-optional and
\\D-non digit ch*/
Matcher matcher = SEGMENT_PATTERN.matcher(testcase1);
while (found) {
boolean Found = matcher.find();
String segment = matcher.group();//representing a number or an operator
if (Character.isDigit(segment.toCharArray()[0])) {
//is digit
}
else {
//is operator
}
}
This a a solution using a patter to determine if you have a number or and operator,u just have to adapt it a little to your case to computing the result.
You can add all the matches found to an array list than traverse it and test the operators and computer the result.
It works for floating numbers too,ex:"it matches 5.10".
I would suggest a different logic for your purpose.
Usually the logic behind programs algorithms is not different from the logic that you will apply if you have to do the task by hand.
For an expression like your example you would usually do:
Find all the *
For each * compute the result of the operation
Repeat steps 1 and 2 for + and -
Try to implement a recursive descent parser, a tutorial depicting how a calculator can be implemented (in Python but the same concepts apply to java) can be found here http://blog.erezsh.com/how-to-write-a-calculator-in-70-python-lines-by-writing-a-recursive-descent-parser/

Evaluate Polynomial String without using regex and API

Given a polynomial with a single variable x, and the value of x as input, compute its value. Examples:
eval("-2x^3+10x-4x^2","3")=-60
eval("x^3+x^2+x","6")=258
Description of issue: In this code I break the string into a substring whenever a +/- is encountered and pass the substring to a function which evaluates single term like "-2x^3". So my code for input = "-2x^3+10x-4x^2" calculates till "-2x^3+10x" only and skips "-4x^2" part.
Can anyone please tell me whats wrong here?
public class EvalPolyX2 {
static String testcase1 = "-2x^3+10x-4x^2";
static String testcase2 = "3";
public static void main(String args[]){
EvalPolyX2 testInstance = new EvalPolyX2();
int result = testInstance.eval(testcase1,testcase2);
System.out.println("Result : "+result);
}
public int eval(String str,String valx){
int sum = 0;
String subStr = "";
if(str.charAt(0) == '-')
{
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i);
len = str.length();
i = 0;
}
}
}
else if(str.charAt(0) != '-')
{
str = '+' + str;
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i);
len = str.length();
i=0;
}
}
}
return sum;
}
public int evalSubPoly(String poly,String valx){
int len = poly.length();
String num = "";
String power = "";
int exp = 0, coeff = 0;
for(int i = 0; i < len; i++)
{
if(poly.charAt(i) == 'x')
{
num = poly.substring(0, i);
coeff = Integer.parseInt(num);
}
if(poly.charAt(i) == '^')
{
power = poly.substring(i+1, len);
exp = Integer.parseInt(power);
}
}
if(power.equals(""))
exp = 1;
System.out.println("coeff="+coeff);
int sum = 1;
int x = Integer.parseInt(valx);
for (int i = 0; i < exp; i++)
{
sum = sum*x;
}
System.out.println("sum="+sum);
sum = sum*coeff;
return sum;
}
}
What's wrong with using regex? You can split the polynomial into monomials, evaluate each, and add all of the results.
private static final Pattern monomial = Pattern
.compile("([+-])?(\\d+)?x(?:\\^(\\d+))?");
public static int eval(String str, String valx) {
Matcher m = monomial.matcher(str);
int x = Integer.parseInt(valx);
int total = 0;
while (m.find()) {
String mul = m.group(2);
int value = (mul == null) ? 1 : Integer.parseInt(m.group(2));
String pow = m.group(3);
value *= (pow == null) ? x : (int) Math.pow(x,
Integer.parseInt(pow));
if ("-".equals(m.group(1)))
value = -value;
total += value;
}
return total;
}
System.out.println(eval("-2x^3+10x-4x^2", "3"));
System.out.println(eval("x^3+x^2+x", "6"));
-60
258
This code replacement should help
if(str.charAt(i) == '-' || str.charAt(i) == '+' || i == (len - 1))
{
if(i == len - 1)
{
i++;
}
...
Though there could be better ways, but I only wanted to show a way out here.
The reason is you are looking for + or - as the delimiter.
But the last part of the expression will not end with either of these but just probably EOL
You need to account for the last term (the if-statement will only trigger when a - or + is found, which there isn't at the end).
One easy way to do this is to replace:
for (int i = 0; i < len; i++)
{
if (str.charAt(i) == '-' || str.charAt(i) == '+')
with:
// v one more iteration
for (int i = 0; i <= len; i++)
{
if (i == len || str.charAt(i) == '-' || str.charAt(i) == '+')
// \------/
// extra condition
The above simply goes on for one more iteration and, on that iteration, always goes into the if-statement, causing the last term to be processed.
You can also simplify
if (str.charAt(0) == '-')
{
// common code
}
else if (str.charAt(0) != '-')
{
str = '+' + str;
// common code
}
To:
if (str.charAt(0) != '-')
{
str = '+' + str;
}
// common code
There's also a bug with handling +. I get a NumberFormatException for this. One way to handle it is to ignore the + between the terms (and not adding a + to the start):
if (i != len && str.charAt(i) == '+')
str = str.substring(i+1);
else
str = str.substring(i);
And you might as well make your functions static and call them directly rather than declaring a new instance of your class.
Test.
The simple answer is that when you do this:
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
the effect is that you're setting subStr to text just before the - or +, and evaluating it. But since there's no - or + at the end of the string, there's no way this logic will evaluate the last term of the polynomial, since it only evaluates substrings that are right before a - or +.
P.S. That's just one problem I noticed. I don't know if the rest of the logic is correct.
When you parse the string, you look for +/- and only stop if you find them. This works for the first two terms, but when you get down to "-4x^2" the loop won't stop because there is no +/-. So in addition to the conditions you have, you need to add code so that when the end of the string is reached, what you have left is the last term. So what you want to have is this
if(str.charAt(0) == '-')
{
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i+1);
len = str.length();
i = 0;
}
}
System.out.println("subStr="+str);
sum += evalSubPoly(str, valx);
}
else if(str.charAt(0) != '-')
{
str = '+' + str;
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i+1);
len = str.length();
i=0;
}
}
System.out.println("subStr="+str);
sum += evalSubPoly(str, valx);
}
I will also throw out the disclaimer that there may be more errors, but this is the major one causing your problem.
EDIT: added change to else if statement and added change mentioned in my comment above
With regular expressions, you can get a more simple solution. And, do you want support for simple constants? Try the next:
public class EvalPolyX2 {
public static void main(String args[]) {
System.out.println("Result: " + eval("x^3+x^2+x", 6));
}
public static int eval(String eq, int val) {
int result = 0;
String mons[] = eq.split("(?=[+-])(?!\\B)");
for (String str : mons) {
str = str.replace("+", "");
if (str.contains("x")) {
double a = 1, b = 1;
String[] comps = str.split("x\\^?");
if (comps.length > 0) {
a = comps[0].isEmpty() ? 1 : Integer.parseInt(comps[0]);
}
if (comps.length > 1) {
b = Integer.parseInt(comps[1]);
}
result += a * Math.pow(val, b);
} else {
result += Integer.parseInt(str);
}
}
return result;
}
}

Categories

Resources