d2jsp
Log InRegister
d2jsp Forums > Off-Topic > Computers & IT > Programming & Development > C Code Logic
12Next
Add Reply New Topic New Poll
Member
Posts: 9,805
Joined: Jul 8 2008
Gold: 9.00
Oct 1 2014 12:06pm
So ive got 3 assignments. Ive completed the first one which is to write a program that will take in a text file and spit out a reverse of it. example: "i like dogs" would have an output "sgod ekil i"
my 2nd assignment is to find the last occurrence of a letter in a text file. Since i have a program that reverses a whole file, could i simply implement that and search for the first occurrence? Instead of finding all occurrences and storing the buffer location of each and finding the largest?

I also already have a program that finds the first occurrence, so im really thinking it would just be some copy/paste and rewrite a few lines.
Member
Posts: 32,925
Joined: Jul 23 2006
Gold: 3,804.50
Oct 1 2014 05:02pm
Quote (Wacko @ Oct 1 2014 02:06pm)
So ive got 3 assignments. Ive completed the first one which is to write a program that will take in a text file and spit out a reverse of it. example: "i like dogs" would have an output "sgod ekil i"
my 2nd assignment is to find the last occurrence of a letter in a text file. Since i have a program that reverses a whole file, could i simply implement that and search for the first occurrence? Instead of finding all occurrences and storing the buffer location of each and finding the largest?

I also already have a program that finds the first occurrence, so im really thinking it would just be some copy/paste and rewrite a few lines.


you could, but it won't perform as well. you dont need to store all occurrences. just the last one. as soon as you find a new one, you replace the last one. when you reach the end, your last one is the answer.
Member
Posts: 6,562
Joined: Oct 29 2007
Gold: 4.00
Oct 1 2014 06:50pm
Quote (carteblanche @ Oct 1 2014 05:02pm)
you could, but it won't perform as well. you dont need to store all occurrences. just the last one. as soon as you find a new one, you replace the last one. when you reach the end, your last one is the answer.


why wouldn't it perform as well? (assuming he saves the result of the reversal in a text file and isn't reversing again)
Member
Posts: 13,425
Joined: Sep 29 2007
Gold: 0.00
Warn: 20%
Oct 1 2014 07:48pm
Quote (Aimed_Shot @ Oct 1 2014 08:50pm)
why wouldn't it perform as well? (assuming he saves the result of the reversal in a text file and isn't reversing again)


Because it is much faster to use fseek() than to load an entire file and reverse it just to find the last character.
Member
Posts: 32,925
Joined: Jul 23 2006
Gold: 3,804.50
Oct 1 2014 08:07pm
Quote (Aimed_Shot @ Oct 1 2014 08:50pm)
why wouldn't it perform as well? (assuming he saves the result of the reversal in a text file and isn't reversing again)


my high school physics teacher taught us a little trick that i've always remembered. we were learning newtonian mechanics (forces, velocity, etc) and when a block is at an angle, students were constantly confused whether they should use sine or cosine. when the angle was 40 degrees, sine and cosine were similar enough that you can't tell which to use based on the number you get from the formula. so his advice: use your model, but stretch the data to the extreme. sin 40 and cos 40 are close enough that can't figure out which is correct by looking at it, but if you stretched that angle to 0.01 degrees and 89.99 degrees, then sin and cos are very different, and it becomes clear which one to use.

in this context, instead of a text file that's 3 words long, consider a text file that's 20 gigs. OP's method is to first reverse the string, then find the first occurrence. how will he reverse the string? either 1) he'll keep the whole thing in memory (good luck), or 2) he'll keep part of it in memory and write to another file when he's low in memory. then repeat until the whole thing is in the new file. now he's doing a find on the new file.

option 1) clearly eats up tremendous memory, and 2) writes a huge file to disk. neither are preferred.

consider the alternative. read the file in chunks, keeping a pointer to the last occurrence. then release your memory and read more. repeat until you reach the end. this won't eat up as much memory, and it won't write a huge file to disk.

does that make sense?

Quote
(assuming he saves the result of the reversal in a text file and isn't reversing again)

maybe you were confused with your assumption. nobody said it's the same file. input is the character and a file, output is the last occurrence.
if his assignment was literally to write down the last occurrence (eg: write down "position 15"), then sure you can just find the first occurrence in the reversed file. but his assignment is to write the program which will do it for any given file.

This post was edited by carteblanche on Oct 1 2014 08:13pm
Member
Posts: 6,562
Joined: Oct 29 2007
Gold: 4.00
Oct 1 2014 10:18pm
Quote (carteblanche @ Oct 1 2014 08:07pm)
my high school physics teacher taught us a little trick that i've always remembered. we were learning newtonian mechanics (forces, velocity, etc) and when a block is at an angle, students were constantly confused whether they should use sine or cosine. when the angle was 40 degrees, sine and cosine were similar enough that you can't tell which to use based on the number you get from the formula. so his advice: use your model, but stretch the data to the extreme. sin 40 and cos 40 are close enough that can't figure out which is correct by looking at it, but if you stretched that angle to 0.01 degrees and 89.99 degrees, then sin and cos are very different, and it becomes clear which one to use.

in this context, instead of a text file that's 3 words long, consider a text file that's 20 gigs. OP's method is to first reverse the string, then find the first occurrence. how will he reverse the string? either 1) he'll keep the whole thing in memory (good luck), or 2) he'll keep part of it in memory and write to another file when he's low in memory. then repeat until the whole thing is in the new file. now he's doing a find on the new file.

option 1) clearly eats up tremendous memory, and 2) writes a huge file to disk. neither are preferred.

consider the alternative. read the file in chunks, keeping a pointer to the last occurrence. then release your memory and read more. repeat until you reach the end. this won't eat up as much memory, and it won't write a huge file to disk.

does that make sense?


maybe you were confused with your assumption. nobody said it's the same file. input is the character and a file, output is the last occurrence.
if his assignment was literally to write down the last occurrence (eg: write down "position 15"), then sure you can just find the first occurrence in the reversed file. but his assignment is to write the program which will do it for any given file.


Right, I understand the time and space complexities. i guess I was under the assumption that it was the same file

Member
Posts: 9,803
Joined: Jun 28 2005
Gold: 6.67
Oct 1 2014 10:49pm
If it was a lazy reverse operation, it would be totally fine. Since it's greedy (you always reverse the whole file, instead of what your program actually needs), it's not. Just do the backwards search, it's simple enough.
Member
Posts: 6,325
Joined: Dec 2 2007
Gold: 5,347.75
Oct 26 2014 09:49am
No matter what you will have to look at each character in the string once.

I would loop through every character and then just update the index when you find the letter occur. Then you will have the last occurrence when you are done.

That is O(n) asymptotic time, which is linear.

Code
/**
* Finds the last occurence of a character in a string
* @param s the string to search
* @param c the character to find in the string
* @return the index of the character in the string. -1 if not found
*/
int lastOccurrence(string s, char c) {
int index = -1;

for (string::iterator it = s.begin(); it != s.end(); ++it) {
if (*it == c) {
index = (int)distance(s.begin(), it);
}
}
return index;
}


Didn't see it was C, but however you can use the above to get inspiration.

If you are to perform other tasks with the same file in the same problem, you will have to study if preprocessing the string would benefit.

This post was edited by Utunity on Oct 26 2014 09:52am
Member
Posts: 6,325
Joined: Dec 2 2007
Gold: 5,347.75
Oct 26 2014 11:38am
Sorry for double posting but I figured out my answer was quite wrong.

I have managed to do it in almost constant time best case and O(n) worst case

Code
long lastOccurrenceFile(const char * filename, char c) {

FILE *fp = fopen(filename, "r");
long index = -1;

if (fp != NULL) {
fseek(fp, 0L, SEEK_END);
long i = 0, sz = ftell(fp);

while( --i <= sz ) {
fseek(fp, i, SEEK_END);
if (fgetc(fp) == c) { index = sz + i; break; }
}
}
fclose(fp);
return index;

}


With the above code I found a "`" which was at the end of a 500mb file in constant time. However if it was the last occurrence in the beginning of the file it would have taken much longer.
Member
Posts: 13,425
Joined: Sep 29 2007
Gold: 0.00
Warn: 20%
Oct 26 2014 01:48pm
Quote (Utunity @ Oct 26 2014 01:38pm)
Sorry for double posting but I figured out my answer was quite wrong.

I have managed to do it in almost constant time best case and O(n) worst case

Code
long lastOccurrenceFile(const char * filename, char c) {

  FILE *fp = fopen(filename, "r");
  long index = -1;

  if (fp != NULL) {
    fseek(fp, 0L, SEEK_END);
    long i = 0, sz = ftell(fp);

    while( --i <= sz ) {
      fseek(fp, i, SEEK_END);
      if (fgetc(fp) == c) { index = sz + i; break; }
    }
  }
  fclose(fp);
  return index;

}


With the above code I found a "`" which was at the end of a 500mb file in constant time. However if it was the last occurrence in the beginning of the file it would have taken much longer.


Good job on answering a question that is a month old...
Go Back To Programming & Development Topic List
12Next
Add Reply New Topic New Poll