how to find the first and last letters of a word - python

I have a task to find if a word starts with an o ends with a t or both. For finding if it starts or ends the code works fine . For the both part it doesn't work but I cant find the problem. It should return onetwo if the word starts with o and ends with t.
def one_two(word):
if word[0] == "o":
return "one"
if word[-1] == "t":
return "two"
if word[0] == "o" and word[-1] == "t":
return "onetwo"
assert (one_two("only") == "one")
assert (one_two("cart") == "two")
assert (one_two("o+++t") == "onetwo")

You need to check first if both conditions are true, if not the both case would never execute:
def one_two(word):
if word == "":
return "empty"
if word[0] == "o" and word[-1] == "t":
return "onetwo"
elif word[0] == "o":
return "one"
elif word[-1] == "t":
return "two"
print(one_two("only") == "one")
print(one_two("cart") == "two")
print(one_two("o+++t") == "onetwo")

As already mentioned, you'd need to check the last condition first, as it's checking both the first and last letter. Note that you can keep the multiple if statements if you want, rather than switch to use elif, because the return statements break out of the function early in any case.
def one_two(word):
try:
fw, *_, lw = word
except ValueError: # empty string, or string is too short
if not word:
return None
fw, lw = word, word
if (fw, lw) == ('o', 't'):
return 'onetwo'
if fw == 'o':
return 'one'
if lw == 't':
return 'two'
assert (one_two("only") == "one")
assert (one_two("cart") == "two")
print(one_two("o+++t"))
assert (one_two("o+++t") == "onetwo")
# edge cases
assert one_two('') is None
assert one_two('o') == 'one'
assert one_two('t') == 'two'
assert one_two('ot') == 'onetwo'

you are saying return so code doesn't continue
you can try check it otherway around or simply go like this:
def one_two(word):
msg = ""
if word[0] == "o":
msg += "one"
if word[-1] == "t":
msg += "two"
return msg
assert (one_two("only") == "one")
assert (one_two("cart") == "two")
assert (one_two("o+++t") == "onetwo")

def one_two(word):
return {'o': 'one'}.get(word[0], '') + {'t': 'two'}.get(word[-1], '') if len(word) else ''

Related

How do i get these output?

How do i get these output?
def pair(str):
count = 0
for ch in str:
if ch == 'HLL':
return "Alice"
if ch == 'EO':
return "Bob"
if ch == "WORL":
return "Alice"
if ch == "D":
return "Bob"
else:
return "Hello World"
print(count)
return is executed before print, which means this method ends before print. print is not reachable in your code.
I don't know that you want to get data type of these output.
So, I guess 2 data types and write them here.
String
def pair(str):
count = 0
result = ''
for ch in str:
count += 1
if ch == 'HLL':
result += "Alice"
if ch == 'EO':
result += "Bob"
if ch == "WORL":
result += "Alice"
if ch == "D":
result += "Bob"
else:
result += "Hello World"
print(count)
return result
List
def pair(str):
count = 0
result = list()
for ch in str:
count += 1
if ch == 'HLL':
result.append("Alice")
if ch == 'EO':
result.append("Bob")
if ch == "WORL":
result.append("Alice")
if ch == "D":
result.append("Bob")
else:
result.append("Hello World")
print(count)
return result
Since return is the code that ends the function(def), for loop is executed only once in your code
For reference, if the input is a string(str), only one letter is entered in 'ch' in the for loop, so nothing other than D will be identified.

How to get textX model to treat fifth test case as separate line

Sample code that is failing when adding the fifth test line to the input variable. Leave the fifth line out and the model works.
from textx import metamodel_from_str
mm = metamodel_from_str('''
File:
lines+=Line;
Line:
startwords=Startwords
dirp=DirPhrase?
words=Words?
command=Commands?
;
Startwords:
(StartKeywords | Signs)?;
StartKeywords:
'bag';
Commands:
('sleep over'|'walk');
Words:
words+=Word?;
Word:
!DirType !Commands ID;
Signs:
signs+=Sign;
Sign:
!Commands !StartKeywords Word;
DirPhrase:
dirtyp=DirType
dir=Dir
;
DirType:
'fast';
Dir:
('left'|'right')+;
''')
input = '''
bag sun kiss sleep over
animal walk
big horse walk
big white cow fast left
little black cow fast right
'''
#little black cow fast right
model = mm.model_from_str(input, debug=False)
l = model.lines[0]
assert l.startwords == 'bag'
assert l.words.words == ['sun', 'kiss']
assert l.command == 'sleep over'
l = model.lines[1]
assert l.startwords.signs == ['animal']
assert l.words == None
assert l.command == 'walk'
l = model.lines[2]
assert l.startwords.signs == ['big', 'horse']
assert l.words == None
assert l.command == 'walk'
l = model.lines[3]
assert l.startwords.signs == ['big', 'white', 'cow']
assert l.words == None
assert l.command == None
assert l.dirp.dirtyp == 'fast'
assert l.dirp.dir == 'left'
if len(model.lines) == 5:
l = model.lines[4]
assert l.startwords.signs == ['little', 'black', 'cow']
assert l.words == None
assert l.command == None
assert l.dirp.dirtyp == 'fast'
assert l.dirp.dir == 'right'
What is happening is somehow the fifth input line is getting read into l.words during the fourth input line processing. The assert there fails because l.words is supposed to be None. I have tried using [eolterm] modifier however that created other errors.
Solved the issue using [eolterm] in the following section of code
from this
Words:
words+=Word?;
to this
Words:
words+=Word[eolterm];
[eolterm] does not like the ? so had to remove that. With that gone it works like a champ.

python comparing parentheses from user input and making sure they have a pair

I'm writing a program to take a user input of parentheses i.e. {} [] () and checking to see if they have a pair (opening and closing). I'm running into an error when running my code where i always get the return false. I've tried different ways of checking against a pre set "list" but it doesn't seem to work. I have to use the class from above too. any help is appreciated.
some example inputs are:
>>>parenthesesMatch('{[]}')
True
>>>parenthesesMatch('({})')
True
>>>parenthesesMatch('{[)]}')
False
My code:
#George flamburis
class Stack():
def __init__(self,que=[]):
self.lst = que
def __repr__(self):
return "Stack({})".format(self.lst)
def push(self, add):
self.lst.append(add)
def pop(self):
return self.lst.pop()
def isEmpty(self):
return self.lst==[]
def first(self, loc=0): #naming of this method can't be []
return self.lst[loc]
def len(self):
return len(self.lst)
def parenthesesMatch(match):
s = Stack()
end = []
for char in match:
if char in "[ { (":
s.push(char)
else:
end.append(char)
if s.len()==len(end):
for num in range(len(end)):
if s.first(num) and end[num] not in '[]' or '{}' or'()':
return False
return True
elif s.len()!=len(end):
return False
It's much easier to simply attempt to pop a closing character off the stack when you see one, and fail if that isn't possible.
pairs = dict(tuple(pair) for pair in ["()", "[]", "{}"])
# pairs["("] == ")"
# pairs["["] == "]"
# etc
def parenthesesMatch(match):
s = Stack()
for char in match:
# Not "] } )"
if char in pairs.values() and pairs[s.pop()] != char:
return False
elif char in pairs:
s.push(char)
return s.isEmpty()
def match(par):
combs = {'{': '}', '(': ')', '[': ']'}
stack = []
for char in par:
if char in '[{(':
stack.append(char)
elif char == combs[stack[len(stack) - 1]]:
stack.pop()
else:
return False
return len(stack) == 0
Comments outline my thought.
def isParenthesesMatch(s):
# to be balanced should be divisable by 2
if len(s)%2 != 0:
return False
open_paren = ['(','[','{']
open_paren_stack = list()
match_close_paren = {')' : '(',']': '[', '}' : '{'}
for item in s:
#Don't care about open
if item in open_paren:
open_paren_stack.append(item)
#if closed we should be able to pop
elif len(open_paren_stack) == 0:
return False
#if we can pop it should match up
elif open_paren_stack.pop() != match_close_paren[item]:
return False
#in case we push a bunch of open and then end with balanced pair
return len(open_paren_stack) == 0
def parenthesesMatch(match):
counter = {'{': 0, '[': 0, '(': 0, '}': 0, ']': 0, ')': 0}
parantheses = '{}[]()'
for character in match:
if character not in parantheses:
continue
counter[character] += 1
return (counter['{'] == counter['}']) and (counter['['] == counter[']']) and (counter['('] == counter[')'])

Why does this substitution cipher script keep throwing an error?

I'm very new to python so bear with me. I'm putting together a little crypto puzzle and part of it requires a substitution cipher. In this case each letter is replaced with three random letters. Every time I run this code it throws an error when I try to encrypt something:
Traceback (most recent call last):
File "/home/pi/Desktop/expansion cipher.py", line 159, in <module>
crypt()
File "/home/pi/Desktop/expansion cipher.py", line 142, in crypt
print encrypt(txt)
File "/home/pi/Desktop/expansion cipher.py", line 127, in encrypt
ctxt = ctxt + exp_ciph(ptxt[counter])
File "/home/pi/Desktop/expansion cipher.py", line 121, in exp_ciph
return cur_exp
UnboundLocalError: local variable 'cur_exp' referenced before assignment
Here is my code:
def rev_ciph(char):
if char == "gps":
cur_rev = "_"
if char == "evl":
cur_rev = "."
if char == "jkb":
cur_rev = "e"
if char == "bhj":
cur_rev = "t"
if char == "szk":
cur_rev = "a"
if char == "nwu":
cur_rev = "o"
if char == "dpl":
cur_rev = "i"
if char == "sbg":
cur_rev = "n"
if char == "dsl":
cur_rev = "s"
if char == "yhq":
cur_rev = "p"
if char == "sav":
cur_rev = "h"
if char == "gfs":
cur_rev = ","
if char == "rtg":
cur_rev = "d"
if char == "fqu":
cur_rev = "l"
if char == "rjt":
cur_rev = "u"
if char == "sbv":
cur_rev = "c"
if char == "yqm":
cur_rev = "m"
if char == "ywh":
cur_rev = "f"
if char == "drt":
cur_rev = "y"
if char == "zfd":
cur_rev = "w"
if char == "asn":
cur_rev = "g"
if char == "fzj":
cur_rev = "p"
if char == "rka":
cur_rev = "b"
if char == "kzv":
cur_rev = "v"
if char == "lah":
cur_rev = "k"
if char == "rma":
cur_rev = "x"
if char == "fqn":
cur_rev = "q"
if char == "vrq":
cur_rev = "j"
if char == "tfv":
cur_rev = "z"
return cur_rev
def exp_ciph(char):
if char == "_":
cur_exp = "gps"
if char == ".":
cur_exp = "evl"
if char == "e":
cur_exp = "jkb"
if char == "t":
cur_exp = "bhj"
if char == "a":
cur_exp = "szk"
if char == "o":
cur_exp = "nwu"
if char == "i":
cur_exp = "dpl"
if char == "n":
cur_exp = "sbg"
if char == "s":
cur_exp = "dsl"
if char == "p":
cur_exp = "yhq"
if char == "h":
cur_exp = "sav"
if char == ",":
cur_exp = "gfs"
if char == "d":
cur_exp = "rtg"
if char == "l":
cur_exp = "fqu"
if char == "u":
cur_exp = "rjt"
if char == "c":
cur_exp = "sbv"
if char == "m":
cur_exp = "yqm"
if char == "f":
cur_exp = "ywh"
if char == "y":
cur_exp = "drt"
if char == "w":
cur_exp = "zfd"
if char == "g":
cur_exp = "asn"
if char == "p":
cur_exp = "fzj"
if char == "b":
cur_exp = "rka"
if char == "v":
cur_exp = "kzv"
if char == "k":
cur_exp = "lah"
if char == "x":
cur_exp = "rma"
if char == "q":
cur_exp = "fqn"
if char == "j":
cur_exp = "vrq"
if char == "z":
cur_exp = "tfv"
return cur_exp
def encrypt(ptxt):
ctxt = "Ciphertext: "
counter = 0
while counter <= len(ptxt):
ctxt = ctxt + exp_ciph(ptxt[counter])
counter += 1
return ctxt
def decrypt(ctxt):
ptxt = "Plaintext: "
counter = 0
while counter <= len(ctxt):
ptxt = ptxt + rev_ciph(ctxt[counter])
counter += 1
return ptxt
def crypt():
print
txt = raw_input("Plaintext: ")
print encrypt(txt)
print
def ucrypt():
print
txt = raw_input("Ciphertext: ")
print decrypt(txt)
print
ex_code = False
while ex_code == False:
print "(1) Encrypt"
print "(2) Decript"
print "(3) Exit"
print
mchoc = raw_input("What would you like to do(1,2,3?): ")
if mchoc == "1":
crypt()
if mchoc == "2":
ucrypt()
if mchoc == "3":
ex_code = True
print
You have two problems. The first is that you aren't handling all possible inputs. Having just copied and tested you code, I see that you get UnboundLocalError: local variable 'cur_exp' referenced before assignment if and only if you try to encrypt something that includes a character that isn't handled by exp_ciph(char) (or rev_ciph(char) for that matter). Neither of these functions handles capital letters, for instance. Python is ALWAYS case sensitive, and regards capital and lower case letters as entirely different characters. Your functions also don't handle other characters, such as "," and ";". If you give the program a string to encrypt that includes a character not handled by your first two functions, then, when that character comes up, all of the conditions for the if statements in these functions are false, and thus cur_exp is never created and assigned a value. When one of these functions then tries to return cur_exp, it finds that cur_exp doesn't exist. That is the source of the error you describe above.
If you input a string consisting ONLY of lower case letters and possibly "_", the you get an entirely different error, namely:
IndexError: string index out of range
This is because the function encrypt(ptxt) always goes looking for one more character than a string has. In Python (and, I think, every programming language) the elements in an iterable such as a string or a list are indexed by their OFFSET from the first item; that is, how many items are in front of it. So, if you have a string foo with 4 charachters:
foo = "abcd"
then:
foo[0] == "a"
foo[1] == "b"
foo[2] == "c"
foo[3] == "d"
There is no foo[4]. Calling foo[4] will raise exactly the above error. The len(object) function returns the number of items in an iterable. So, keeping with the above example,
len(foo) == 4
and thus calling
foo[len(foo)]
will raise IndexError:. This is EXACTLY what always happens in your encrypt(ptxt) function here
counter = 0
while counter <= len(ptxt):
ctxt = ctxt + exp_ciph(ptxt[counter])
counter += 1
You will want to do this instead:
counter = 0
while counter <= len(ptxt) - 1:
ctxt = ctxt + exp_ciph(ptxt[counter])
counter += 1
Those are the first two problem I encounter running this. I won't guarantee there are no more. Hopefully this gets you farther down the path though.

Python. Making a function that tests if a word is a palindrome recursively

I'm trying to make a program that tests if a word is a palindrome using a recursive function. I pretty much have it working but I'm just having trouble with getting it to move on to the next letter if the first and last are the same.
word = input("enterword")
word = word.lower()
def palindrom(word):
if len(word) == 1 or len(word) == 0:
return 0;
if word[0] == word[-1]:
print(word[0], word[-1])
palindrom(word);
else:
return 1;
test = palindrom(word)
if test == 0:
print("Yes")
elif test == 1:
print("No")
So right now it tests if the first and last letter are the same and if so, should run the function again. I just need to have it then check word[1] and word[-2] but I'm having some trouble. I tried splitting word and just popping the letters but it kept looking at the list as a length of 1. So if there is a way to get it to get the length of the whole split list, that would work as well.
You're just missing the return statement when you call your method recursively and the correct slice:
def palindrom(word):
if len(word) == 1 or len(word) == 0:
return 0
if word[0] == word[-1]:
print(word[0], word[-1])
return palindrom(word[1:-1])
else:
return 1
You are missing return statement, also you need to pass reduced word palindrom(word[1:-1]) on each recursion.
word = "viooiv"
word = word.lower()
def palindrom(word):
if len(word) == 1 or len(word) == 0:
return 0
if word[0] == word[-1]:
print(word[0], word[-1])
return palindrom(word[1:-1])
else:
return 1
test = palindrom(word)
if test == 0:
print("Yes")
elif test == 1:
print("No"
Output:
('v', 'v')
('i', 'i')
('o', 'o')
Yes
Try calling palindrome on the word with this function:
def palindrome(word, i = 0):
if i == len(word):
return word[0] == word[-1]
if word[i] == word[-i - 1]:
return palindrome(word, i + 1)
else:
return False
A bit more shorter code:
def checkpalindrome(value):
valuelen = len(value)
if valuelen < 2:
print("palindrome")
else:
checkpalindrome(value[1:valuelen-1]) if value[0] == value[-1] else print('Not palindrome')

Categories

Resources