JAVA index problems while doing caesar cipher - java

GOAL OF CODE :(using netbeans)
I was trying to write this code to apply the caesar cipher algorithm where multiple keys can be used in order e.g : key = [1,2,3] , text = test , where it will use key as "1" on "t" then key "2" on "e" then key "3" on "s" then return to key "1" on last t .
OUTPUT :
run:
Enter the text : mohammad rahmat
Enter the number of keys you want to use : 3
Enter 3 number of keys : 1
2
3
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at caesar.Caesar.main(Caesar.java:68)
nqkbopbfbsckncw
Java Result: 1
BUILD SUCCESSFUL (total time: 9 seconds)
CODE :
package caesar;
import java.util.Scanner;
public class Caesar {
/**
* #param args the command line arguments
*/
static Scanner input = new Scanner(System.in);
public static void main(String[] args) {
// TODO code application logic here
char table[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t',
'u','v','w','x','y','z',' ','.'};
String tmp;
System.out.print("Enter the text : ");
tmp = input.nextLine();
char text[] = tmp.toCharArray();
System.out.print("Enter the number of keys you want to use : ");
int keyNo = input.nextInt();
int key[] = new int[keyNo];
System.out.printf("Enter %d number of keys : ",keyNo);
for (int i = 0; i < keyNo; ++i){
key[i] = input.nextInt();
}
char entext[] = new char[text.length];
int k = 0;
int a = 0;
int count = 0;
while (k < text.length){
int j = 0;
while (text[a] != table[j])
j++;
if (key[count]+j >= table.length){
entext[a] = table[(j+key[count])%table.length];
}
else entext[a] = table[j+key[count]];
a++;
count++;
if (count == keyNo)
count = 0;
k++;
}
String answer = new String(entext);
System.out.printf("ENCRYPTION : %s \n\n",answer);
char detext[] = new char[text.length];
k = 0;
a = 0;
count = 0;
while (k < text.length){
int j = 0;
while (text[a] != table[j])
j++;
if (key[count]-j < 0){
detext[a] = table[table.length+(key[count]-j)];
}
else detext[a] = table[j-key[count]];
a++;
count++;
if (count == keyNo)
count = 0;
k++;
}
String answer2 = new String(detext);
System.out.printf("DECRYPTION : %s\n\n",answer2);
}
}

you should use a debugger to analyze your code.
detext[a] = table[table.length+(key[count]-j)];
you're incrementing j and subtracting it from count which is zero. increment count before you operate on finding finding array index.

i found it finally , while converting it back to original text I had to take the converted text , in other words :
replace
while (k < text.length){
int j = 0;
while (text[a] != table[j])
with
while (k < entext.length){
int j = 0;
while (entext[a] != table[j])

Related

Generate all possible string combinations by replacing the hidden “#” number sign

My task is to generates all possible combinations of that rows without the hidden # number sign. The input is XOXX#OO#XO and here is the example of what the output should be:
XOXXOOOOXO
XOXXOOOXXO
XOXXXOOOXO
XOXXXOOXXO
I am only allowed to solve this solution iteratively and I am not sure how to fix this and have been working on this code for a week now.
Here is my code:
import java.lang.Math;
public class help {
public static void main(String[] args) {
String str = new String("XOXX#OO#XO");
UnHide(str);
}
public static void UnHide(String str) {
//converting string to char
char[] chArr = str.toCharArray();
//finding all combinations for XO
char[] xo = new char[]{'X', 'O'};
int count = 0;
char perm = 0;
String s = "";
//finding amount of times '#' appears in string
for (int i = 0; i < str.length(); i++) {
if (chArr[i] == '#')
count++;
}
int[] combo = new int[count];
int pMax = xo.length;
while (combo[0] < pMax) {
// print the current permutation
for (int k = 0; k < count; k++) {
//print each character
//System.out.print(xo[combo[i]]);
perm = xo[combo[k]];
s = String.valueOf(perm);
char[] xoArr = s.toCharArray();
String strChar = new String(xoArr);
//substituting '#' to XO combo
for (int i = 0; i < chArr.length; i++) {
for (int j = 0; j < s.length(); j++) {
if (chArr[i] == '#') {
chArr[i] = xoArr[j];
strChar = String.copyValueOf(chArr);
i++;
}
}
i++;
if (i == chArr.length - 1) {
System.out.println(strChar);
i = 0;
}
}
}
System.out.println(); //print end of line
// increment combo
combo[count - 1]++; // increment the last index
//// if increment overflows
for (int i = count - 1; combo[i] == pMax && i > 0; i--) {
combo[i - 1]++; // increment previous index
combo[i] = 0; // set current index to zero
}
}
}
}
Since your input has 2 #'s, there are 2n = 4 permutations.
If you count from 0 to 3, and look at the numbers in binary, you get 00, 01, 10, and 11, so if you use that, inserting O for 0 and X for 1, you can do this using simple loops.
public static void unHide(String str) {
int count = 0;
for (int i = 0; i < str.length(); i++)
if (str.charAt(i) == '#')
count++;
if (count > 30)
throw new IllegalArgumentException("Too many #'s found. " + count + " > 30");
char[] buf = str.toCharArray();
for (int permutation = 0, end = 1 << count; permutation < end; permutation++) {
for (int i = buf.length - 1, bit = 0; i >= 0; i--)
if (str.charAt(i) == '#')
buf[i] = "OX".charAt(permutation >>> bit++ & 1);
System.out.println(buf);
}
}
Test
unHide("XOXX#OO#XO");
Output
XOXXOOOOXO
XOXXOOOXXO
XOXXXOOOXO
XOXXXOOXXO
You can iteratively generate all possible combinations of strings using streams as follows:
public static String[] unHide(String str) {
// an array of substrings around a 'number sign'
String[] arr = str.split("#", -1);
// an array of possible combinations
return IntStream
// iterate over array indices
.range(0, arr.length)
// append each substring with possible
// combinations, except the last one
// return Stream<String[]>
.mapToObj(i -> i < arr.length - 1 ?
new String[]{arr[i] + "O", arr[i] + "X"} :
new String[]{arr[i]})
// reduce stream of arrays to a single array
// by sequentially multiplying array pairs
.reduce((arr1, arr2) -> Arrays.stream(arr1)
.flatMap(str1 -> Arrays.stream(arr2)
.map(str2 -> str1 + str2))
.toArray(String[]::new))
.orElse(null);
}
// output to the markdown table
public static void main(String[] args) {
String[] tests = {"XOXX#OOXO", "XOXX#OO#XO", "#XOXX#OOXO#", "XO#XX#OO#XO"};
String header = String.join("</pre> | <pre>", tests);
String matrices = Arrays.stream(tests)
.map(test -> unHide(test))
.map(arr -> String.join("<br>", arr))
.collect(Collectors.joining("</pre> | <pre>"));
System.out.println("| <pre>" + header + "</pre> |");
System.out.println("|---|---|---|---|");
System.out.println("| <pre>" + matrices + "</pre> |");
}
XOXX#OOXO
XOXX#OO#XO
#XOXX#OOXO#
XO#XX#OO#XO
XOXXOOOXOXOXXXOOXO
XOXXOOOOXOXOXXOOOXXOXOXXXOOOXOXOXXXOOXXO
OXOXXOOOXOOOXOXXOOOXOXOXOXXXOOXOOOXOXXXOOXOXXXOXXOOOXOOXXOXXOOOXOXXXOXXXOOXOOXXOXXXOOXOX
XOOXXOOOOXOXOOXXOOOXXOXOOXXXOOOXOXOOXXXOOXXOXOXXXOOOOXOXOXXXOOOXXOXOXXXXOOOXOXOXXXXOOXXO
The process would probably be best to calculate the number of permutations, then loop through each to define what combination of characters to use.
For that, we'll have to divide the permutation number by some value related to the index of the character we're replacing, which will serve as the index of the character to swap it to.
public static void test(String word) {
// Should be defined in class (outside method)
String[] replaceChars = {"O", "X"};
char replCharacter = '#';
String temp;
int charIndex;
int numReplaceable = 0;
// Count the number of chars to replace
for (char c : word.toCharArray())
if (c == replCharacter)
numReplaceable++;
int totalPermutations = (int) Math.pow(replaceChars.length, numReplaceable);
// For all permutations:
for (int permNum = 0; permNum < totalPermutations; permNum++) {
temp = word;
// For each replacement character in the word:
for (int n = 0; n < numReplaceable; n++) {
// Calculate the character to swap the nth replacement char to
charIndex = permNum / (int) (Math.pow(replaceChars.length, n))
% replaceChars.length;
temp = temp.replaceFirst(
replCharacter + "", replaceChars[charIndex]);
}
System.out.println(temp);
}
}
Which can produces:
java Test "#TEST#"
OTESTO
XTESTO
OTESTX
XTESTX
This can also be used with any number of characters, just add more to replaceChars.

How do I count the characters in a string and then sort them alphabetically?

I am taking input from the user. I have that bit done. The input can be a word or even a sentence saved as a string. What I want to do is then count the number of times the letters appear in the input, and also have it sorted alphabetically.
Example input:
learning to program
Example output:
a 2
e 1
g 2
i 1
How to count occurences in a string is explained here:
https://stackoverflow.com/a/881111/8935250
I tried to mimic your example output in this code fiddle.
Methods I used:
Sort
Map
const string = "learning to program"
function count(character) {
return string.split(character).length
}
map = string.split("").map(c => {
return {c, count: count(c)}
})
map.sort((a,b) => b.count - a.count)
console.log(map)
console.log(string.split("").sort((a,b) => string.split(b).length - string.split(a).length))
should also do the job but does not show the occurrences.
I wrote some code for you which should do the trick :)
String name = "doodleice";
HashMap<Character, Integer> charMap = new HashMap<>();
char[] charArray = name.toCharArray();
for(int i = 0; i < charArray.length; i++){
if(charMap.containsKey(charArray[i])){
charMap.put(charArray[i], charMap.get(charArray[i]) + 1);
}
else{
charMap.put(charArray[i], 1);
}
}
ArrayList<Character> charList = new ArrayList<>();
for(Map.Entry<Character, Integer> entry: charMap.entrySet()){
charList.add(entry.getKey());
}
Collections.sort(charList);
for(int i = 0; i < charList.size(); i++){
System.out.println(charList.get(i) + " " + charMap.get(charList.get(i)));
}
One of the Simple solution for sorted String "aabbbcddeeee" then output: a2b3c1d2e4
public static void main(String[] args) {
String input = "aabbbcddeeee"; // output: a2b3c1d2e4
int count = 0;
int i = 0;
int k = 0;
for (i = 0; i < input.length(); i++) {
for (int j = i; j < input.length(); j++) {
if (input.charAt(i) == input.charAt(j)) {
count = count + 1;
k++;
} else
break;
}
System.out.print(input.charAt(i));
System.out.print(count+"\n");
i = k - 1;
count = 0; // reset counter
}
}
How about this;
const test ="the quick brown fox jumps over the lazy dog";
const letterMap = {};
[...test].forEach(x=>{letterMap[x]?letterMap[x]++:(letterMap[x]=1)});
console.log (Object.keys(letterMap).sort().map((key) => [key, letterMap[key]]));
Output;
[[" ",8],["a",1],["b",1],["c",1],["d",1],["e",3],["f",1],["g",1],["h",2],["i",1],["j",1],["k",1],["l",1],["m",1],["n",1],["o",4],["p",1],["q",1],["r",2],["s",1],["t",2],["u",2],["v",1],["w",1],["x",1],["y",1],["z",1]]

Maximum Integer Value java

I was trying to solve the Maximum Integer Value problem form Geeksforgeeks.
The problem states the following:
Given a string S of digits(0-9), your task is to find the maximum value that can be obtained from the string by putting either '*' or '+' operators in between the digits while traversing from left to right of the string and picking up a single digit at a time.
Input:
The first line of input contains T denoting the number of testcases. T testcases follow. Each testcase contains one line of input denoting the string.
Output:
For each testcase, print the maximum value obtained.
this is what I did:
class GFG
{
public static void sort(int[] numbers)
{
int n = numbers.length;
for (int i = 1; i < n; ++i)
{
int key = numbers[i];
int j = i - 1;
while (j >= 0 && numbers[j] > key)
{
numbers[j + 1] = numbers[j];
j = j -1 ;
}
numbers[j + 1] = key;
}
System.out.println(numbers.length - 1);
}
public static void main (String[] args)
{
Scanner sc = new Scanner(System.in);
int testCases = sc.nextInt();
int [] maxNum;
for(int i = 0; i< testCases; i++)
{
String numbers = sc.nextLine();
char[] cNumbers = numbers.toCharArray();
maxNum = new int [cNumbers.length];
for(int j = 0; j + 1 < cNumbers.length; j++)
{
int sum = 0;
int mult = 0;
sum = cNumbers[j] + cNumbers[j + 1];
mult = cNumbers[j] * cNumbers[j + 1];
int maxNumber = Math.max(sum, mult);
maxNum[i] = maxNumber;
}
sort(maxNum);
}
}
}
an example of Input:
2
01230
891
My Output:
-1
4
Correct Output:
9
73
What is wrong with my code?!
Just quick glance it would seem if your digit is less than two it should be added. 2 or larger should get multiplied. Not at a PC to test though.
The idea is to put the operators alternatively and choose the maximum results.
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int testCases = Integer.parseInt(sc.nextLine());
for (int i = 0; i < testCases; i++) {
String numbers = sc.nextLine();
int max = 0;
for (int j = 0; j + 1 < numbers.length(); j++) {
int next = Integer.parseInt(numbers.substring(j, j+1));
if (max + next > max * next)
max = max + next;
else
max = max * next;
}
System.out.println(max);
}
sc.close();
}
}
After the execution of
int testCases = sc.nextInt();
the buffer contains a new line character. So when executing the line
String numbers = sc.nextLine();
it read '\n' into numbers, so you got -1 as the first output.
Also you need to convert character to Integer before using it any arithmetic operations.
sum = cNumbers[j] + cNumbers[j+1];
mult = cNumbers[j] * cNumbers[j+1];
So the above code will give you wrong results.
I tried the following sample and worked.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String inputAsString = sc.nextLine();
int testCases = Integer.parseInt(inputAsString);
int maxNumber = 0;
for (int i = 0; i < testCases; i++) {
String numbers = sc.nextLine();
if(!numbers.matches("\\d+")){
System.out.println("Only numeric values are expected.");
continue;
}
char[] cNumbers = numbers.toCharArray();
int sum = 0;
int mult = 1;
for (int j = 0; j < cNumbers.length; j++) {
int nextNumber = Character.getNumericValue(cNumbers[j]);
sum = sum + nextNumber;
mult = mult * nextNumber;
maxNumber = mult > sum ? mult : sum;
sum = maxNumber;
mult = maxNumber;
}
System.out.println(maxNumber);
}
sc.close();
}
I read your description and what you do is wrong. please read question carefully specially the example in reference site.
as mentioned in comments by moilejter you use sc.nextInt() which doesn't read '\n' and make problem. the next sc.nextLine() will read only a empty string and your program throw exception.
Second problem is that you must calculate max continuously and you don't need an int array (you calculate max result of operation between two successive number and save them in an array which is not correspond to max integer value. you only find max between each two digit but not max of operation on all digit).
Third problem is that you use character as numbers which is made incorrect result. (you must convert them to integer)
So there is a code that works for your output:
public class GFG
{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int testCases = Integer.valueOf(sc.nextLine());
for (int i = 0; i < testCases; i++)
{
String numbers = sc.nextLine();
char[] cNumbers = numbers.toCharArray();
long maxUntilNow = cNumbers[0] - '0';
for (int j = 1; j < cNumbers.length; j++)
{
int numberOfThisPlace = cNumbers[j] - '0';
maxUntilNow = Math.max(maxUntilNow + numberOfThisPlace,
maxUntilNow * numberOfThisPlace);
}
System.out.println(maxUntilNow);
}
}
}
I hope this is what you want.
As per the problem statement, we need to obtain maximum value from the string by putting either * or + operators in between the digits while traversing from left to right of the string and picking up a single digit at a time.
So, this can be solved in O(n) without using any sorting algorithm.
The simple logic behind the solution is whenever you find "0" or "1" in any of the operands use "+" and the rest of the places use "*".
Here is my solution which got successfully submitted:
import java.util.*;
import java.lang.*;
import java.io.*;
class GFG {
public static void main (String[] args) {
Scanner scan = new Scanner(System.in);
int T = Integer.parseInt(scan.nextLine());
while(T-- > 0) {
String str = scan.nextLine();
maxValue(str);
}
}
static void maxValue(String str) {
long maxNumber = 0;
for(int i = 0; i < str.length(); i++) {
int n = Character.getNumericValue(str.charAt(i));
if (maxNumber == 0 || maxNumber == 1 ||
n == 0 || n == 1) {
maxNumber += n;
} else {
maxNumber *= n;
}
}
System.out.println(maxNumber);
}
}

How can I get the longest increasing subsequence in a string?

I'm pretty rusty on my Java skills but I was trying to write a program that prompts the user to enter a string and displays a maximum length increasing ordered subsequence of characters. For example, if the user entered Welcome the program would output Welo. If the user entered WWWWelllcommmeee, the program would still output Welo. I've gotten this much done but it's not doing what it should be and I'm honestly at a loss as to why.
import java.util.ArrayList;
import java.util.Scanner;
public class Stuff {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Please enter a string. ");
String userString = input.next();
ArrayList charList = new ArrayList();
ArrayList finalList = new ArrayList();
int currentLength = 0;
int max = 0;
for(int i = 0; i < userString.length(); i++){
charList.add(userString.charAt(i));
for(int j = i; j < userString.length(); j++){
int k=j+1;
if(k < userString.length() && userString.charAt(k) > userString.charAt(j)){
charList.add(userString.charAt(j));
currentLength++;
}
}
}
if(max < currentLength){
max = currentLength;
finalList.addAll(charList);
}
for (int i = 0; i < finalList.size(); i++){
char item = (char) finalList.get(i);
System.out.print(item);
}
int size1 = charList.size();
int size2 = finalList.size();
System.out.println("");
System.out.println("Size 1 is: " + size1 + " Size 2 is : " + size2);
}
}
My code, if I input Welcome, outputs WWeceeclcccome.
Does anyone have some tips on what I'm doing wrong?
In these cases it tends to help to step away from the keyboard and think about the algorithm you're trying to implement. Try to explain it first in words.
You are constructing a list of individual characters by appending each of the characters in the input string followed by characters to its right that are in correct alphabetical with their successor. For the input "Welcome" this means the accumulated output will be, showing the outer loop in vertical and inner loop in horizontal:
W W e c
e e c
l c
c c
o
m
e
In total: WWeceeclccome
I can't see the logic of this implementation. Here is a faster solution which runs in O(nlogn) time.
import java.util.Scanner;
public class Stuff
{
//return the index of the first element that's not less than the target element
public static int bsearch(char[] arr, int size, int key)
{
int left = 0;
int right = size - 1;
int mid;
while (left <= right)
{
mid = (left + right) / 2;
if(arr[mid] < key)
left = mid + 1;
else
right = mid - 1;
}
return left;
}
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.println("Please enter a string: ");
String userString = input.next();
char[] maxArr = new char[userString.length()];
char[] precedent = new char[userString.length()];
maxArr[0] = userString.charAt(0);
precedent[0] = userString.charAt(0);
int len = 1;
for(int i = 1; i < userString.length(); i++)
{
if(userString.charAt(i) > maxArr[len - 1])
{
maxArr[len] = userString.charAt(i);
precedent[len] = userString.charAt(i);
len++;
}
else
maxArr[bsearch(maxArr, len, userString.charAt(i))] = userString.charAt(i);
}
//System.out.println(len);
for(int i = 0; i < len; i++)
System.out.print(precedent[i]);
}
}
Using Dynamic Programming O(N^2) in lexicography order mean if i/p is abcbcbcd then o/p can be abcccd, abbbcd, abbccd but as per lexicography order o/p will be abbbcd.
public static String longestIncreasingSubsequence(String input1) {
int dp[] = new int[input1.length()];
int i,j,max = 0;
StringBuilder str = new StringBuilder();
/* Initialize LIS values for all indexes */
for ( i = 0; i < input1.length(); i++ )
dp[i] = 1;
/* Compute optimized LIS values in bottom up manner */
for ( i = 1; i < input1.length(); i++ )
for ( j = 0; j < i; j++ )
if (input1.charAt(i) >= input1.charAt(j) && dp[i] < dp[j]+1)
dp[i] = dp[j] + 1;
/* Pick maximum of all LIS values */
for ( i = 0; i < input1.length(); i++ ) {
if ( max < dp[i] ) {
max = dp[i];
if (i + 1 < input1.length() && max == dp[i+1] && input1.charAt(i+1) < input1.charAt(i)) {
str.append(input1.charAt(i+1));
i++;
} else {
str.append(input1.charAt(i));
}
}
}
return str.toString();
}

How can i generate all subsets of a variable length set?

I am trying to write a program that generates all the subsets of an entered set in java. I think i nearly have it working.
I have to use arrays (not data structures)
The entered array will never be greater than 20
Right now when i run my code this is what i get:
Please enter the size of A: 3
Please enter A: 1 2 3
Please enter the number N: 3
Subsets:
{ }
{ 1 }
{ 1 2 }
{ 1 2 3 }
{ 2 3 }
{ 2 3 }
{ 2 }
{ 1 2 }
this is the correct number of subsets (2^size) but as you can see it prints a few duplicates and not some of the subsets.
Any ideas where I am going wrong in my code?
import java.util.Scanner;
public class subSetGenerator
{
// Fill an array with 0's and 1's
public static int [] fillArray(int [] set, int size)
{
int[] answer;
answer = new int[20];
// Initialize all elements to 1
for (int i = 0; i < answer.length; i++)
answer[i] = 1;
for (int a = 0; a < set.length; a++)
if (set[a] > 0)
answer[a] = 0;
return answer;
} // end fill array
// Generate a mask
public static void maskMaker(int [] binarySet, int [] set, int n, int size)
{
int carry;
int count = 0;
boolean done = false;
if (binarySet[0] == 0)
carry = 0;
else
carry = 1;
int answer = (int) Math.pow(2, size);
for (int i = 0; i < answer - 1; i++)
{
if (count == answer - 1)
{
done = true;
break;
}
if (i == size)
i = 0;
if (binarySet[i] == 1 && carry == 1)
{
binarySet[i] = 0;
carry = 0;
count++;
} // end if
else
{
binarySet[i] = 1;
carry = 1;
count++;
//break;
} // end else
//print the set
System.out.print("{ ");
for (int k = 0; k < size; k++)
if (binarySet[k] == 1)
System.out.print(set[k] + " ");
System.out.println("}");
} // end for
} // maskMaker
public static void main (String args [])
{
Scanner scan = new Scanner(System.in);
int[] set;
set = new int[20];
int size = 0;
int n = 0;
// take input for A and B set
System.out.print("Please enter the size of A: ");
size = scan.nextInt();
if (size > 0)
{
System.out.print("Please enter A: ");
for (int i = 0; i < size; i++)
set[i] = scan.nextInt();
} // end if
System.out.print("Please enter the number N: ");
n = scan.nextInt();
//System.out.println("Subsets with sum " + n + ": ");
System.out.println("Subsets: ");
System.out.println("{ }");
maskMaker(fillArray(set, size), set, n, size);
} // end main
} // end class
The value of i always goes from 0 to N-1 and then back to 0. This is not useful to generate every binary mask you need only one time. If you think about it, you need to move i only when you have generate all possible masks up to i-1.
There is a much easier way to do this if you remember every number is already internally represented in binary in the computer and everytime you increment it Java is doing the adding and carrying by itself. Look for bitwise operators.

Categories