Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
Task:
To register in the system, each resident must come up with a password. The password consists of letters of the Latin alphabet (uppercase and lowercase), as well as numbers from 0 to 9, that is, it is possible to use 62 characters in total. The password length is from 5 to 20 characters. The password is stored in the database in encrypted form, encryption is carried out according to the following algorithm:
The number b of uppercase Latin letters is counted. For each uppercase letter character in the password, a cyclic shift to the right by bb characters is performed (for example, if b=3, then the D character is converted to the G character, the Y character to the B character).
Similarly, for each lowercase character in the password, a cyclic shift to the right is performed by m characters, where m is the number of lowercase letters in the password.
To quickly search for users in the database, a hash function is calculated for each encrypted password using the following algorithm:
All 62 characters are ordered, numbers come first, then lowercase letters, then uppercase letters.
Each character is assigned a code - the number of the character in this sequence, starting from 0. Thus, the digit codes match their values, the lowercase letter code a-10, b-11, etc.
All codes are summed up, and the remainder of the resulting sum s is found from dividing by the numbers p and q. The resulting pair of numbers (s mod p,s mod q) will be the value of the hash function.
A hash function is considered good if collisions rarely occur, that is, the values of the function match for different passwords.
John came up with a new password. At the same time, there are already nn passwords in the database, and I would like to avoid collisions. Will John succeed?
Input data
The first line contains a string representing John's password.
The second line contains an integer n – the number of passwords in the database.
The third line contains integers p and q. The following lines store passwords in unencrypted form.
Output data
An integer is the number of passwords whose hash function matches the hash function of John's password.
Sample Input:
AabB1cd
5
13 17
Nik143pasw
qeAom1
q1w2e3r4t
aBoba2012
N33iEj
Sample Output:
2
Note:
Passwords that match John's hash function are highlighted.
Processing of John's password:
After cyclic shift: CefD1gh (uppercase letters are shifted by 2, lowercase by 4)
The sum of the character codes is 38+14+15+39+1+16+17=140
The hash function is equal to (10,4)
You have a few logic problems in your code. When you are rotating your upper and lower-case characters to their "encrypted" forms, you iterate through the password twice, and sometimes incorrectly rotate the characters. Take for example just the line
if (pas[i] + big >= 'A' && pas[i] + big <= 'Z') pas[i] = pas[i] + big;
Consider the case where pas[i] == '9' and big == 8. You will end up transforming all of your 9's into As.
Now consider the line in the next loop
if (pas[i] + small >= 'a' && pas[i] + small <= 'z') pas[i] = pas[i] + small;
Which will similarly transform some upper-case letters into lower-case if small is large enough.
You can also combine these two problems. Consider the case where pas[i] is originally Y, big is 1, little is 7. You'll transform Y --> Z, and then in the next step transform Z --> a.
Compartmentalize and abstract your single large main function into smaller functional blocks. This will allow you to reason about each piece individually instead of trying to keep the entirely of main() in your head. Humans have limited short-term memory.
Some suggested functions would include
bool is_upper(char c)
bool is_lower(char c)
bool is_numeric(char c)
char rotate_upper(char c, int steps)
char rotate_lower(char c, int steps)
Instead of looping through the password twice on your transformation step, consider looping through the password once. If the character is upper-case, transform accordingly. If it's lower-case, transform accordingly. This will prevent you from double-rotating some numbers.
Combining all of the above, the two encryption loops of your main function could turn from:
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + big >= 'A' && pas[i] + big <= 'Z') pas[i] = pas[i] + big;
else if (pas[i] >= 'A' && pas[i] <= 'Z') {
int tempVar = big;
while (tempVar > 0) {
if (pas[i] == 'Z') {
pas[i] = 'A';
tempVar = tempVar - 1;
}
tempVar = tempVar - 1;
pas[i] = pas[i] + 1;
}
}
}
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + small >= 'a' && pas[i] + small <= 'z') pas[i] = pas[i] + small;
else if (pas[i] >= 'a' && pas[i] <= 'z') {
int tempVar = small;
while (tempVar > 0) {
if (pas[i] == 'z') {
pas[i] = 'a';
tempVar = tempVar - 1;
}
pas[i] = pas[i] + 1;
tempVar = tempVar - 1;
}
}
}
to
for (int i = 0; i < pas.length(); i++) {
char c = pas[i];
if (is_upper(c)) {
pas[i] = rotate_upper(c, big);
}
else if (is_lower(c)) {
pas[i] = rotate_lower(c, small);
}
}
You can transform 30 lines of code into just under 10. That's much easier to read for both you, the developer, and for any potential reviewers.
Related
I recently learnt that using getchar_unlocked() is a faster way of reading input.
I searched on the internet and found the code snippet below:
But I am unable to understand it.
void fast_scanf(int &number)
{
register int ch = getchar_unlocked();
number= 0;
while (ch > 47 && ch < 58) {
number = number * 10 + ch - 48;
ch = getchar_unlocked();
}
}
int main(void)
{
int test_cases;fast_scanf(test_cases);
while (test_cases--)
{
int n;
fast_scanf(n);
int array[n];
for (int i = 0; i < n; i++)
fast_scanf(array[i]);
}
return 0;
}
So, this code takes input for an integer array of size n for a given number of test_cases . I didn't understand anything in the function fast_scanf, like why this line:
while (ch > 47 && ch < 58)
{ number = number * 10 + ch - 48;
why the register is used while declaring ch?
why the getchar_unlocked() is used twice in the function? and so on..
It would be great help if someone elaborates this for me. Thanks in advance!
Okay, since what you are asking needs to be explained clearly, I am writing it here... so I don't jumble it all up inside the comments...
The function: (Edited it a bit to make it look like more C++-standard)
void fast_scanf(int &number)
{
auto ch = getchar_unlocked();
number= 0;
while (ch >= '0' && ch <= '9')
{
number = number * 10 + ch - '0';
ch = getchar_unlocked();
}
}
Here, take up consideration by looking at the ASCII Table first, since you won't understand how the results are coming up if you don't...
1) Here, you have a character ch takes up the input character from the user using getchar_unlocked() (The auto keyword does that automatically for you and is only usable in C++, not C)...
2) You assign the variable number to zero so that the variable can be re-used, note that the variable is a reference so it changes inside your program as well...
3) while (ch >= '0' && ch <= '9')... As pointed out, checks whether the characters is within the numerical ASCII limit, similar to saying that the character has to be greater than or equal to 48 but less than or equal to 57...
4) Here, things are a little bit tricky, Variable number is multiplied with the product of itself and 10 and the real integer value of the character you stored)...
5) In the next line, ch is reassigned so that you don't have to stay in the loop forever, since ch will remain that number forever if the user doesn't type anything... remember a loop goes back to where it was declared after reaching the end, checks if the condition is true, continues if it is true else breaks)...
For example: 456764
Here, ch will first take 4 then the others follow so we go with 4 first...
1) Number will be assigned to zero. While loop checks if the given character is a number or not, if it is continues the loop else breaks it...
2) Multiplication of 0 with 10 will be zero... and adding it with difference 52 (that is '4') with 48 (that is '0') gives you 4 (the real numerical value, not the char '4')...
So the variable number now is 4...
And the same continues with the others as well... See...
number = number * 10 + '5' - '0'
number = 4 * 10 + 53 - 48
number = 40 + 5
number = 45... etc, etc. for other numbers...
This Leetcode problem is about how to match a pattern string against a text string as efficiently as possible. The pattern string can consists of letters, dots, and stars, where a letter only matches itself, a dot matches any individual character, and a star matches any number of copies of the preceding character. For example, the pattern
ab*c.
would match ace and abbbbcc. I know that it's possible to solve this original problem using dynamic programming.
My question is whether it's possible to see whether two patterns match one another. For example, the pattern
bdbaa.*
can match
bdb.*daa
Is there a nice algorithm for solving this pattern-on-pattern matching problem?
Here's one approach that works in polynomial time. It's slightly heavyweight and there may be a more efficient solution, though.
The first observation that I think helps here is to reframe the problem. Rather than asking whether these patterns match each other, let's ask this equivalent question:
Given patterns P1 and P2, is there a string w where P1 and P2 each match w?
In other words, rather than trying to get the two patterns to match one another, we'll search for a string that each pattern matches.
You may have noticed that the sorts of patterns you're allowed to work with are a subset of the regular expressions. This is helpful, since there's a pretty elaborate theory of what you can do with regular expressions and their properties. So rather than taking aim at your original problem, let's solve this even more general one:
Given two regular expressions R1 and R2, is there a string w that both R1 and R2 match?
The reason for solving this more general problem is that it enables us to use the theory that's been developed around regular expressions. For example, in formal language theory we can talk about the language of a regular expression, which is the set of all strings that the regex matches. We can denote this L(R). If there's a string that's matched by two regexes R1 and R2, then that string belongs to both L(R1) and L(R2), so our question is equivalent to
Given two regexes R1 and R2, is there a string w in L(R1) ∩ L(R2)?
So far all we've done is reframe the problem we want to solve. Now let's go solve it.
The key step here is that it's possible to convert any regular expression into an NFA (a nondeterministic finite automaton) so that every string matched by the regex is accepted by the NFA and vice-versa. Even better, the resulting NFA can be constructed in polynomial time. So let's begin by constructing NFAs for each input regex.
Now that we have those NFAs, we want to answer this question: is there a string that both NFAs accept? And fortunately, there's a quick way to answer this. There's a common construction on NFAs called the product construction that, given two NFAs N1 and N2, constructs a new NFA N' that accepts all the strings accepted by both N1 and N2 and no other strings. Again, this construction runs in polynomial time.
Once we have N', we're basically done! All we have to do is run a breadth-first or depth-first search through the states of N' to see if we find an accepting state. If so, great! That means there's a string accepted by N', which means that there's a string accepted by both N1 and N2, which means that there's a string matched by both R1 and R2, so the answer to the original question is "yes!" And conversely, if we can't reach an accepting state, then the answer is "no, it's not possible."
I'm certain that there's a way to do all of this implicitly by doing some sort of implicit BFS over the automaton N' without actually constructing it, and it should be possible to do this in something like time O(n2). If I have some more time, I'll revisit this answer and expand on how to do that.
I have worked on my idea of DP and came out with the below implementation of the above problem. Please feel free to edit the code in case someone finds any test cases failed. From my side, I tried few test cases and passed all of them, which I will be mentioning below as well.
Please note that I have extended the idea which is used to solve the regex pattern matching with a string using DP. To refer to that idea, please refer to the LeetCode link provided in the OP and look out for discussion part. They have given the explanation for regex matching and the string.
The idea is to create a dynamic memoization table, entries of which will follow the below rules:
If pattern1[i] == pattern2[j], dp[i][j] = dp[i-1][j-1]
If pattern1[i] == '.' or pattern2[j] == '.', then dp[i][j] = dp[i-1][j-1]
The trick lies here: If pattern1[i] = '*', then if dp[i-2][j] exists, then
dp[i][j] = dp[i-2][j] || dp[i][j-1] else dp[i][j] = dp[i][j-1].
If pattern2[j] == '*', then if pattern1[i] == pattern2[j-1], then
dp[i][j] = dp[i][j-2] || dp[i-1][j]
else dp[i][j] = dp[i][j-2]
pattern1 goes row-wise and pattern2 goes column-wise. Also, please note that this code should also work for normal regex pattern matching with any given string. I have verified it by running it on LeetCode and it passed all the available test cases there!
Below is the complete working implementation of the above logic:
boolean matchRegex(String pattern1, String pattern2){
boolean dp[][] = new boolean[pattern1.length()+1][pattern2.length()+1];
dp[0][0] = true;
//fill up for the starting row
for(int j=1;j<=pattern2.length();j++){
if(pattern2.charAt(j-1) == '*')
dp[0][j] = dp[0][j-2];
}
//fill up for the starting column
for(int j=1;j<=pattern1.length();j++){
if(pattern1.charAt(j-1) == '*')
dp[j][0] = dp[j-2][0];
}
//fill for rest table
for(int i=1;i<=pattern1.length();i++){
for(int j=1;j<=pattern2.length();j++){
//if second character of pattern1 is *, it will be equal to
//value in top row of current cell
if(pattern1.charAt(i-1) == '*'){
dp[i][j] = dp[i-2][j] || dp[i][j-1];
}
else if(pattern1.charAt(i-1)!='*' && pattern2.charAt(j-1)!='*'
&& (pattern1.charAt(i-1) == pattern2.charAt(j-1)
|| pattern1.charAt(i-1)=='.' || pattern2.charAt(j-1)=='.'))
dp[i][j] = dp[i-1][j-1];
else if(pattern2.charAt(j-1) == '*'){
boolean temp = false;
if(pattern2.charAt(j-2) == pattern1.charAt(i-1)
|| pattern1.charAt(i-1)=='.'
|| pattern1.charAt(i-1)=='*'
|| pattern2.charAt(j-2)=='.')
temp = dp[i-1][j];
dp[i][j] = dp[i][j-2] || temp;
}
}
}
//comment this portion if you don't want to see entire dp table
for(int i=0;i<=pattern1.length();i++){
for(int j=0;j<=pattern2.length();j++)
System.out.print(dp[i][j]+" ");
System.out.println("");
}
return dp[pattern1.length()][pattern2.length()];
}
Driver method:
System.out.println(e.matchRegex("bdbaa.*", "bdb.*daa"));
Input1: bdbaa.* and bdb.*daa
Output1: true
Input2: .*acd and .*bce
Output2: false
Input3: acd.* and .*bce
Output3: true
Time complexity: O(mn) where m and n are lengths of two regex patterns given. Same will be the space complexity.
You can use a dynamic approach tailored to this subset of a Thompson NFA style regex implementing only . and *:
You can do that either with dynamic programming (here in Ruby):
def is_match(s, p)
return true if s==p
len_s, len_p=s.length, p.length
dp=Array.new(len_s+1) { |row| [false] * (len_p+1) }
dp[0][0]=true
(2..len_p).each { |j| dp[0][j]=dp[0][j-2] && p[j-1]=='*' }
(1..len_s).each do |i|
(1..len_p).each do |j|
if p[j-1]=='*'
a=dp[i][j - 2]
b=[s[i - 1], '.'].include?(p[j-2])
c=dp[i - 1][j]
dp[i][j]= a || (b && c)
else
a=dp[i - 1][j - 1]
b=['.', s[i - 1]].include?(p[j - 1])
dp[i][j]=a && b
end
end
end
dp[len_s][len_p]
end
# 139 ms on Leetcode
Or recursively:
def is_match(s,p,memo={["",""]=>true})
if p=="" && s!="" then return false end
if s=="" && p!="" then return p.scan(/.(.)/).uniq==[['*']] && p.length.even? end
if memo[[s,p]]!=nil then return memo[[s,p]] end
ch, exp, prev=s[-1],p[-1], p.length<2 ? 0 : p[-2]
a=(exp=='*' && (
([ch,'.'].include?(prev) && is_match(s[0...-1], p, memo) ||
is_match(s, p[0...-2], memo))))
b=([ch,'.'].include?(exp) && is_match(s[0...-1], p[0...-1], memo))
memo[[s,p]]=(a || b)
end
# 92 ms on Leetcode
In each case:
The operative starting point in the string and pattern is at the second character looking for * and matches one character back for as long as s matches the character in p prior to the *
The meta character . is being used as a fill in for the actual character. This allows any character in s to match . in p
You can solve this with backtracking too, not very efficiently (because the match of the same substrings may be recalculated many times, which could be improved by introducing a lookup table where all non-matching pairs of strings are saved and the calculation only happens when they cannot be found in the lookup table), but seems to work (js, the algorithm assumes the simple regex are valid, which means not beginning with * and no two adjacent * [try it yourself]):
function canBeEmpty(s) {
if (s.length % 2 == 1)
return false;
for (let i = 1; i < s.length; i += 2)
if (s[i] != "*")
return false;
return true;
}
function match(a, b) {
if (a.length == 0 || b.length == 0)
return canBeEmpty(a) && canBeEmpty(b);
let x = 0, y = 0;
// process characters up to the next star
while ((x + 1 == a.length || a[x + 1] != "*") &&
(y + 1 == b.length || b[y + 1] != "*")) {
if (a[x] != b[y] && a[x] != "." && b[y] != ".")
return false;
x++; y++;
if (x == a.length || y == b.length)
return canBeEmpty(a.substr(x)) && canBeEmpty(b.substr(y));
}
if (x + 1 < a.length && y + 1 < b.length && a[x + 1] == "*" && b[y + 1] == "*")
// star coming in both strings
return match(a.substr(x + 2), b.substr(y)) || // try skip in a
match(a.substr(x), b.substr(y + 2)); // try skip in b
else if (x + 1 < a.length && a[x + 1] == "*") // star coming in a, but not in b
return match(a.substr(x + 2), b.substr(y)) || // try skip * in a
((a[x] == "." || b[y] == "." || a[x] == b[y]) && // if chars matching
match(a.substr(x), b.substr(y + 1))); // try skip char in b
else // star coming in b, but not in a
return match(a.substr(x), b.substr(y + 2)) || // try skip * in b
((a[x] == "." || b[y] == "." || a[x] == b[y]) && // if chars matching
match(a.substr(x + 1), b.substr(y))); // try skip char in a
}
For a little optimization you could normalize the strings first:
function normalize(s) {
while (/([^*])\*\1([^*]|$)/.test(s) || /([^*])\*\1\*/.test(s)) {
s = s.replace(/([^*])\*\1([^*]|$)/, "$1$1*$2"); // move stars right
s = s.replace(/([^*])\*\1\*/, "$1*"); // reduce
}
return s;
}
// example: normalize("aa*aa*aa*bb*b*cc*cd*dd") => "aaaa*bb*ccc*ddd*"
There is a further reduction of the input possible: x*.* and .*x* can both be replaced by .*, so to get the maximal reduction you would have to try to move as many stars as possible next to .* (so moving some stars to the left can be better than moving all to the right).
IIUC, you are asking: "Can a regex pattern match another regex pattern?"
Yes, it can. Specifically, . matches "any character" which of course includes . and *. So if you have a string like this:
bdbaa.*
How could you match it? Well, you could match it like this:
bdbaa..
Or like this:
b.*
Or like:
.*ba*.*
I am writing a program that takes a char and compares it to see if it's in a range of certain chars. For instance, if the char I get is an n I go to state 3, if its a - m or o - z I go to state 4. I'm new to C++ so I'm still learning.
Can I say something like:
char c = file.next_char();
...
if (c in 'a'...'m', 'o'...'z')
{
state = 3;
} else {
state = 4;
}
There is no such syntax in C++. The options are:
Use a switch statement, when the list of values is generally not contiguous, or
Convert the list of explicit character values into contiguous ranges into equivalent boolean expressions. As you know, alphabetic characters consist of a contiguous range of octets in ASCII, so your pseudo-code is equivalent to:
if ( (c >= 'a' && c <= 'm')
||
(c >= 'o' && c <= 'z'))
If you are using ascii (English), you can rely on the fact that all the lower case letters are adjacent. Just check 'a' <= c && c <= 'z'
after ruling out 'n'.
You never said what happens if the state is not one of those, so I left it alone.
// 3 and 4 mean nothing. Give your states meaningful names
enum state_type {FirstState, SecondState, ThirdState, FourthState};
state_type state = FirstState;
char c = get_next_char();
if ('n' == c){
state = FourthState;
} else if ('a' < c && c < 'z'){
state = ThirdState;
} else {
// no change?
}
You could maybe use a for loop to compare it to see if it's a letter in the first or second range. The code would be something this:
char range1[/*amount in array here*/] = "abcdefghijklmnopqrstuvwxyz";
//Substitute range on line above(the characters in the string)
for(int i = 0; i <= /*amount in array here*/; i++) {
if(range1[i] == /*nameoflettervariablehere*/){
//Code here
}
}
I'm sorry but I don't know of a more efficient way.
Well currently I am re creating my own version of enigma as a little project but if you understand how the enigma machine works it has rotors which connect a character to a completely different character for example A might be connected to F or U may be connected to C and this is done three times. Currently I am getting the char for the rotor by using this function:
char getRotorOne(char i) {
if(i == 'a') {
return 'g';
}if(i == 'b') {
return 'A';
}if(i == 'c') {
return 'o';
}
The main problem with this is it takes a long time to write and it seems inefficient and I think there must be a better way. The other problem with this is on the original enigma machine there were only the 26 letters of the alphabet on this there are the 94 tapeable characters of ascii (32-126) is there any other simpler way that this can be done? If you think this question is unclear or you don't understand please tell me instead of just flagging my post, then you can help me improve my question.
Use tables! Conveniently, C string literals are arrays of characters. So you can do this:
// abc
const char* lower_mapping = "gAo";
// ABC
const char* upper_mapping = "xyz";
char getRotorOne(char i) {
if (i >= 'a' && i <= 'z') return lower_mapping[i - 'a'];
if (i >= 'A' && i <= 'Z') return upper_mapping[i - 'A'];
assert(false && "Unknown character cannot be mapped!");
}
Since chars are really just small integers, and ASCII guarantees contiguous ranges for a-z and A-Z (and 0-9) you can subtract from a given character the first one in its range (so, 'a' or 'A') to get an index into that range. That index can then be used to look up the corresponding character via a table, which in this case is just a simple hardcoded string literal.
This is an improvement on Cameron's answer. You should use a simple char array for each rotor, but as you said you want to process ASCII characters in the range 32-126, you should build each mapping as an array of 95 characters:
char rotor1[95] ="aXc;-0..."; // the 95 non control ascii characters in arbitrary order
Then you write your rotor function that way:
char getRotorOne(char i) {
if ((i < 32) || (i > 126)) return i; // do not change non processed characters
return rotor1[i - 32]; // i - 32 is in range 0 - 94: rotor1[i - 32] is defined
}
To start off, I'm four weeks into a C++ course and I don't even know loops yet, so please speak baby talk?
Okay, so I'm supposed to read a twelve character string (plus NULL makes thirteen) from a file, and then shift the letters backwards three, and then print my results to screen and file. I'm okay with everything except the shifting letters. I don't want to write miles of code to take each character individually, subtract three, and re-assemble the string, but I'm not sure how to work with the whole string at once. Can someone recommend a really simple method of doing this?
If you are dealing with simple letters (A to Z or a to z), then you can assume that the internals codes are linear.
Letters are coded as numbers, between 0 and 127. A is coded as 65, B as 66, C as 67, Z as 90.
In order to shift letters, you just have to change the internal letter code as if it were a number, so basically just substracting 3 from the character. Beware of edge cases though, because substracting 3 to 'A' will give you '>' (code 62) and not 'X' (code 88). You can deal with them using "if" statements or the modulo operator ("%").
Here is an ASCII characters table to help you
Once you've loaded your string in, you can use the modulous operator to rotate while keeping within the confines of A-Z space.
I'd keep track of whether the letter was a capital to start with:
bool isCaps = ( letter >= 'A' ) && ( letter <= 'Z' );
if( isCaps )
letter -= 'A'-'a';
and then just do the cipher shift like this:
int shift = -3;
letter -= 'a'; // to make it a number from 0-25
letter = ( letter + shift + 26 ) % 26;
// add 26 in case the shift is negative
letter += 'a'; // back to ascii code
finally finish off with
if( isCaps )
letter += 'A'-'a';
so, putting all this together we get:
char *mystring; // ciphertext
int shift = -3; // ciphershift
for( char *letter = mystring; letter; ++letter )
{
bool isCaps = ( *letter >= 'A' ) && ( *letter <= 'Z' );
if( isCaps )
*letter -= 'A'-'a';
letter -= 'a';
letter = ( letter + shift + 26 ) % 26;
letter += 'a';
if( isCaps )
letter += 'A'-'a';
}
You're going to have to learn loops. They will allow you to repeat some code over the characters of a string, which is exactly what you need here. You'll keep an integer variable that will be your index into the string, and inside the loop do your letter-shifting on the character at that index and increment the index variable by one until you reach NULL.
Edit: If you're not expected to know about loops yet in your course, maybe they want you to do this:
string[0] -= 3; // this is short for "string[0] = string[0] - 3;"
string[1] -= 3;
string[2] -= 3;
...
It will only result in 12 lines of code rather than miles. You don't have to "reassemble" the string this way, you can just edit each character in-place. Then I bet after making you do that, they'll show you the fast way of doing it using loops.
Iterate over the characters with a for loop. And do what you want with the char*. Then put the new char back.
for(int i=0; i<12; i++){
string[i] = string[i] - 3;
}
Where string is your character array (string). There is a bit more involved if you want to make it periodic (I.E. have A wrap round to Z, but the above code should help you get started)
I'm a little unclear what you mean by "shift the letters backwards 3"?
Does that mean D ==> A?
If so, here's a simple loop.
(I didn't do reading from the file, or writing to the file... Thats your part)
#include <string.h>
int main(void)
{
char input[13] = "ABCDEFGHIJKL";
int i;
int len = strlen(input);
for(i=0; i<len; ++i)
{
input[i] = input[i]-3;
}
printf("%s", input); // OUTPUT is: ">?#ABCDEFGHI"
}