When investigating if a string is Palindrome, cant i just take the reverse of the reversed string? whats wrong with my code?
def reverse(s):
return s[::-1]
def isPalindrome(s):
if (s == reverse(reverse(s))):
return True
else:
return False
reverse(reverse(s)) always equals s. You want to check whether s equals reverse(s):
def is_palindrome(s):
return s == reverse(s)
It depends on what you are aiming to do. If you just want to have the logic implemented, then your version would work (yet you still have to correct your bug there, it's if (s == reverse(s)) and not reversing the reversed version); however, if that's the task which was given to you in your coding interview, then you're not really doing it right, because of:
You're using an integral API call to reverse the string (and hence you're not implementing isPalindrome);
The time complexity of your version will be much worse than the
complexity of isPalindrome algorithm per se.
Related
what is the time complexity of this code?
how can I improve this code?
import random
n=input('choose one h/t? ')
v=random.randint(0,1)
if n=='h':
if v==0:
print('Hurrah!!! You win. Result is Head.')
else:
print('alas!!! You lose. Result is Tell.')
elif n=='t':
if v==1:
print('hurrah!!! You win. Result is Tell.')
else:
print('alas!!! You lose. Result is Head.')
I suggest you:
either merge the h and v if to get one if only
either determine first if it’s a h or t case, outside of other if. Then, use a function to test the other parts.
Indeed, just refactor to use functions as you are repeating yourself.
In Python 2 code I had something like:
...
elif type(value) == datetime.date:
return transform_date(value)
elif type(value) == datetime.datetime:
return transform_datetime(value)
...
Now, if I follow advise of avoiding "antipattern", I should replace it with isinstance.
isinstance(value, datetime.date)
And there will be a problem, because then correctness will depend on which type I check first.
I am well aware of more than 10 years old How to compare type of an object in Python? and What's the canonical way to check for type in Python? , but this question differs in two important ways:
It's about Python 3, idioms may be different
I am interested in exact check, because the transformation depends on the exact type (otherwise it will be lossy)
Exact match: For example, obj.__class__ or type(obj) matches.
As in Python there is only one obvious way to do it, the answer to this question should not depend on opinion that much.
If you really want strict per-exact-class match, the pythonic solution hasn't changed since py2: use a dict
dispatch = {
datetime.date: transform_date,
datetime.datetime: transform_datetime,
# etc
}
transform = dispatch.get(type(value), some_default_func)
transform(value)
The function below checks to see if the first 9 digits of string (n) equate to the 10th character (an integer from 1-9 or X for 10).
def isISBN(n):
checkSum = 0
for i in range(9):
checkSum = checkSum + (eval(n[i])*(i+1))
if checkSum%11 == eval(n[9]) or (checkSum%11 == 10 and n[9] == 'X'): return True
else: return False
When I run the function for n='020103803X' I get an error:
NameError: name 'X' is not defined
I've searched for this problem and found that most people's issues were with input() or raw_input(), but as I am not using input(), I'm confused as to why I can't test if a character is a specific string. This is my first post as Python beginner, please tell if I'm breaking rules or what extra info I should include.
The problem is with your use of eval: eval('X') is the same as doing X (without the quotes). python sees that as a variable reference, and you have no variable named X.
There is no reason to use eval here. What are you hoping to accomplish? Perhaps you should be checking to see if the character is a digit?
if checkSum%11 == n[9].isdigit() or (checkSum%11 == 10 and n[9] == 'X'): return True
You're trying to get a response from
eval('X')
This is illegal, as you have no symbol 'X' defined.
If you switch the order of your if check, you can pass legal ISBNs. However, it still fails on invalid codes with an X at the end.
def isISBN(n):
checkSum = 0
for i in range(9):
checkSum = checkSum + (eval(n[i])*(i+1))
if (checkSum%11 == 10 and n[9] == 'X') or \
checkSum%11 == eval(n[9]):
return True
else:
return False
Note also that you can short-cut that return logic by simply returning the expression value:
return (checkSum%11 == 10 and n[9] == 'X') or \
checkSum%11 == eval(n[9])
Eval is not the proper usage, nor is the way you use it correct. For example, see Wikipedia which shows the use. You probably want to use a try: except: pair.
try:
int(n[i]
except:
print "this character is not a digit"
A call to eval is sometimes used by inexperienced programmers for all
sorts of things. In most cases, there are alternatives which are more
flexible and do not require the speed penalty of parsing code.
For instance, eval is sometimes used for a simple mail merge facility,
as in this PHP example:
$name = 'John Doe';
$greeting = 'Hello';
$template = '"$greeting,
$name! How can I help you today?"';
print eval("return $template;");
Although this works, it can cause some security problems (see §
Security risks), and will be much slower than other possible
solutions. A faster and more secure solution would be changing the
last line to echo $template; and removing the single quotes from the
previous line, or using printf.
eval is also sometimes used in applications needing to evaluate math
expressions, such as spreadsheets. This is much easier than writing an
expression parser, but finding or writing one would often be a wiser
choice. Besides the fixable security risks, using the language's
evaluation features would most likely be slower, and wouldn't be as
customizable.
Perhaps the best use of eval is in bootstrapping a new language (as
with Lisp), and in tutoring programs for languages[clarification
needed] which allow users to run their own programs in a controlled
environment.
For the purpose of expression evaluation, the major advantage of eval
over expression parsers is that, in most programming environments
where eval is supported, the expression may be arbitrarily complex,
and may include calls to functions written by the user that could not
have possibly been known in advance by the parser's creator. This
capability allows you to effectively augment the eval() engine with a
library of functions that you can enhance as needed, without having to
continually maintain an expression parser. If, however, you do not
need this ultimate level of flexibility, expression parsers are far
more efficient and lightweight.
Thanks everyone. I don't know how I didn't think of using int(). The reason I used eval() was because the past few programs I wrote required something like
x = eval(input("Input your equation: "))
Anyways the function works now.
def isISBN(n):
checkSum = 0
for i in range(9):
checkSum = checkSum + (int(n[i])*(i+1))
if n[9] == 'X':
if checkSum%11 == 10: return True
else: return False
elif checkSum%11 == int(n[9]): return True
else: return False
I'm trying to craft an LL(1) parser for a deterministic context-free grammar. One of the things I'd like to be able to use, because it would enable much simpler, less greedy and more maintainable parsing of literal records like numbers, strings, comments and quotations is k tokens of lookahead, instead of just 1 token of lookahead.
Currently, my solution (which works but which I feel is suboptimal) is like (but not) the following:
for idx, tok in enumerate(toklist):
if tok == "blah":
do(stuff)
elif tok == "notblah":
try:
toklist[idx + 1]
except:
whatever()
else:
something(else)
(You can see my actual, much larger implementation at the link above.)
Sometimes, like if the parser finds the beginning of a string or block comment, it would be nice to "jump" the iterator's current counter, such that many indices in the iterator would be skipped.
This can in theory be done with (for example) idx += idx - toklist[idx+1:].index(COMMENT), however in practice, each time the loop repeats, the idx and obj are reinitialised with toklist.next(), overwriting any changes to the variables.
The obvious solution is a while True: or while i < len(toklist): ... i += 1, but there are a few glaring problems with those:
Using while on an iterator like a list is really C-like and really not Pythonic, besides the fact it's horrendously unreadable and unclear compared to an enumerate on the iterator. (Also, for while True:, which may sometimes be desirable, you have to deal with list index out of range.)
For each cycle of the while, there are two ways to get the current token:
using toklist[i] everywhere (ugly, when you could just iterate)
assigning toklist[i] to a shorter, more readable, less typo-vulnerable name each cycle. this has the disadvantage of hogging memory and being slow and inefficient.
Perhaps it can be argued that a while loop is what I should use, but I think while loops are for doing things until a condition is no longer true, and for loops are for iterating and looping finitely over an iterator, and a(n iterative LL) parser should clearly implement the latter.
Is there a clean, Pythonic, efficient way to control and change arbitrarily the iterator's current index?
This is not a dupe of this because all those answers use complicated, unreadable while loops, which is what I don't want.
Is there a clean, Pythonic, efficient way to control and change arbitrarily the iterator's current index?
No, there isn't. You could implement your own iterator type though; it wouldn't operate at the same speed (being implemented in Python), but it's doable. For example:
from collections.abc import Iterator
class SequenceIterator(Iterator):
def __init__(self, seq):
self.seq = seq
self.idx = 0
def __next__(self):
try:
ret = self.seq[self.idx]
except IndexError:
raise StopIteration
else:
self.idx += 1
return ret
def seek(self, offset):
self.idx += offset
To use it, you'd do something like:
# Created outside for loop so you have name to call seek on
myseqiter = SequenceIterator(myseq)
for x in myseqiter:
if test(x):
# do stuff with x
else:
# Seek somehow, e.g.
myseqiter.seek(1) # Skips the next value
Adding behaviors like providing the index as well as value is left as an exercise.
def palindrome(s):
for i in range(0,len(s)-1):
if s[i] == s[i][::-1]:
return s[i]
words = ['foof','boom','aanaa','nana']
print(palindrome(words))
am trying to make it check for palindromes in a huge text, though, beside the point, I only found one palindrome with my function. I decided to test it with something trivial, but it only regards 'foof' as a palindrome. There is something fundamentally wrong with the for loop, my guess, but I cannot, for the world of me, figure out what the problem is.
A side question: my first post I wrote the code and used the Code Sample button to make it format as a code, somewhat, but somebody had to edit my post so there would be these syntax colours in the code. How can I do it myself, so there would be no need for someone else to edit my posts? :)
Cheers
It's because of your return statement, the function will stop executing as soon as it finds the first palindrome.
You need to create a new list inside your function and each palindrome to that.
def palindrome(s):
l = []
for i in range(0,len(s)-1):
if s[i] == s[i][::-1]:
l.append(s[i])
return l
The function should return a list of palindromes and not just the first one...