In short i want to number chars in order from 1 to n without changing the position of the chars in a list.
Suppose I have a list called key = ['c', 'a', 't'] How would i go about
assigning a number to each letter depending on where it is situated in the alphabet with respect to the other letters. Starting at 1 and going until len(key) such that our key becomes [ 2, 1, 3]
I'm really stumped. I have a way to convert them to numbers but very unsure as to how to compare them such that the above happens any help, tips, ideas or explanations would be appreciated.
this is what i have so far...
import string
key = list(input("enter key: ").upper())
num = []
for i in key:
num.append(string.ascii_uppercase.index(i)+1)
This solution assumes that duplicate entries should be assigned the same number, so that
# ['c','a','t'] -> [2, 1, 3]
# ['c','a','t','c','a','t'] -> [2, 1, 3, 2, 1, 3]
You can write a simple function like this:
def get_alphabet_pos(lst):
uniques = sorted(set(lst)) # set() to filter uniques, then order by value
numbers = {letter: i+1 for i, letter in enumerate(uniques)} # build a lookup dict
return [numbers[key] for key in lst]
get_alphabet_pos('cat') # [2, 1, 3]
So here's what happens in the function:
In line 1 of the function we convert your list to a set to remove any duplicate values. From the docs # https://docs.python.org/3/tutorial/datastructures.html#sets:
A set is an unordered collection with no duplicate elements.
Still in line 1 we sort the set and convert it back into a list. Thanks to #StefanPochmann for pointing out that sorted() takes care of the list conversion.
In line 2, we use enumerate() so we can iterate over the indices and values of our list of unique values: https://docs.python.org/3/library/functions.html#enumerate
The rest of line 2 is a simple dict comprehension to build a dictionary of letter -> number mappings. We use the dictionary in line 3 to look up the numbers for each letter in our input dict.
You might have to modify this slightly depending on how you want to handle duplicates :)
I really wonder why the second one gives an error:
It would be really great if some one could pls highlight can we use lists as an element in set or it's not allowed to have any mutable object inside a set.
1)
>>> x = set(["Perl", "Python", "Java"])
>>> x
set(['Python', 'Java', 'Perl'])
>>>
2)
>>> cities = set((["Python","Perl"], ["Paris", "Berlin", "London"]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>>
As you noted, you can't have a list as a member of a set (because it's not hashable).
I think you've been confused by the repr of the set in your first example. The output set(['Python', 'Java', 'Perl']) doesn't indicate that the set contains a 3-element list. Rather, it contains the three strings, with the list just being part of the notation the repr uses (since the set constructor expects an iterable of items). Note that the order of the items changes from your input to the the arbitrary order of the output!
In Python 3, the set type's repr uses set-literal syntax instead:
>>> x = set(["Perl", "Python", "Java"])
>>> x
{'Java', 'Perl', 'Python'}
for i in range(0,len(text_list)):
if (text_list[i] == "!" and text_list[i+1].isupper()):
print "something"
else:
text_list.pop(i)
Traceback (most recent call last):
File "test.py", line 12, in <module>
if (text_list[i]=="!" and text_list[i+1].isupper()):
Error:
IndexError: list index out of range
I want to remove all the exclamation marks from a text file that are not at the end of a sentence.
When i becomes len(text_list) - 1, i + i is out of bounds. This is your first problem. The second problem is that you are popping within the for loop. This changes the size of the list.
I suggest to save the indices to be removed in a separate list, and then pop them after the loop is finished.
to_remove = []
for i in range(0,len(text_list) - 1):
if (text_list[i]=="!" and text_list[i+1].isupper()):
print "something"
else:
to_remove.append(i)
for i in reversed(to_remove):
text_list.pop(i) # use del if you don't need the popped value
When your i will become last index of the text_list then "text_list[i+1].isupper()" will give you error because i+1 will be out of index range. You can do something like this :
for i in range(0,len(text_list)):
if(i!=len(text_list-1)):
if (text_list[i]=="!" and text_list[i+1].isupper()):
print "something"
else:
text_list.pop(i)
Hi so I am trying to write a function hack() that takes no arguments and returns an iterator over all possible passwords.
Basically, I have to user an iterator to brute force a password. All I know from the question is that:
The password consists of three segments.
The first segment of the password is a concatenation of two words in the following list of words: ["hello", "BEGONE", "dog", "MrCool"]
The middle segment is "Donkey20"
And the last segment consists of two digits that together (i.e. 1 and 7 = 17), are no larger than 38. (And at least 0)
My method of thinking is this:
Find all the possible combinations of POSSIBLE_WORDS by using permutations(). (Find all segment 1 possibilities)
For each combination in the new list, add "Donkey20" to the end. (For example: helloBEGONEDonkey20)
Find all possible combinations between the elements in THAT list and POSSIBLE_NUMBERS.
Create an iterator that iterates over all these possible passwords, and return it
My current code only is able to do step 2, but instead of Donkey20 being at the end of each combination it's at the start. (e.g. Donkey20helloBEGONE instead of helloBEGONEDonkey20)
POSSIBLE_WORDS = ["hello", "BEGONE", "dog", "MrCool"]
MIDDLE = "Donkey20"
possible_numbers1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
possible_numbers2 = [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]
possible_numbers3 = [29, 30, 31, 32, 33, 34, 35, 36, 37, 38]
POSSIBLE_NUMBERS = possible_numbers1 + possible_numbers2 + possible_numbers3
from itertools import permutations, combinations
def hack():
first_words = [''.join(word) for word in permutations(POSSIBLE_WORDS, 2)]
first_words.append(MIDDLE)
first_half = [''.join(word) for word in permutations(first_words, 2)]
Any way to fix this issue? How do I finish the remainder of the steps? Is there a different approach I could use to code this program?
Any help would be very much appreciated!
First of all, there is no reason to build up POSSIBLE_NUMBERS like that. Just use range(39) or list(range(39)) instead.
Your intention in
first_words.append(MIDDLE)
was almost certainly not to tack the single word "Donkey20" onto the end of the list of all possible first parts but was instead to tack it onto the end of each first word. I think that your intention in that part of the code can be better expressed by getting rid of that line as well as the following line and just use the single line
first_half = [word + MIDDLE for word in first_words]
When you are putting together the final possible passwords, you are going to need to turn the numbers into strings. Doubtless you already know about str() but that function has the drawback that str(1) is '1' whereas you probably want '01'. In this context, you might want to use format() since format(1,'02') returns '01'.
This should be enough of a hint to get you going. Since this seems to be homework I don't want to say any more.
I have a list of numbers and I want to extract N elements as lists, and store them in another list.
Example:
list1 = [1,2,3,4,5,6,7,8,9]
resultList = [[1,2,3],[4,5,6],[7,8,9]]
I've done the following
def getLines(square, N):
i = 0
line = [None]*N
lines = list()
for elt in square:
line[i] = elt
i += 1
if i == N:
lines.append(line)
i = 0
return lines
Why do I always get the last list three times
[[7,8,9],[7,8,9],[7,8,9]]
when I call the function getLines(list1, 3).
I also tried to eliminate the temporary list and add the elements directly to resultList like this:
def getLines(square, N):
i = 0
j = 0
lines = [[None]*N]*N # Need to be initialized to be able to index it.
for elt in square:
lines[i][j] = elt
j += 1
if j == N:
i += 1
j = 0
return lines
The last group is still appearing N times. Any hints on how to fix that?
This is because you are creating only one inner list object, and altering it.
In pseudocode, what you are doing is:
Create a list called line assigning [None, None, None] to it
Create an empty list called lines
For three times:
-- Pick n items from the square list
-- Assign these three items to line[0], line[1] and line[2]
-- Append line to lines
So, what you are doing is assigning to individual items of line. This is important - you're not making a new object each time, you're changing individual items in the line list.
At the end of it all, line will point to the list [7, 8, 9]. And you can see lines as being substantially [line, line, line] (a list of three times the same object), so specifically now it will point to [[7,8,9], [7,8,9], [7,8,9]].
To solve this, possibly the solution that most keeps your original code is to re-define line after appending it. This way, the variable name line will refer to a different list each time, and you won't have this problem.
def getLines(square, N):
i = 0
line = [None]*N
lines = list()
for elt in square:
line[i] = elt
i += 1
if i == N:
lines.append(line)
line = [None]*N # Now `line` points to a different object
i = 0
return lines
Of course, there is leaner, more Pythonic code that can do the same thing (I see that an answer has already been given).
EDIT - Ok, here goes a somehow more detailed explanation.
Perhaps one of the key concepts is that lists are not containers of other objects; they merely hold references to other objects.
Another key concept is that when you change an item in a list (item assignment), you're not making the whole list object become another object. You're merely changing a reference inside it. This is something we give for granted in a lot of situations, but somehow becomes counter-intuitive when we'd want things to go the other way and "recycle" a list.
As I was writing in the comments, if list was a cat named Fluffy, every time you're appending you're creating a mirror that points to Fluffy. So you can dress Fluffy with a party hat, put a mirror pointing to it, then give Fluffy a clown nose, put on another mirror, then dress Fluffy as a ballerina, add a third mirror, and when you look at the mirrors, all three of them will show the ballerina Fluffy. (Sorry Fluffy).
What I mean is that in practice in your first script, when you do the append:
lines.append(line)
by the first concept I mentioned, you are not making lines contain the current status of line as a separate object. You are appending a reference to the line list.
And when you do,
line[i] = elt
by the second concept, of course line is always the same object; you're just changing what's referenced at the i-th position.
This is why, at the end of your script, lines will appear to "contain three identical objects": because you actually appended three references to the same object. And when you ask to see the content of lists, you will read, three times, the list object in its current status.
In the code I provided above, I re-define the name lists to make it reference a brand new list every time it's been appended to lists:
lines.append(line)
line = [None]*N # Now `line` points to a different object
This way, at the end of the script I have "three different cats" appended, and each one was conveniently named Fluffy just until I had appended it, to give room for a new Fluffy list after that.
Now, in your second script, you do something similar. The key instruction is:
lines = [[None]*N]*N # Need to be initialized to be able to index it.
In this line, you are creating two objects:
- the list [None, None, None]
- the list named lines, which contains N references to the same list [None, None, None].
What you did was just to create straight away Fluffy and the three mirrors pointing at him.
In fact if you change lines[0][2], or lines[1][2], you're just changing the same item [2] of your same Fluffy.
What you actually wanted to do is,
lines = [[None]*N for i in range(N)]
which creates three different cats - I mean, lists, and have lines point to the three.
You might consider solving this like:
def getLines(square, N):
return [square[i:i + N] for i in range(0, len(square), N)]
For example: getLines([1, 2, 3, 4, 5, 6, 7, 8, 9], 3) will return [[1, 2, 3], [4, 5, 6], [7, 8, 9]], or getLines([1, 2, 3, 4, 5, 6, 7, 8, 9], 2) results in [[1, 2], [3, 4], [5, 6], [7, 8], [9]], and so on.