Python: replace list items and produce all possible permutations - python-3.x

I am trying to implement morse decode for partial morse code.Say for example the representation of word TEST in morse code is ['-','.','...','-'] however if the first character of every morse code string is missing and represented by x then partial morse code for TEST will become ['x','x','x..','x'].Thus in order to decode this partial message, we will have to replace x with either. or - for every occurrence of x in above partial morse code.With 'x' unknown the permutations of TEST word on decoding would be ETST,EEDT,ETSE etc.I have implemented the morse partial decode function as below:
def morsePartialDecode(inputStringList):
with open('words.txt','a') as wordfile:
dictionaryFileLoc = './dictionary.txt'
message_received = inputStringList
message_received = ' '.join(inputStringList)
for i in range(len(message_received)):
x = 'x'
y = '.'
message = message_received.replace(x, y)
message1 = message.split(",")
message_converted = morseDecode(message1)
print message_converted
print >> wordfile, (message_converted)
for i in range(len(message_received)):
x = 'x'
y = '-'
message = message_received.replace(x, y)
message2 = message.split(",")
message_converted = morseDecode(message2)
print >> wordfile, (message_converted)
elements = []
wordfile.closed
return message_converted
def partialMorseCodeTest():
test = ['x', 'x', 'x..', 'x']
print morsePartialDecode(test)
partialMorseCodeTest()
Output:
EESE
TTDT
I need all the combinations of ['x','x','x..','x'] with x replaced by . or -.And my morseDecode() will convert each combination to respective words like EESE, TTDT etcmorsedecode)What to do.Thanks in advance!

Great case for itertools
Example using itertools.product:
from itertools import product
def replace_x_with_all_combinations(morse):
# only works with 1 and 1 only 'x' in each element
all_perm = list()
for v in morse:
if 'x' in v:
# create a list of permutations per element of the morse list
# and append them to the all_perm list
all_perm.append([v.replace('x','.'), v.replace('x','-')])
else:
# if no x found, then append the original element
all_perm.append([v])
# all_perm = [['.', '-'], ['.', '-'], ['...', '-..'], ['.', '-']]
# the list all_perm needs to be unpacked before passing
# to the product() generator, hence the *
return list(product(*all_perm))
partial = ['x','x','x..','x']
result = replace_x_with_all_combinations(partial)
for e in result:
print(e)
Output:
('.', '.', '...', '.')
('.', '.', '...', '-')
('.', '.', '-..', '.')
('.', '.', '-..', '-')
('.', '-', '...', '.')
('.', '-', '...', '-')
('.', '-', '-..', '.')
('.', '-', '-..', '-')
('-', '.', '...', '.')
('-', '.', '...', '-')
('-', '.', '-..', '.')
('-', '.', '-..', '-')
('-', '-', '...', '.')
('-', '-', '...', '-')
('-', '-', '-..', '.')
('-', '-', '-..', '-')
[EDIT]
Although I put the restriction in the above code myself, the "works only for 1 x in the morse character" bugged me, so the following example will take more than one digit missing from a morse character, more than one 'x'
from itertools import product
def replace_x_in_morse_charcter(morse_character):
all_perm = [['.','-'] if c == 'x' else [c] for c in morse_character]
p = list(product(*all_perm))
return [''.join([v for v in e]) for e in p]
def replace_x_in_morse_word(morse):
all_perm = [replace_x_in_morse_charcter(c) for c in morse]
return list(product(*all_perm))
partial = ['x','x','x..','xx']
result = replace_x_in_morse_word(partial)
for e in result:
print(e)
[EDIT] for fun a one liner:
morse_word = ['x','x','x..','xx']
result = list(product(*[[''.join([v for v in e]) for e in list(product(*[['.','-'] if c == 'x' else [c] for c in cm]))] for cm in morse_word]))

Related

Python - match dictionary value within string & print key in string order

I asked a similar question to this earlier on but Im still having a hard time figuring this out. I have the following code:
d = {'k' : '10', 'a' : '20', 'r' : '30', 'p' : '401'}
string = '401203010'
text = ''
for i, j in d.items():
if j in string:
text += i
print(text) #prints karp
desired output: park
the output I get is karp, however I would like the output to be in order of value match in the string, Thanks!
try this maybe?
d = {'k' : '10', 'a' : '20', 'r' : '30', 'p' : '40'}
string = '40203010'
text = ''
keylen = len(''.join(d.keys()))
while len(text) != keylen:
found_val = 0
for i, j in d.items():
jl = len(j)
if string[:jl] == j:
text += i
string = string[jl:]
found_val += 1
if found_val == 0:
break
print(text)
for the sake of clarity, this is really not an algorithm you want to use here. For example one of the downfalls is if it isn't guaranteed that a part of the string will be in the dictionary values then the loop will never end. I don't want to spend the mental resources to fix that potential pitfall because I have some reading to do but perhaps you can figure out a way around it.
edit, never mind that wasn't that difficult but you should test various edge cases.
You could first split up string into substrings of 2, and then switch the keys ad values of d in a temporary dictionary, then just add the values from that:
d = {'k' : '10', 'a' : '20', 'r' : '30', 'p' : '40'}
string = '40203010'
text = ''
split_string = [string[i:i+2] for i in range(0, len(string), 2)]
# ['40', '20', '30', '10']
new_dict = dict((y,x) for x,y in d.items())
# {'30': 'r', '10': 'k', '20': 'a', '40': 'p'}
text = "".join(new_dict[string] for string in split_string)
print(text)
# park

List containing lists (matrix) as input() with python 3

I'm trying to convert a given input to a list containing lists as shown in the command-line code below:
matrix = input('asking')
asking[[2, 0, 4],[1, 2, 4],[4, 4, 2]]
matrix
'[[2, 0, 4],[1, 2, 4],[4, 4, 2]]'
desired output:
[[2,0,4],[1,2,4],[4,4,2]]
Attempts
list(matrix)
['[', '[', '2', ',', ' ', '0', ',', ' ', '4', ']', ',', ' ', '[', '1', ',', ' ', '2', ',', ' ', '4', ']', ',', ' ', '[', '4', ',', ' ', '4', ',', ' ', '2', ']', ']']
x = [int(a) for a in matrix]
builtins.TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'
matrix.split(',')
['[[2', '0', '4]', '[1', '2', '4]', '[4', '4', '2]]']
Code:
fin_result = 0
def perform_check():
print("Enter form \n [[a,b,c] \n [d,e,f] \n [g,h,i]]")
#ask_for_input = [[4,-1,1],[4,5,3],[-2,0,0]]
ask_for_input = [[2,0,4],[1,2,4],[4,4,2]]
print(type(ask_for_input))
#call function to cont
calculate_determinate_matrix(ask_for_input)
def calculate_determinate_matrix(matrix3x3):
matrix_list2x2 = []
matrix_list2x2.append([[matrix3x3[1][1], matrix3x3[1][2]], [matrix3x3[2][1], matrix3x3[2][2]]])
matrix_list2x2.append([[matrix3x3[1][0], matrix3x3[1][2]],[matrix3x3[2][0], matrix3x3[2][2]]])
matrix_list2x2.append([[matrix3x3[1][0], matrix3x3[1][1]],[matrix3x3[2][0], matrix3x3[2][1]]])
count = 0
for count, matrix_2x2 in enumerate(matrix_list2x2):
if count % 2 == 1:
calculate_2x2_matrix(matrix_2x2, matrix3x3[0][count] * -1)
else:
calculate_2x2_matrix(matrix_2x2, matrix3x3[0][count])
def calculate_2x2_matrix(matrix, mult):
global fin_result
result = matrix[0][0] * matrix[1][1]
result_2 = matrix[0][1] * matrix[1][0]
fin_result += mult * (result - result_2)
def main():
perform_check()
print(fin_result)
if __name__ == "__main__":
main()
Clearly this code needs work, but I can't figure this in terms of list comprehension.
Use json loads() method:
matrix = '[[2, 0, 4],[1, 2, 4],[4, 4, 2]]'
matrix = json.loads(matrix)
type(matrix)
<type 'list'>
And in case you want to check for errors in input you can wrap it in try-except:
try:
matrix = json.loads(matrix)
except ValueError:
#code goes here
An alternative to json.loads is ast.literal_eval. It has the advantage that it recognizes Python syntax even if it was invalid JSON, like single-quoted strings. In your exact case, it doesn't make a difference:
import ast
matrix = '[[2, 0, 4],[1, 2, 4],[4, 4, 2]]'
matrix = ast.literal_eval(matrix)

how do i remove comma in the list using for loop?

I have this code:
a = []
num = input('Enter numbers *Separate by using commas:')
for i in num:
a.append(i)
print(a)
and I get this:
Enter numbers *Separate by using commas:1,2,3
['1', ',', '2', ',', '3']
how do I remove the comma?..and I need to use the for loop...thanks
You can use this (by default prevents "," to enter in your array in the first place and functional for multi-digit numbers as you pointed out)-
a = []
num = input('Enter numbers *Separate by using commas:')
num = num.split(",") #splits the input string with "," delimiter
for i in num:
a.append(i)
print(a)

How to remove punctuation from a string and remember the position of it from the string

Hello I have been trying to create a program which gets a string and removes all the punctuation and capitalisation, then the program should insert all the punctuation and capitalisation back into the sentence at the place were it came from.
Here is what I got so far;
sentence = 'I am called bob. What is your name?'
punc = ('!', '"', '£', '$', '%', '^', '&', '*', '(', ')', '¬', '`', '{', '}', '~', '#', ':', '?', '>', '<', ',', '.', '/', ';', '#', ']', '[', '/', '*')
Dictionary = {}
count = 0
for i in sentence:
count = count + 1
if i == punc:
Dictionary[i] = count
print(Dictionary)
I know it's not very much and it don't do anything(I don't know why) but any help would be greatly appreciated.
I am using python 3.4
Strings are immutable and therefore do not have an insert or remove method. However, you can change this to a list which is certainly mutatble. I'd probably have a dictionary with the punctuation as a key and a list of each index. The issue you may run into is that if you have multiple punctuation marks, there's no guarantee that they will be inserted in the correct order. For example:
sentence = 'I am called bob. What is your name?'
punc = ('!', '"', '£', '$', '%', '^', '&', '*', '(', ')', '¬', '`', '{', '}', '~', '#', ':', '?', '>', '<', ',', '.', '/', ';', '#', ']', '[', '/', '*')
sentence = list(sentence)
Dictionary = {}
for i, p in enumerate(sentence): # enumerate() returns an iterable in (index, value) format
if p in punc:
if p in Dictionary:
Dictionary[p].append(i)
else:
Dictionary[p] = [i]
print(Dictionary) # => {'?': [34], '.': [15]}
For example, if I have a weirdly formatted string with a random amount of various punctuation marks:
sentence = 'I? am. cal?led ,bob. Wh,at. is your .name?.'
... # above code
print(sentence) # => "I? am. call?ed bob,. What .i,s your .name?."
This is obviously incorrect. The only sure-fire way is to iterate through the dict from the lowest element to the highest element and add them that way.
Final code:
original = sentence = 'I? am. cal?led ,bob. Wh,at. is your .name?.'
punc = ('!', '"', '£', '$', '%', '^', '&', '*', '(', ')', '¬', '`', '{', '}', '~', '#', ':', '?', '>', '<', ',', '.', '/', ';', '#', ']', '[', '/', '*')
sentence = list(sentence)
Dictionary = {}
seq = [] # list of all indices with any punctuation
for i, p in enumerate(sentence):
if p in punc:
seq.append(i)
if p in Dictionary:
Dictionary[p].append(i)
else:
Dictionary[p] = [i]
sentence = list(filter(lambda x: x not in punc, sentence))
for i in seq:
for key, indices in Dictionary.items():
if i in indices:
sentence.insert(i, key)
indices.remove(i)
assert(''.join(sentence) == original)

Getting index of duplicate letters in a string

from graphics import *
import random
def hangman(word):
returnStuff = {'again':0, '1st':1}
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
win = GraphWin("Hangman", 800, 550)
win.setBackground("yellow")
titleText = Text(Point(400,50), 'HANGMAN')
titleText.setSize(24)
titleText.setStyle('bold')
titleText.draw(win)
#Building the hangman base
base = Line(Point(120,350),Point(230,350))
base.draw(win)
stand = Line(Point(175,350),Point(175,150))
stand.draw(win)
stand2 = Line(Point(175,150),Point(250,150))
stand2.draw(win)
stand3 = Line(Point(250,150),Point(250,180))
stand3.draw(win)
#drawing the empty lines for the word
x1 = 150
x2 = 180
l = 0
print(word)
while l< len(word):
wordLine = Line(Point(x1, 420),Point(x2,420))
wordLine.draw(win)
l+=1
x1+=40
x2+=40
guessCounter = 0
textCheck = 0
invalidText = Text(Point(600,100), 'You did not enter a valid letter.')
invalidText.setTextColor('red')
indexes = []
while guessCounter < 6:
#text entry box
textEntry = Entry(Point(600,180),10)
textEntry.draw(win)
guessText = Text(Point(600,150), 'Guess a letter:')
guessText.draw(win)
#user has to click this box to confirm the letter
enterBox = Rectangle(Point(580,200), Point(620,220))
enterBox.setFill('white')
enterBox.draw(win)
clickText = Text(Point(600,210), 'Enter')
clickText.draw(win)
click = win.getMouse()
x = click.getX()
y = click.getY()
if 580 < x < 620 and 200 < y < 220:
guess = textEntry.getText().lower().strip()
if guess not in alphabet:
if textCheck == 0:
invalidText.draw(win)
textCheck = 1
else:
if textCheck == 1:
invalidText.undraw()
textCheck = 0
for letter in word:
if letter == guess:
indexes.append(word.index(guess))
print(indexes)
win.getMouse()
win.close()
return returnStuff
#list with various words pertaining to nanotechnology
words = ['nanotechnology', 'science', 'nanometre' , 'strength', 'chemistry',
'small', 'molecule', 'light' , 'weight', 'technology', 'materials',
'property', 'physics', 'engineering', 'matter', 'waterloo', 'nanobot',
'reaction', 'structure', 'cells']
#picks a random word from the list
word = random.choice(words)
#this variable ensures it opens the game the first time
initialCall = 1
#stores the returnValue for the first call
returnValue = hangman(word)
#sets the initialCall to 0 after first call
if returnValue['1st']==1:
initialCall=0
#Calls the game function again if user wishes
while initialCall == 1 or returnStuff['again'] == 1:
returnValue = hangman(word)
I am making Hangman in Python graphics. I apologize for the huge block of code, it all works fine, I just thought it must be useful. The part of the code that I'm concerned about is this:
else:
if textCheck == 1:
invalidText.undraw()
textCheck = 0
for letter in word:
if letter == guess:
indexes.append(word.index(guess))
print(indexes)
This block of code will be executed when the user's letter guess is in the alphabet, I then run through each letter in the chosen word, and if at any point a letter in the word is the same as the guess letter, I store the index of that letter in a empty list so I can use that to tell the computer where to draw the letters on the empty lines.
It works fine, with the exception of when there is a duplicate letter in the word. For example, engineering has 3 es. Unfortunately, .index() only records the index for when the letter appears the first time, and it disregards the other letters. What is the work around for this so I can get the indexes of all 3 es in that word, instead of 3 indexes of just the first e. For testing purposes, I have printed the chosen word and the index list on the console so I can see what's going on and so I don't actually have to guess a letter.
you can do something like this
def indexes(word,letter):
for i,x in enumerate(word):
if x == letter:
yield i
test
>>> list( indexes("engineering","e") )
[0, 5, 6]
>>>
this function is a generator, that is a lazy function that only give result when asked for then, to get a individual result you use next, the functions is execute until the first yield then return the result and stop its execution and remember where it was, until another call to next is executed in witch point resume execution from the previous point until the next yield, if the is no more raise StopIteration, for example:
>>> word="engineering"
>>> index_e = indexes(word,"e")
>>> next(index_e)
0
>>> print(word)
engineering
>>> next(index_e)
5
>>> next(index_e)
6
>>> next(index_e)
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
next(index_e)
StopIteration
>>>
to update a list with the result of this function, you can use the extend method
>>> my_list=list()
>>> index_e = indexes(word,"e")
>>> my_list.extend( index_e )
>>> my_list
[0, 5, 6]
>>>
generator are used in cases where their result is only a intermediary step to something else because they use a minimum amount of memory, but in this case maybe you want the whole thing so use it as the first example or remake the function to return a list in the first place like this
def indexes(word,letter):
result = list()
for i,x in enumerate(word):
if x == letter:
result.append(i)
return result
sorry if I confuse you with the yield thing.

Resources