I am trying to implement a loop that encrypts a string to the given shift amount of int shift. The code below works great, however I'd like to change the code so that it encrypts in a descending order instead of ascending. Any clues as to what to change in the algorithm?
int shift = 3;
string line = "abc";
for (int i = 0; i < line.length(); i++) {
if (line[i] >= 'a' && line[i] <= 'z') {
int rotate = line[i] + shift;
if (rotate > 'z') line[i] = ((line[i] - 26) + shift);
else line[i] = rotate;
}
}
cout << line << endl;
With a shift of 3, the above code converts string line "abc" to "def", but I am trying to get the output of "dcb".
NOTE: The code is in C++ but I will accept JavaScript, Java, or Php suggestions just as C++, as long as it's raw code with no library resources. Thanks guys and gals.
you can just upgrade the variable shift and then instead of checking overflow of increasing check the decreasing
int shift = -3;
string line = "abc";
for (int i = 0; i < line.length(); i++) {
if (line[i] >= 'a' && line[i] <= 'z') {
int rotate = line[i] + shift;
if (rotate < 'a') line[i] = ((line[i] + 26) + shift);
else line[i] = rotate;
}
}
cout << line << endl;
you can also do the below if in your loop if you want to handle uppercases
if (line[i] >= 'A' && line[i] <= 'Z') {
int rotate = line[i] + shift;
if (rotate < 'A') line[i] = ((line[i] + 26) + shift);
else line[i] = rotate;
}
Related
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.
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();
}
I was doing practice algorithms problems HackerRank website and I submitted my code firstly in C language but I got some Test Cases incorrect. I thought my logic was right so I ported my code to Java and I passed all my Test Cases.
Link to the problem definition:
https://www.hackerrank.com/challenges/caesar-cipher-1
Here is my code in C:
int main(){
int n;
scanf("%d", &n);
char* s = (char *)malloc(n * sizeof(char));
scanf("%s", s);
int k;
scanf("%d", &k);
k = k % 26;
for(int i = 0; i < n; i++){
if(s[i] >= 65 && s[i] <= 90){
s[i] += k;
if(s[i] > 90){
s[i] = s[i] - 90 + 64;
}
}
if(s[i] >= 97 && s[i] <= 122){
s[i] += k;
if(s[i] > 122){
s[i] = s[i] - 122 + 96;
}
}
}
printf("%s", s);
return 0;
}
And here is my code in Java:
public class Solution {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
String str = br.readLine();
int K = Integer.parseInt(br.readLine());
K %= 26;
for(int i = 0; i < N; i++){
char c = str.charAt(i);
if(c >= 65 && c <= 90){
c += K;
if(c > 90){
c = (char)(c - 90 + 64);
}
}
if(c >= 97 && c <= 122){
c += K;
if(c > 122){
c = (char)(c - 122 + 96);
}
}
System.out.print(c);
}
}
}
Both my solutions are passing Sample Test Cases and logic is all the same. I can't understand why it is showing W/A in C in some Test Cases.
P.S. This is practice problem solution and not a live contest solution.
C strings are terminated with a special '\0' character appended to their end. So an actual string is always 1 character longer than the visible text.
You are not allocating memory for the input string null terminator:
Replace
char* s = (char *)malloc(n * sizeof(char));
with
char* s = malloc(n * sizeof(char) + 1);
or even
char* s = malloc(n + 1);
as sizeof(char) is guaranteed to be 1.
In addition there would be a problem with these lines:
if(s[i] >= 97 && s[i] <= 122){
s[i] += k;
s[i] might be 122 and k might be very well greater than 5. As s[i] is most likely signed char type, and it might overflow past the value of 127, which is the maximum for signed char. And signed integer overflow has an undefined behavior.
This one is working fine.
int main(){
int n;
scanf("%d",&n);
char* s = (char *)malloc(10240 * sizeof(char));
scanf("%s",s);
int k;
scanf("%d",&k);
for(int i = 0; i < n; i++){
if(s[i] >= 65 && s[i] <= 90){
s[i] = (s[i]-'A'+k)%26 +'A';
}
if(s[i] >= 97 && s[i] <= 122){
s[i] = (s[i]-'a'+k)%26 +'a';
}
}
printf("%s", s);
return 0;
}
Just updated contents of if blocks and malloc size.
Take following code as base:
for (int i = 0; i < 26; i++)
{
alphabet[i] = (char) ('A'+ i );
}
My question is: -
If 'A' Changes to 'X' how can we achieve the alphabet to reset from the start?
For example XYZABC
Whenever you have something that should "wrap around", have a look at the modulo operator. The basic idea is: you don't want to count from i=0 to 26, but e.g. from i=23 to 49, but only add the modulo-26 value to it.
Instead of starting to count at 23 (which would be kind of 'X' - 'A'), you can directly integrate this offset into your loop:
for (int i = 0; i < 26; i++)
{
alphabet[i] = (char) ('A' + ('X' - 'A' + i) % 26);
}
'A' is the base, 'X' - 'A' builds that offset where you add i to, and then take the modulo of 26 (as the alphabet has 26 characters), and then add that to your 'A' again.
You can just insert an if statement:
char startChar = 'X';
for (int i = 0; i < 26; i++) {
char ch = (char) (startChar + i);
if (ch > 'Z') {
ch -= 26;
}
alphabet[i] = ch;
}
I have this Vigenère cipher code that works, but it spits out a number one on the first encryption when I put "Attack at Dawn" (POTTER). It comes out as 1inuhc Qi Xubf. What is causing this?
public class vigenere {
public static void main(String[] args) {
System.out.println();
char[] message = args[0].toCharArray();
int code;
int index = 0;
code = args[1].charAt(index%args[1].length()) - 96;
for(int i = 0; i < message.length; i++){
code = args[1].charAt(index%args[1].length()) - 96;
if(65 <= message[i] && message[i] <= 90){
index++;
message[i] = (char) (65 + ((message[i] - 65) + code) % 26);
}
else if(97 <= message[i] && message[i] <= 122){
index++;
message[i] = (char) (97 + ((message[i] - 97) + code) % 26);
}
System.out.print(message[i]);
}
}
}
I think that you input is
text to be encrypted "Attack at Dawn"
key = potter (should be in all low case letter right) because of this line
code = args[1].charAt(index%args[1].length()) - 96;
I enter the key as Potter and get your result posted.but I use potter, it works fine.