Dmytro Bihun
Dmytro Bihun

Reputation: 5

Caesar's cypher encryption algorithm

Caesar's cypher is the simplest encryption algorithm. It adds a fixed value to the ASCII (unicode) value of each character of a text. In other words, it shifts the characters. Decrypting a text is simply shifting it back by the same amount, that is, it substract the same value from the characters.

My task is to write a function that:

This is my MATLAB code:

function [coded] = caesar(input_text, shift)
x = double(input_text); %converts char symbols to double format
for ii = 1:length(x) %go through each element
    if (x(ii) + shift > 126) & (mod(x(ii) + shift, 127) < 32)
        x(ii) = mod(x(ii) + shift, 127) + 32; %if the symbol + shift > 126, I make it 32
    elseif (x(ii) + shift > 126) & (mod(x(ii) + shift, 127) >= 32)
        x(ii) = mod(x(ii) + shift, 127);
    elseif (x(ii) + shift < 32) & (126 + (x(ii) + shift - 32 + 1) >= 32)
        x(ii) = 126 + (x(ii) + shift - 32 + 1);
    elseif (x(ii) + shift < 32) & (126 + (x(ii) + shift - 32 + 1) < 32)
        x(ii) = abs(x(ii) - 32 + shift - 32);
    else x(ii) = x(ii) + shift;
    end
end
     coded = char(x); % converts double format back to char
end

I can't seem to make the wrapping conversions correctly (e.g. from 31 to 126, 30 to 125, 127 to 32, and so on). How should I change my code to do that?

Upvotes: 0

Views: 3377

Answers (4)

Veljko Miletic
Veljko Miletic

Reputation: 81

Here Is one short code:

function coded = caesar(v,n)
C = 32:126;
v = double(v);

for i = 1:length(v)
    x = find(C==v(i));
    C = circshift(C,-n);
    v(i) = C(x);
    C = 32:126;
end
coded = char(v);
end

Upvotes: 0

evan_
evan_

Reputation: 11

First i converted the output(shift+ text_input) to char.

function coded= caesar(text_input,shift)
coded=char(text_input+shift);

for i=1:length(coded)
    while coded(i)<32
        coded(i)=coded(i)+95;
    end
    while coded(i)>126 
        coded(i)=coded(i)-95;
    end

end

Upvotes: 0

NAND
NAND

Reputation: 687

We can solve it using the idea of periodic functions : periodic function repeats itself every cycle and every cycle is equal to ...

like periodic functions ,we have a function that repeats itself every 95 values

the cycle = 126-32+1 ; we add one because the '32' is also in the cycle ...

So if the value of the character exceeds '126' we subtract 95 ,

i.e. if the value =127(bigger than 126) then it is equivalent to 127-95=32 .

&if the value is less than 32 we subtract 95.

i.e. if the value= 31 (less than 32) then it is equivalent to 31+95 =126..

Now we will translate that into codes :

function out= caesar(string,shift)
value=string+shift;

for i=1:length(value)
    while value(i)<32
        value(i)=value(i)+95;
    end
    while value(i)>126 
        value(i)=value(i)-95;
    end

end
out=char(value);

Upvotes: 0

Dev-iL
Dev-iL

Reputation: 24169

Before you even start coding something like this, you should have a firm grasp of how to approach the problem.

The main obstacle you encountered is how to apply the modulus operation to your data, seeing how mod "wraps" inputs to the range of [0 modPeriod-1], while your own data is in the range [32 126]. To make mod useful in this case we perform an intermediate step of shifting of the input to the range that mod "likes", i.e. from some [minVal maxVal] to [0 modPeriod-1].

So we need to find two things: the size of the required shift, and the size of the period of the mod. The first one is easy, since this is just -minVal, which is the negative of the ASCII value of the first character, which is space (written as ' ' in MATLAB). As for the period of the mod, this is just the size of your "alphabet", which happens to be "1 larger than the maximum value, after shifting", or in other words - maxVal-minVal+1. Essentially, what we're doing is the following

input -> shift to 0-based ("mod") domain -> apply mod() -> shift back -> output

Now take a look how this can be written using MATLAB's vectorized notation:

function [coded] = caesar(input_text, shift)
FIRST_PRINTABLE = ' ';
LAST_PRINTABLE = '~';
N_PRINTABLE_CHARS = LAST_PRINTABLE - FIRST_PRINTABLE  + 1;

coded = char(mod(input_text - FIRST_PRINTABLE + shift, N_PRINTABLE_CHARS) + FIRST_PRINTABLE);

Here are some tests:

>> caesar('blabla', 1)
ans =
    'cmbcmb'
>> caesar('cmbcmb', -1)
ans =
    'blabla'
>> caesar('blabla', 1000)
ans =
    '5?45?4'
>> caesar('5?45?4', -1000)
ans =
    'blabla'

Upvotes: 3

Related Questions