In my textbook, there is this example very similar this to reverse a line from an input file:
void Reverse(ifstream &inFile, int level)
{
int myInput = inFile.get();
if (myInput != '\n' && myInput != EOF) // don't understand this, line 4
Reverse(inFile, level);
if (myInput != EOF)
cout.put(myInput);
}
What I don't get is the line I commented. Because from an input file that's inputs were:
ABC\n
DEF\0
When the \n is equal to myInput, doesn't it make line 4's conditional statement become false since the first (myInput != '\n') would be false, and the second part (myInput != EOF) be true making that whole line false, and not calling the Reverse function again? Thanks.
The trick to understanding recursion on a very basic level is to trace the
execution and write out the sequence of calls. The following might help you
to understand how this works. I indented each call to Recurse() and
included the line numbers that are executed.
3: myInput = 'A'
5: Reverse()
3: myInput = 'B'
5: Reverse()
3: myInput = 'C'
5: Recurse()
3: myInput = '\n' <<<< base condition, recursion stops here
7: cout.put('\n')
7: cout.put('C')
7: cout.put('B')
7: cout.put('A')
So this will output '\nCBA'.
As for the logic in the base condition, remember De Morgan's Laws:
(NOT P) AND (NOT Q)
-> NOT (P OR Q)
(myInput != '\n') && (myInput != EOF)
-> (!(myInput == '\n')) && (!(myInput == EOF))
-> !((myInput == '\n') || (myInput == EOF))
The if statement on line 4 will exclude newlines and the end of file
condition so the recursion stops when it encounters either condition. This is
what causes the recursion to only read one line from the file.
That line is the recursion's base condition. Apparently, this function is designed to print out one line in reverse from the input file at a time. So, once it encounters a \n or an EOF, it has reached the end of the current line, and so does not continue further. Repeated calls to Reverse print out successive lines.
You're right. It won't call Reverse() when the character is a '\n'. So this will only reverse the first line of a file.
Related
I am looking to create a couple of options with optparse in R. I want to feed the R script an argument from bash. This option will first check the length of the argument and then it will check if the argument contains all numbers or a combo of numbers and letters. This should be written as an if then statement.
So what I have so far:
if (opt$TYPE) != "RUNDATE" && str_length(opt$IDNO) != 8 && opt$IDNO != opt$IDNO[0-9]{8} {
print_help(opt_parser)
stop("Not a valid Identity Number.n", call. = FALSE)
}
if (opt$TYPE) != "LIMSID" && str_length(opt$IDNO) == 7 && opt$IDNO != opt$IDNO[A-Z]{3}[0-9]{4} {
print_help(opt_parser)
stop("Not a valid Identity Number.n", call. = FALSE)
}
Example: ABC1234 & ABCD123
needs to be checked so that the first three characters are letters, and that the last four characters are numbers. This would allow ABC1234 to proceed while ABCD123 would trigger the error message and stop the function.
I have an idea for the syntax in bash and am looking for it's equivalent in R:
[[A-Z]]{3}[0-9]{4}
This question already has an answer here:
if {...} else {...} : Does the line break between "}" and "else" really matters?
(1 answer)
Closed 1 year ago.
It works, but I wonder why tis is correct
if (one_time_cost_year_zero != 0) { EIW_TPI_flag = 1
} else {EIW_TPI_flag = 0}
while this results in an error
if (one_time_cost_year_zero != 0) { EIW_TPI_flag = 1 }
else {EIW_TPI_flag = 0}
What's the logic behind that?
Because R would not know that your if -else statement is not finished yet (since only the if () line is also valid R...) compare
1 + 2
+ 3
vs
1 + 2 +
3
In R if we want to split a command over multiple lines we need to either leave a bracket open (as in the if -else example) or have a "hanging" operator at the end of the line (there are also "multiline" strings, but they are not really commands per se)....
Then, the error you are seeing results from the fact that we can't beginn a command with else (like we can't start a command with in, | etc.)
Accordingly, we could also write:
if (one_time_cost_year_zero != 0) { EIW_TPI_flag = 1 } else
{EIW_TPI_flag = 0}
I want to print out the elements in the list in reverse order recursively.
def f3(alist):
if alist == []:
print()
else:
print(alist[-1])
f3(alist[:-1])
I know it is working well, but I don't know the difference between
return f3(alist[:-1])
and
f3(alist[:-1])
Actually both are working well.
My inputs are like these.
f3([1,2,3])
f3([])
f3([3,2,1])
There is a difference between the two although it isn't noticeable in this program. Look at the following example where all I am doing is passing a value as an argument and incrementing it thereby making it return the value once it hits 10 or greater:
from sys import exit
a = 0
def func(a):
a += 1
if a >= 10:
return a
exit(1)
else:
# Modifications are made to the following line
return func(a)
g = func(3)
print(g)
Here the output is 10
Now if I re-write the code the second way without the "return" keyword like this :
from sys import exit
a = 0
def func(a):
a += 1
if a >= 10:
return a
exit(1)
else:
# Modifications are made to the following line
func(a)
g = func(3)
print(g)
The output is "None".
This is because we are not returning any value to handle.
In short, return is like internal communication within the function that can be possibly handled versus just running the function again.
Say I have a string.
"poop"
I want to change "poop" to "peep".
In fact, I also want all of the o's in poop to change to e's for any word I put in.
Here's my attempt to do the above.
def getword():
x = (input("Please enter a word."))
return x
def main():
y = getword()
for i in range (len(y)):
if y[i] == "o":
y = y[:i] + "e"
print (y)
main()
As you can see, when you run it, it doesn't amount to what I want. Here is my expected output.
Enter a word.
>>> brother
brether
Something like this. I need to do it using slicing. I just don't know how.
Please keep your answer simple, since I'm somewhat new to Python. Thanks!
This uses slicing (but keep in mind that slicing is not the best way to do it):
def f(s):
for x in range(len(s)):
if s[x] == 'o':
s = s[:x]+'e'+s[x+1:]
return s
Strings in python are non-mutable, which means that you can't just swap out letters in a string, you would need to create a whole new string and concatenate letters on one-by-one
def getword():
x = (input("Please enter a word."))
return x
def main():
y = getword()
output = ''
for i in range(len(y)):
if y[i] == "o":
output = output + 'e'
else:
output = output + y[i]
print(output)
main()
I'll help you this once, but you should know that stack overflow is not a homework help site. You should be figuring these things out on your own to get the full educational experience.
EDIT
Using slicing, I suppose you could do:
def getword():
x = (input("Please enter a word."))
return x
def main():
y = getword()
output = '' # String variable to hold the output string. Starts empty
slice_start = 0 # Keeps track of what we have already added to the output. Starts at 0
for i in range(len(y) - 1): # Scan through all but the last character
if y[i] == "o": # If character is 'o'
output = output + y[slice_start:i] + 'e' # then add all the previous characters to the output string, and an e character to replace the o
slice_start = i + 1 # Increment the index to start the slice at to be the letter immediately after the 'o'
output = output + y[slice_start:-1] # Add the rest of the characters to output string from the last occurrence of an 'o' to the end of the string
if y[-1] == 'o': # We still haven't checked the last character, so check if its an 'o'
output = output + 'e' # If it is, add an 'e' instead to output
else:
output = output + y[-1] # Otherwise just add the character as-is
print(output)
main()
Comments should explain what is going on. I'm not sure if this is the most efficient or best way to do it (which really shouldn't matter, since slicing is a terribly inefficient way to do this anyways), just the first thing I hacked together that uses slicing.
EDIT Yeah... Ourous's solution is much more elegant
Can slicing even be used in this situation??
The only probable solution I think would work, as MirekE stated, is y.replace("o","e").
I'm failing the last test case, which is the one with the spaces and single quotation mark.
I used s.strip, but the error still persists.
Is there another way to go about this?
Thank you.
from test import testEqual
def removeWhite(s):
s.strip()
s.strip("'")
return s
def isPal(s):
if s == "" or len(s) == 1:
return True
if removeWhite(s[0]) != removeWhite(s[-1]):
return False
return isPal(removeWhite(s[1:-1]))
testEqual(isPal(removeWhite("x")),True)
testEqual(isPal(removeWhite("radar")),True)
testEqual(isPal(removeWhite("hello")),False)
testEqual(isPal(removeWhite("")),True)
testEqual(isPal(removeWhite("hannah")),True)
testEqual(isPal(removeWhite("madam i'm adam")),True)
At first your removeWhite function doesn't return all spaces because strip only removes from the end and the beginning of a string. See:
>>> " a ".strip()
'a'
>>> " a a ".strip()
'a a'
So i suggest this approach:
def removeWhite(s):
return ''.join(filter(lambda x: x not in " '", s))
Please note that I use join because filter returns an iterator which needs to be converted back to a string.
For finding the palindromes i would suggest this function:
def isPal(s):
if len(s) <= 1: # Special case to prevent KeyError later
return True
stripped = removeWhite(s) # Strip off all whitespaces
first = stripped[:len(stripped) // 2] # First half of the string
if len(stripped) % 2: # Length of string is even?
second = stripped[len(stripped) // 2 + 1:] # Drop the middle character
else:
second = stripped[len(stripped) // 2:] # Else keep it
secondrev = ''.join(reversed(second)) # Reverse the second half
return first == secondrev # And return wether they're equal.
This holds for all your examples. But it think your isPal function should work too if you fix your removeWhite function