converting digits to word in string in python - python

> #!/usr/bin/env python
>
> import inflect
>
> p = inflect.engine()
s1 = ''
>
> word = 'so do 1st or do 2nd or 3rd byte 4 th so do 5th longest word 3765 word 50 but 7th'
> list_word = list(word)
> print (list_word)
>
> for(m= 0; m <list_word.len(); m++):
> if list_word[m].isalpha():
> s1 += i + ''
> elif list_word[m].isnumeric():
> if (list_word[m+1].isnumeric()):
> continue
> elif (list_word[m+1]+list_word[m+2] == 'st'):
> s1 += first + ''
> m += 2
> elif (list_word[m+1]+list_word[m+2] == 'nd'):
> s1 += second + ''
> m += 2
> elif (list_word[m+1]+list_word[m+2] == 'rd'):
> s1 += third + ''
> m += 2
> elif (list_word[m+1]+list_word[m+2] == 'th'):
> if (list_word[m] == '5'):
> s1 += fifth + ''
> m += 2
> else :
> s1 += p.number_to_words(list_word[m]) + ''
> m += 2
> elif (list_word[m+1].isnumeric()):
> continue
> else:
> s1 += p.number_to_words(list_word[m]) + ''
> else:
> s1 += ' '
>
I need to convert digits to word and make a complete string with alphabets only. But the issue is this kind of for loop can not be used in Python and i need to iterate to next to next character at some places. Can I get any suggestions regarding this, please.
Or if someone can suggest any other approach.

Using the num2words package we can do do this to translate the whole string without any for-loops:
import re
import num2words
def transInt(num, mode=None):
# Changes the mode of the translation to
# correctly translate ordinal numbers.
if mode:
mode = "ordinal"
else:
mode = "cardinal"
# translates the number to either float
# or int, so the translation works correctly.
if "." in num:
num = float(num)
else:
num = int(num)
return num2words.num2words(num, to=mode)
def replaceInt(string):
# Matches numbers, followed by optional ordinal-characters after it.
return re.sub(r"(\d+\.*\d*)(st|nd|rd|th)*", lambda x: transInt(*x.groups()), string)
word = 'so do 1st or do 2nd or 3rd byte 4th so do 5th longest word 3765 word 50 but 7th'
print(word)
print(replaceInt(word))
Output:
so do 1st or do 2nd or 3rd byte 4th so do 5th longest word 3765 word 50 but 7th
so do first or do second or third byte fourth so do fifth longest word three thousand, seven hundred and sixty-five word fifty but seventh
The important thing with the translation is that the suffix ("th" in 5th) is connected to the number. In your example you have "4 th" which will not work with my code. Or rather, it will translate 4 as four instead of fourth

The simplest way would be to use a while loop instead and manually iterate the variable. For example:
m = 0
while m < len(list_word):
body
final else
m += 1
In effect this is the same as using the for loop like you are

Related

how do i run length encode a pattern, rather than a character?

heres my current RLE code
import re
def decode(string):
if string == '':
return ''
multiplier = 1
count = 0
rle_decoding = []
rle_encoding = []
rle_encoding = re.findall(r'[A-Za-z]|-?\d+\.\d+|\d+|[\w\s]', string)
for item in rle_encoding:
if item.isdigit():
multiplier = int(item)
elif item.isalpha() or item.isspace():
while count < multiplier:
rle_decoding.append('{0}'.format(item))
count += 1
multiplier = 1
count = 0
return(''.join(rle_decoding))
def encode(string):
if string == '':
return ''
i = 0
count = 0
letter = string[i]
rle = []
while i <= len(string) - 1:
while string[i] == letter:
i+= 1
count +=1
#catch the loop on last character so it doesn't got to top and access out of bounds
if i > len(string) - 1:
break
if count == 1:
rle.append('{0}'.format(letter))
else:
rle.append('{0}{1}'.format(count, letter))
if i > len(string) - 1: #ugly that I have to do it twice
break
letter = string[i]
count = 0
final = ''.join(rle)
return final
the code might have gotten fucked up when I removed all my comments, but the current code isn't too important. the problem is, I am running RLE on hexadecimal values, that have all been converted to letters so that 0-9 becomes g-p. the problem is that there are a lot of patterns like 'kjkjkjkjkjkjkjkjlmlmlmlmlmlmlm' which doesn't compress at all, because of their not single characters. how would I, if even possible, be able to run my program so that it encodes patterns as well?

cs50 pset6 readability getting wrong grade and negative index

Can anyone spot the issue? I get a negative for my index everytime so it always prints "Before Grade 1". I tried doing some regex but I still don't know how to implement it really
import re
from cs50 import get_string
words = 1
letters = 0
sentences = 0
st = get_string("Text: ")
t = len(st)
regex = r'\w+'
output = re.findall(regex,st)
for i in range(t):
if st.isalpha():
letters += 1
if st.isspace():
words += 1
if st[i] == '.' or st[i] == '!' or st[i] == '?':
sentences += 1
L = (letters / words * 100)
S = (sentences / words * 100)
index = 0.0588 * L - 0.296 * S - 15.8
roundedIndex = round(index)
if roundedIndex < 1:
print("Before Grade 1")
if roundedIndex >= 16:
print("Grade 16+")
else:
print(roundedIndex)
Inside your loop, you're checking if the whole string is alphabetical or a space, not whether the letter corresponding to the index i is. You probably want st[i].isalpha() and st[i].isspace().
Or, you could loop over the characters directly, rather than over indexes:
for char in st:
if char.isalpha():
...
if char.isspace():
...

How can I swap 1 letter and give all possible letter in python

How can I swap only "one" letter and give all possible output in python3 and append into the list
for example: the word "study"
we will have all possible output like
swap the s:
tsudy, tusdy, tudsy, tudys,
#swap the t:
tsudy, sutdy, sudty, sudyt
#also with u,d,y:
...
You can convert word into list of chars,
chars = list(word)
remove selected char from list using its position
chars.pop(index)
and later add this char in different places in this list
new_chars = chars[:pos] + [char] + chars[pos:]
Code:
word = 'study'
for index, char in enumerate(word):
print('char:', char)
# create list without selected char
chars = list(word)
chars.pop(index)
# put selected char in different places
for pos in range(len(chars)+1):
# create new list
new_chars = chars[:pos] + [char] + chars[pos:]
new_word = ''.join(new_chars)
# skip original word
if new_word != word:
print(pos, '>', new_word)
Result:
char: s
1 > tsudy
2 > tusdy
3 > tudsy
4 > tudys
char: t
0 > tsudy
2 > sutdy
3 > sudty
4 > sudyt
char: u
0 > ustdy
1 > sutdy
3 > stduy
4 > stdyu
char: d
0 > dstuy
1 > sdtuy
2 > stduy
4 > stuyd
char: y
0 > ystud
1 > sytud
2 > styud
3 > stuyd
BTW: I wouldn't call it "swapping" but "moving" char. In "swapping" I would rather replace two chars - ie. swapping a with c in abcd gives cbad, not bcad (like in "moving")

search through the word for the letter which comes alphabetically first, and returns that letter

I'm trying to write a code that basically requires me to find the letter that comes alphabetically first and print. Although the printing is required in another function. Need to use the while loop
this what I've gotten so far.
def alphabetically_first(word):
n = 0
p = 0
while n + 1 < len(word):
if word[n] < word[n+1]:
p = word[n]
elif word[n + 1] < word [n]:
p = word[n+1]
n += 1
print p
return

Random word generator termination condition malfunctioning

I am trying to build a random word generator that randomly selects a consonant and vowel structure (e.g. 'cvvc' could be 'mean'). It is not working. The problem when I run it in the debugger is at the last two lines at the end of the while loop.
import random
vowelsList = ['a','e','i','o','u']
constonentsList = ['b','c','d','f','g','h','j','k','l','p','q','r','s','t','u','v','w','x','y','z','th','ch','sh','st','ck']
n = random.randint(1,2)
word = ''
struct = ''
length = 0
x = True
len_con = len(constonentsList)
len_vow = len(vowelsList)
length = 0
while x:
if n == 1:
word += constonentsList[random.randint(0,len_con - 1)]
struct += 'c'
length += 1
elif n == 2:
word += vowelsList[random.randint(0,len_vow - 1)]
struct += 'v'
length += 1
n = random.randint(0,2)
if (length >= 3 & n == 0): #If the word is more than 3 letters and n == 0, don't continue
x = False
print(word)
print(struct)
print(length)
Your code is actually working, albeit only just. The length reflects how many consonants and vowels you produced, but the generated word can be longer as you include two-letter consonants like th and sh. However, there are improvements to be made.
The & operator does not do what you think it does. It is a binary bitwise operator; it sets binary flags in integers:
>>> 1 & 1
1
>>> 2 & 1
3
You want to use the and operator instead to do boolean logic AND testing:
if length >= 3 and n == 0:
For booleans, using & happens to work as the boolean type overloads the operator to return booleans still.
You can greatly simplify your program by using the random.choice() function, and move the termination test to the while loop condition. The length variable is redundant; you can just use len(struct) here:
import random
import string
vowels = 'aeiou'
consonants = [c for c in string.ascii_lowercase if c not in vowels]
consonants += ['th','ch','sh','st','ck']
n = random.randint(1, 2)
word = ''
struct = ''
while len(struct) < 3 or n: # minimum length 3
if n == 1:
word += random.choice(consonants)
struct += 'c'
elif n == 2:
word += random.choice(vowels)
struct += 'v'
n = random.randint(0, 2)
print(word)
print(struct)
print(len(struct))

Categories