Occurrence of a letter case sensitive - python

I am trying to find occurrence of letter 'b' and 'B'. the code that I have written works perfectly. Is there a better way that i can do this.
My code:
def count_letter_b(string):
#TODO: Your code goes here
a = int(string.count('B'))
b = int(string.count('b'))
return a + b
print count_letter_b("Bubble Bungle")

You can turn the string to uppercase (or lowercase), then count the occurrences:
string.upper().count('B')
So, overall, your code will look like this:
def count_letter_b(string):
return string.upper().count('B')
Note: no need to cast to int(..) as the result of str.count is already an int

Well if you only want to apply the same computation to a varying amount of letters you may want them to be arguments (count_letter(s, letters)), but anyway, here is a more functional example:
def count_letter_b(string):
return sum(map(string.count, 'Bb'))
This uses the str.count version that is bound to your input string instance.
Note that you're shadowing the name string if you use it as a parameter name.

You could do
# count in upper string, upper character
def countInvariantChars(c,s):
return s.upper().count(c.upper())
# list comprehensions + length
def countInvariantChars2(c,s):
return len([x for x in s if c.upper() == x.upper()])
# sum ones of list comprehension
def countInvariantChars3(c,s):
return sum([1 for x in s if c.upper() == x.upper()])
print(countInvariantChars("b","Bubble Bungle"))
print(countInvariantChars2("b","Bubble Bungle"))
print(countInvariantChars3("b","Bubble Bungle"))
Output (pyfiddle.io):
read-only#bash: 4
4
4

Use this:
def count_letter_b(string):
return string.lower().count('b')
print(count_letter_b(string))

Related

HackerRank Game of Thrones

I am trying to solve this problem on HackerRank and I am having a issue with my logic. I am confused and not able to think what I'm doing wrong, feels like I'm stuck in logic.
Question link: https://www.hackerrank.com/challenges/game-of-thrones/
I created a dictionary of alphabets with value 0. And then counting number of times the alphabet appears in the string. If there are more than 1 alphabet characters occurring 1 times in string, then obviously that string cannot become a palindrome. That's my logic, however it only pass 10/21 test cases.
Here's my code:
def gameOfThrones(s):
alpha_dict = {chr(x): 0 for x in range(97,123)}
counter = 0
for i in s:
if i in alpha_dict:
alpha_dict[i] += 1
for key in alpha_dict.values():
if key == 1:
counter += 1
if counter <= 1:
return 'YES'
else:
return 'NO'
Any idea where I'm going wrong?
Explanation
The issue is that the code doesn't really look for palindromes. Let's step through it with a sample text based on a valid one that they gave: aaabbbbb (the only difference between this and their example is that there is an extra b).
Your first for loop counts how many times the letters appear in the string. In this case, 3 a and 5 b with all the other characters showing up 0 times (quick aside, the end of the range function is exclusive so this would not count any z characters that might show up).
The next for loop counts how many character there are that show up only once in the string. This string is made up of multiple a and b characters, more than the check that you have for if key == 1 so it doesn't trigger it. Since the count is less than 1, it returns YES and exits. However aaabbbbb is not a palindrome unscrambled.
Suggestion
To fix it, I would suggest having more than just one function so you can break down exactly what you need. For example, you can have a function that would return a list of all the unscrambled possibilities.
def allUnscrambled(string)->list:
# find all possible iterations of the string
# if given 'aabb', return 'aabb', 'abab', 'abba', 'bbaa', 'baba', 'baab'
return lstOfStrings
After this, create a palindrome checker. You can use the one shown by Dmitriy or create your own.
def checkIfPalindrome(string)->bool:
# determine if the given string is a palindrome
return isOrNotPalindrome
Put the two together to get a function that will, given a list of strings, determine if at least one of them is a palindrome. If it is, that means the original string is an anagrammed palindrome.
def palindromeInList(lst)->bool:
# given the list of strings from allUnscrambled(str), is any of them a palindrome?
return isPalindromeInList
Your function gameOfThrones(s) can then call this palindromeInList( allUnscrambled(s) ) and then return YES or NO depending on the result. Breaking it up into smaller pieces and delegating tasks is usually a good way to handle these problems.
Corrected the logic in my solution. I was just comparing key == 1 and not with every odd element.
So the corrected code looks like:
for key in alpha_dict.values():
if key % 2 == 1:
counter += 1
It passes all the testcases on HackerRank website.
The property that you have to check on the input string is that the number of characters with odd repetitions must be less than 1. So, the main ingredients to cook you recipe are:
a counter for each character
an hash map to store the counters, having the characters as keys
iterate over the input string
A plain implementation could be:
def gameOfThrones(s):
counters = {}
for c in s:
counters[c] = counters.get(c, 0) + 1
n_odd_characters = sum(v % 2 for v in counters.values())
Using a functional approach, based on reduce from functools:
from functools import reduce
def gamesOfThrones(s):
return ['NO', 'YES'][len(reduce(
lambda x, y: (x | {y: 1}) if y not in x else (x.pop(y) and x),
s,
{}
)) <= 1]
If you want, you can use the Counter class from collections to make your code more concise:
def gamesOfThrones(s):
return ['NO', 'YES'][sum([v % 2 for v in Counter(s).values() ]) <= 1]

Write a function that takes a string as an argument and displays the letters, one per line using loops in python

I'm learning to program and I'm using "how to think like an computer scientist" the above question is an exercise
This is the program without a function
fruit = "banana"
index = 0
while index < len(fruit):
letter = fruit[index]
print(letter)
index = index + 1
I want to put that into a function like
def tranversal(fruit):
index = 0
while index < len(fruit):
letter = fruit[index]
return letter
index += 1
print(tranversal("apple"))
However this is only printing the first letter of "apple" and if I use print statement instead of return I will get None.
I'm very confused and need help !!
Seems like you didn't understand the purpose of the return statement inside a function. You might want to read this answer first to make things clear.
Once you understand the difference between print() and return, you should define what your function needs to do. Does it need to return the answer or is printing it on the screen enough?
Assuming the latter, given that strings are iterable, a more pythonic way to do it would be:
def transversal(fruit):
for letter in fruit:
print(letter)
Note that since the function is not explicitly returning a value if you try something like:
foo = transversal("banana")
the variable foo will hold the value None.
If you want your function to return the answer and not print it, you could append each letter to an empty result string, with separators for each new line and after you are done with that, simply return result. It could be a good exercise, so you should give it a try :).
A simple solution:
print(*'banana', sep='\n')
Output:
b
a
n
a
n
a
With help of the star operator * you can split a list or a string into parts and and pass them as multiple arguments to function. So the expression print(*'abc') is equivalent to print('a', 'b', 'c').
If you use print in the function, then you dont need to use print when calling the function.
def tranversal(fruit):
index = 0
while index < len(fruit):
letter = fruit[index]
print(letter)
index += 1
tranversal("apple")
If you use a return statement inside of the while loop, then you will immediately leave the function (and return the first letter), and the while loop will not be executed for higher indices.
You can use this code snippet
def printAllChar(s):
for i in s:
print(i,end='\n')
//calling here...
printAllChar("ProgRank")
//output here...
P
r
o
g
R
a
n
k
For the purpose of understanding i wanted to do that exercise with a function, while loop and get a return value.
I've gotten help and i appreciate everyone, here is my code:
def `tranversal`(fruit):
result = ""
length = int(len(fruit))
index = 0
while index < length:
result += fruit[index]
index += 1
if index == length:
return "\n".join(result)
print(tranversal("string"))
You need to execute the statement using the function outside the function. Just shift return tranversal("apple") outside the function transversal like this:
def transversal(fruit):
index = 0
letters = ''
while index < len(fruit):
letters += fruit[index] + '\n'
index += 1
return letters
print(transversal("apple"))
Thank you #MykolaZotko for pointing out an error in the code that caused it to only print the first letter.

How does comparing two chars (within a string) work in Python

I am starting to learn Python and looked at following website: https://www.w3resource.com/python-exercises/string/
I work on #4 which is "Write a Python program to get a string from a given string where all occurrences of its first char have been changed to '$', except the first char itself."
str="restart"
char=str[0]
print(char)
strcpy=str
i=1
for i in range(len(strcpy)):
print(strcpy[i], "\n")
if strcpy[i] is char:
strcpy=strcpy.replace(strcpy[i], '$')
print(strcpy)
I would expect "resta$t" but the actual result is: $esta$t
Thank you for your help!
There are two issues, first, you are not starting iteration where you think you are:
i = 1 # great, i is 1
for i in range(5):
print(i)
0
1
2
3
4
i has been overwritten by the value tracking the loop.
Second, the is does not mean value equivalence. That is reserved for the == operator. Simpler types such as int and str can make it seem like is works in this fashion, but other types do not behave this way:
a, b = 5, 5
a is b
True
a, b = "5", "5"
a is b
True
a==b
True
### This doesn't work
a, b = [], []
a is b
False
a == b
True
As #Kevin pointed out in the comments, 99% of the time, is is not the operator you want.
As far as your code goes, str.replace will replace all instances of the argument supplied with the second arg, unless you give it an optional number of instances to replace. To avoid replacing the first character, grab the first char separately, like val = somestring[0], then replace the rest using a slice, no need for iteration:
somestr = 'restart' # don't use str as a variable name
val = somestr[0] # val is 'r'
# somestr[1:] gives 'estart'
x = somestr[1:].replace(val, '$')
print(val+x)
# resta$t
If you still want to iterate, you can do that over the slice as well:
# collect your letters into a list
letters = []
char = somestr[0]
for letter in somestr[1:]: # No need to track an index here
if letter == char: # don't use is, use == for value comparison
letter = '$' # change letter to a different value if it is equal to char
letters.append(letter)
# Then use join to concatenate back to a string
print(char + ''.join(letters))
# resta$t
There are some need of modification on your code.
Modify your code with as given in below.
strcpy="restart"
i=1
for i in range(len(strcpy)):
strcpy=strcpy.replace(strcpy[0], '$')[:]
print(strcpy)
# $esta$t
Also, the best practice to write code in Python is to use Function. You can modify your code as given below or You can use this function.
def charreplace(s):
return s.replace(s[0],'$')[:]
charreplace("restart")
#'$esta$t'
Hope this helpful.

Contradictory outputs in simple recursive function

Note: Goal of the function is to remove duplicate(repeated) characters.
Now for the same given recursive function, different output pops out for different argument:
def rd(x):
if x[0]==x[-1]:
return x
elif x[0]==x[1]:
return rd(x[1: ])
else:
return x[0]+rd(x[1: ])
print("Enter a sentence")
r=raw_input()
print("simplified: "+rd(r))
This functions works well for the argument only if the duplicate character is within the starting first six characters of the string, for example:
if r=abcdeeeeeeefghijk or if r=abcdeffffffghijk
but if the duplicate character is after the first six character then the output is same as the input,i.e, output=input. That means with the given below value of "r", the function doesn't work:
if r=abcdefggggggggghijkde (repeating characters are after the first six characters)
The reason you function don't work properly is you first if x[0]==x[-1], there you check the first and last character of the substring of the moment, but that leave pass many possibility like affffffa or asdkkkkkk for instance, let see why:
example 1: 'affffffa'
here is obvious right?
example 2: 'asdkkkkkk'
here we go for case 3 of your function, and then again
'a' +rd('sdkkkkkk')
'a'+'s' +rd('dkkkkkk')
'a'+'s'+'d' +rd('kkkkkk')
and when we are in 'kkkkkk' it stop because the first and last are the same
example 3: 'asdfhhhhf'
here is the same as example 2, in the recursion chain we arrive to fhhhhf and here the first and last are the same so it leave untouched
How to fix it?, simple, as other have show already, check for the length of the string first
def rd(x):
if len(x)<2: #if my string is 1 or less character long leave it untouched
return x
elif x[0]==x[1]:
return rd(x[1: ])
else:
return x[0]+rd(x[1: ])
here is alternative and iterative way of doing the same: you can use the unique_justseen recipe from itertools recipes
from itertools import groupby
from operator import itemgetter
def unique_justseen(iterable, key=None):
"List unique elements, preserving order. Remember only the element just seen."
# unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
# unique_justseen('ABBCcAD', str.lower) --> A B C A D
return map(next, map(itemgetter(1), groupby(iterable, key)))
def clean(text):
return "".join(unique_justseen(text)
test
>>> clean("abcdefggggggggghijk")
'abcdefghijk'
>>> clean("abcdefghijkkkkkkkk")
'abcdefghijk'
>>> clean("abcdeffffffghijk")
'abcdefghijk'
>>>
and if you don't want to import anything, here is another way
def clean(text):
result=""
last=""
for c in text:
if c!=last:
last = c
result += c
return result
The only issue I found with you code was the first if statement. I assumed you used it to make sure that the string was at least 2 long. It can be done using string modifier len() in fact the whole function can but we will leave it recursive for OP sake.
def rd(x):
if len(x) < 2: #Modified to return if len < 2. accomplishes same as original code and more
return x
elif x[0]==x[1]:
return rd(x[1: ])
else:
return x[0]+rd(x[1: ])
r=raw_input("Enter a sentence: ")
print("simplified: "+rd(r))
I would however recommend not making the function recursive and instead mutating the original string as follows
from collections import OrderedDict
def rd(string):
#assuming order does matter we will use OrderedDict, no longer recursive
return "".join(OrderedDict.fromkeys(string)) #creates an empty ordered dict eg. ({a:None}), duplicate keys are removed because it is a dict
#grabs a list of all the keys in dict, keeps order because list is orderable
#joins all items in list with '', becomes string
#returns string
r=raw_input("Enter a sentence: ")
print("simplified: "+rd(r))
Your function is correct but, if you want to check the last letter, the function must be:
def rd(x):
if len(x)==1:
return x
elif x[0]==x[1]:
return rd(x[1: ])
else:
return x[0]+rd(x[1: ])
print("Enter a sentence")
r=raw_input()
print("simplified: "+rd(r))

How many letter were changed in string

Hello I am fairly new at programming,
I would like to know is there a function or a method that allows us to find out how many letters have been changed in a string..
example:
input:
"Cold"
output:
"Hold"
Hence only 1 letter was changed
or the example:
input:
"Deer"
output:
"Dial"
Hence 3 letters were changed
I spoke too soon. First result googling:
https://pypi.python.org/pypi/python-Levenshtein/
This should be able to measure the minimum number of changes needed to get from one string to another.
If you don't need to consider character insertions or deletions, the problem is reduced to simply counting the number of characters that are different between the strings.
Since you're new to programming, a imperative-style program would be:
def differences(string1,string2):
i=0
different=0
for i in range(len(string1)):
if string1[i]!=string2[i]:
different= different+1
return different
something slightly more pythonic would be:
def differences(string1,string2):
different=0
for a,b in zip(string1,string2):
if a!=b:
different+= 1
return different
or, if you want to go fully functional:
def differences(string1,string2):
return sum(map(lambda (x,y):x!=y, zip(string1,string2)))
which, as #DSM suggested, is equivalent to the more readable generator expression:
def differences(string1,string2):
return sum(x != y for x,y in zip(string1, string2))
Use the itertools library as follows (Python 3.x)
from itertools import zip_longest
def change_count(string1, string2):
count = 0
for i, (char1, char2) in enumerate(zip_longest(string1, string2)):
if char1 != char2:
count = count + 1
return count
string1 = input("Enter one string: ")
string2 = input("Enter another string: ")
changed = change_count(string1, string2)
print("Times changed: ", changed)
Check out the difflib library, particularly then ndiff method. Note: this is kind of overkill for the required job, but it is really great for seeing the differences between two files (you can see which are new, which are changed, etc etc)
word1 = "Cold"
word2 = "Waldo"
i = 0
differences = difflib.ndiff(word1, word2)
for line in differences:
if line[0] is not " ":
i += 1
print(i)

Categories

Resources