Decoding an encoded text - java

I have below logic to encode a text, but when I try to decode it I am not getting expected result:
private static String encodeText(String input) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
int d = (int) c;
d = d*2 + i;
builder.append((char)d);
}
return builder.reverse().toString();
}
Here is my decode logic, I just tried to reverse the logic of encoding to decode the text:
private static String decode(String input) {
StringBuilder b = new StringBuilder();
for (int i = input.length() - 1; i >= 0; i--) {
char c = input.charAt(i);
int data = (int)c;
data = data - i;
data = (data)/2;
b.append((char)data);
}
return b.toString();
}
If I encode the text hello then the encoded value is âÛÚËÐ, when I try to decode it then I am getting it as fdlmq
Where is the issue in this logic, can you please help me?

Since after encoding the characters, you reverse the string
return builder.reverse().toString();
you need to change integer you subtract as
data = data - (size - i - 1);
where size is the length of the String (input.length())

You need to reverse the string again at the start of decode since you reversed it in encodeText() and then again at the end since you build the string beginning at the end.
private static String decode(String input) {
StringBuilder b = new StringBuilder();
input = new StringBuilder(input).reverse().toString();
for (int i = input.length() - 1; i >= 0; i--) {
char c = input.charAt(i);
int data = (int)c;
data = data - i;
data = (data)/2;
b.append((char)data);
}
return b.reverse().toString();
}

So youve "hi"
You do h*2+0 = x, and i*2+1 = y
Now you reverse it and have "yx".
Now you decode "yx"
You do x-1,...
The thing is, you encoded x with +0, not -1. shouldn't use i here, but input.length() - 1 - i.

It is because i is different in two methods.
Change your decode logic to following.
private static String decode(String input)
{
StringBuilder b = new StringBuilder();
for (int i = input.length() - 1; i >= 0; i--)
{
char c = input.charAt(i);
int data = (int) c;
data = data - (input.length()-1-i);
data = (data) / 2;
b.append((char) data);
}
return b.toString();
}

There is amistake in your decode method data = data - (input.length()-i);
try like this
private static String decode(String input) {
StringBuilder b = new StringBuilder();
int length = input.length() - 1;
for (int i = length; i >= 0; i--) {
char c = input.charAt(i);
int data = (int)c;
data = data - (length-i);
data = (data)/2;
b.append((char)data);
}
return b.toString();
}

Related

Replace while loop with lambda

I'm learning lambdas and I have an exercise to rewrite the while loop in this code using lambdas. This method gets encoded user input and returns decoded. I faced this problem and can't understand what I'm supposed to do. (I know that it's not hard, but I just can't get the concept.) I didn't find any similar questions here.
p.s. Also, one more qustion - can this while loop( or maybe whole method) be reworked with method reference?
public String decode(String input) {
StringBuilder letters = new StringBuilder();
input = input.toUpperCase();
int i = 0, j = 0;
while (i < input.length()) {
char symbol = input.charAt(i);
char keySymbol = KEY.charAt(j);
int newIndex = (ALPHABET.indexOf(symbol) - ALPHABET.indexOf(keySymbol)) % ALPHABET.length();
char newSymbol = ALPHABET.charAt(newIndex);
letters.append(newSymbol);
j = ++j % KEY.length();
i++;
}
return letters.toString().toLowerCase();
}
The code sample below includes the original decode method, and a new decodeLamda method.
The decodeLambda method replaces the iteration over 'input'. Running the sample will show they both have the same output. It is possible to change the loop to a method reference.
public class Main {
public static void main(String[] args) {
Main main = new Main();
System.out.println(main.decode("SECRET MESSAGE"));
System.out.println(main.decodeLambda("SECRET MESSAGE"));
}
public static String KEY = "HOPSCOTCH";
public static String ALPHABET = "ABCDEFGHIJKLMONOPQRSTUVWXYZ";
public String decode(String input) {
StringBuilder letters = new StringBuilder();
input = input.toUpperCase();
int i = 0, j = 0;
while (i < input.length()) {
char symbol = input.charAt(i);
char keySymbol = KEY.charAt(j);
int newIndex = Math.abs(ALPHABET.indexOf(symbol) - ALPHABET.indexOf(keySymbol)) % ALPHABET.length();
char newSymbol = ALPHABET.charAt(newIndex);
letters.append(newSymbol);
j = ++j % KEY.length();
i++;
}
return letters.toString().toLowerCase();
}
public String decodeLambda(String input) {
StringBuilder letters = new StringBuilder();
input = input.toUpperCase();
var ref = new Object() {
int j = 0;
};
input.chars()
.forEach( symbol -> {
char keySymbol = KEY.charAt(ref.j);
int newIndex = Math.abs(ALPHABET.indexOf(symbol) - ALPHABET.indexOf(keySymbol)) % ALPHABET.length();
char newSymbol = ALPHABET.charAt(newIndex);
letters.append(newSymbol);
ref.j = ++ref.j % KEY.length();
});
return letters.toString().toLowerCase();
}
}

How to convert reminder int value to string (Characters)

How to convert int value into string means my string will be 42646 character its mod 42600 how to show and print this character and how?
int count = image_length.length(); //count=42646
System.out.println(count);
int mod = count % length; //46
int rem = count - mod; //42600
String rem_value = String.valueOf(rem);
// I want to get string through reminder value 42600 & how
String[] split = rem_value.split("[^a-zA-Z/]", length);
getSaltString();
photoName = randStr + "_IMG.jpg";
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < split.length; i++) {
url_part = String.valueOf(stringBuilder.append(split[i]));
new RegisterImageThread(ActivityRegisterUploadPhoto.this).execute(photoName, url_part + i);
}
new RegisterImageThread(ActivityRegisterUploadPhoto.this).execute(photoName, url_part+rem_value);
So you want to split the numeric String "42600" to an array right?
Replace the line:
String[] split = rem_value.split("[^a-zA-Z/]", length);
to something like this:
String rem_value = "42600"; //your rem_value
int[] split = new int[rem_value.length()];
for (int i = 0; i < rem_value.length(); i++) {
split[i] = Character.getNumericValue(rem_value.charAt(i));
}
//print the result
Arrays.stream(split).forEach(s -> System.out.println(s));

Compress string longer than 2 - loops

Method to compress a string using java and loops. For example, if dc = "aabbbccaaaaba, then c = "aab3cca4ba" Here is what I have so far. Please help/guide. Thanks.
int cnt = 1;
String ans = "";
for (int i = 0; i < dc.length(); i++) {
if ((i < dc.length()) && (dc.charAt(i) == dc.charAt(i++)) && (dc.charAt(i) == dc.charAt(i+=2))){
cnt++;
ans = ans + dc.charAt(i) + cnt;
}
else
ans = ans + dc.charAt(i);
setC(ans);
Unless you're restricted to using for loops, I believe this would do the trick:
String sb = "";
for (int i = 0; i < dc.length(); i++) {
char c = dc.charAt(i);
int count = 1;
while (i + 1 < dc.length() && (dc.charAt(i + 1)) == c) {
count++;
i++;
}
if (count > 1) {
sb += count;
}
sb += c;
}
System.out.println(sb);
edit:
Changed the example to use regular String instead of StringBuilder. However, I really advise against concatenating strings this way, especially if the string you're trying to compress is long.
It might be easier to get what you want by using Sting.toCharArray().
Then manipulate the array accordingly.
String dc = "aabbbccaaaaba";
String and = "";
int index = 0;
int cnt = 2;
While(dc.charAt(index) != null){
int index1 = index + 1;
char j = dc.charAt(index)
While(j.equals(dc.charAt(index1)){
cnt++;
}
//more code
index++;
}
It's a little incomplete but if you follow the logic I think it's what you're looking for. I won't do your assignment for you.
Easiest Solution: - Only one for loop, Time Complexity - O(n)
public static void main(String[] args) {
String str = "aabbbccaaaaba";
char[] arr = str.toCharArray();
int length = arr.length;
StringBuilder sb = new StringBuilder();
int count=1;
for(int i=0; i<length; i++){
if(i==length-1){
sb.append(arr[i]+""+count);
break;
}
if(arr[i]==arr[i+1]){
count++;
}
else{
sb.append(arr[i]+""+count);
count=1;
}
}
System.out.println(sb.toString());
}

Java - make new string based on old one and lag

I need to get a new string based on an old one and a lag. Basically, I have a string with the alphabet (s = "abc...xyz") and based on a lag (i.e. 3), the new string should replace the characters in a string I type with the character placed some positions forward (lag). If, let's say, I type "cde" as my string, the output should be "fgh". If any other character is added in the string (apart from space - " "), it should be removed. Here is what I tried, but it doesn't work :
String code = "abcdefghijklmnopqrstuvwxyzabcd"; //my lag is 4 and I added the first 4 characters to
char old; //avoid OutOfRange issues
char nou;
for (int i = 0; i < code.length() - lag; ++i)
{
old = code.charAt(i);
//System.out.print(old + " ");
nou = code.charAt(i + lag);
//System.out.println(nou + " ");
// if (s.indexOf(old) != 0)
// {
s = s.replace(old, nou);
// }
}
I commented the outputs for old and nou (new, but is reserved word) because I have used them only to test if the code from position i to i + lag is working (and it is), but if I uncomment the if statement, it doesn't do anything and I leave it like this, it keeps executing the instructions inside the for statmement for code.length() times, but my string doesn't need to be so long. I have also tried to make the for statement like below, but I got lost.
for (int i = 0; i < s.length(); ++i)
{
....
}
Could you help me with this? Or maybe some advices about how I should think the algorithm?
Thanks!
It doesn't work because, as the javadoc of replace() says:
Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.
(emphasis mine)
So, the first time you meet an 'a' in the string, you replace all the 'a's by 'd'. But then you go to the next char, and if it's a 'd' that was an 'a' before, you replace it once again, etc. etc.
You shouldn't use replace() at all. Instead, you should simply build a new string, using a StringBuilder, by appending each shifted character of the original string:
String dictionary = "abcdefghijklmnopqrstuvwxyz";
StringBuilder sb = new StringBuilder(input.length());
for (int i = 0; i < input.length(); i++) {
char oldChar = input.charAt(i);
int oldCharPositionInDictionary = dictionary.indexOf(oldChar);
if (oldCharPositionInDictionary >= 0) {
int newCharPositionInDictionary =
(oldCharPositionInDictionary + lag) % dictionary.length();
sb.append(dictionary.charAt(newCharPositionInDictionary));
}
else if (oldChar == ' ') {
sb.append(' ');
}
}
String result = sb.toString();
Try this:
Convert the string to char array.
iterate over each char array and change the char by adding lag
create new String just once (instead of loop) with new String passing char array.
String code = "abcdefghijklmnopqrstuvwxyzabcd";
String s = "abcdef";
char[] ch = s.toCharArray();
char[] codes = code.toCharArray();
for (int i = 0; i < ch.length; ++i)
{
ch[i] = codes[ch[i] - 'a' + 3];
}
String str = new String(ch);
System.out.println(str);
}
My answer is something like this.
It returns one more index to every character.
It reverses every String.
Have a good day!
package org.owls.sof;
import java.util.Scanner;
public class Main {
private static final String CODE = "abcdefghijklmnopqrstuvwxyz"; //my lag is 4 and I added the first 4 characters to
#SuppressWarnings("resource")
public static void main(String[] args) {
System.out.print("insert alphabet >> ");
Scanner scanner = new Scanner(System.in);
String s = scanner.next();
char[] char_arr = s.toCharArray();
for(int i = 0; i < char_arr.length; i++){
int order = CODE.indexOf(char_arr[i]) + 1;
if(order%CODE.length() == 0){
char_arr[i] = CODE.charAt(0);
}else{
char_arr[i] = CODE.charAt(order);
}
}
System.out.println(new String(char_arr));
//reverse
System.out.println(reverse(new String(char_arr)));
}
private static String reverse (String str) {
char[] char_arr = str.toCharArray();
for(int i = 0; i < char_arr.length/2; i++){
char tmp = char_arr[i];
char_arr[i] = char_arr[char_arr.length - i - 1];
char_arr[char_arr.length - i - 1] = tmp;
}
return new String(char_arr);
}
}
String alpha = "abcdefghijklmnopqrstuvwxyzabcd"; // alphabet
int N = alpha.length();
int lag = 3; // shift value
String s = "cde"; // input
StringBuilder sb = new StringBuilder();
for (int i = 0, index; i < s.length(); i++) {
index = s.charAt(i) - 'a';
sb.append(alpha.charAt((index + lag) % N));
}
String op = sb.toString(); // output

Fancy looping in Java

I have a problem wherein I have two strings, the length of one of which I will know only upon execution of my function. I want to write my function such that it would take these two stings and based upon which one is longer, compute a final string as under -
finalString = longerStringChars1AND2
+ shorterStringChar1
+ longerStringChars3and4
+ shorterStringChar2
+ longerStringChars5AND6
...and so on till the time the SHORTER STRING ENDS.
Once the shorter string ends, I want to append the remaining characters of the longer string to the final string, and exit. I have written some code, but there is too much looping for my liking. Any suggestions?
Here is the code I wrote - very basic -
public static byte [] generateStringToConvert(String a, String b){
(String b's length is always known to be 14.)
StringBuffer stringToConvert = new StringBuffer();
int longer = (a.length()>14) ? a.length() : 14;
int shorter = (longer > 14) ? 14 : a.length();
int iteratorForLonger = 0;
int iteratorForShorter = 0;
while(iteratorForLonger < longer) {
int count = 2;
while(count>0){
stringToConvert.append(b.charAt(iteratorForLonger));
iteratorForLonger++;
count--;
}
if(iteratorForShorter < shorter && iteratorForLonger >= longer){
iteratorForLonger = 0;
}
if(iteratorForShorter<shorter){
stringToConvert.append(a.charAt(iteratorForShorter));
iteratorForShorter++;
}
else{
break;
}
}
if(stringToConvert.length()<32 | iteratorForLonger<b.length()){
String remainingString = b.substring(iteratorForLonger);
stringToConvert.append(remainingString);
}
System.out.println(stringToConvert);
return stringToConvert.toString().getBytes();
}
You can use StringBuilder to achieve this. Please find below source code.
public static void main(String[] args) throws InterruptedException {
int MAX_ALLOWED_LENGTH = 14;
String str1 = "yyyyyyyyyyyyyyyy";
String str2 = "xxxxxx";
StringBuilder builder = new StringBuilder(MAX_ALLOWED_LENGTH);
builder.append(str1);
char[] shortChar = str2.toCharArray();
int index = 2;
for (int charCount = 0; charCount < shortChar.length;) {
if (index < builder.length()) {
// insert 1 character from short string to long string
builder.insert(index, shortChar, charCount, 1);
}
// 2+1 as insertion index is increased after after insertion
index = index + 3;
charCount = charCount + 1;
}
String trimmedString = builder.substring(0, MAX_ALLOWED_LENGTH);
System.out.println(trimmedString);
}
Output
yyxyyxyyxyyxyy
String one = "longwordorsomething";
String two = "short";
String shortString = "";
String longString = "";
if(one.length() > two.length()) {
shortString = two;
longString = one;
} else {
shortString = one;
longString = two;
}
StringBuilder newString = new StringBuilder();
int j = 0;
for(int i = 0; i < shortString.length(); i++) {
if((j + 2) < longString.length()) {
newString.append(longString.substring(j, j + 2));
j += 2;
}
newString.append(shortString.substring(i, i + 1));
}
// Append last part
newString.append(longString.substring(j));
System.out.println(newString);

Categories

Resources