I want to get a nesting list using python,looking likes
[[['a'],'a'],'a']
So,I wrote a recursion function to get it.
def recursion(x,i):
x.append(list('spam'))
x=[x]
i-=1
print('i value is %d'%i)
print(x)
if i>0:
print('start new recursion!')
recursion(x,i)
print('callback x"s value:',x)
#return x
But ,if I call this function like
x=[]
recursion(x,4)
The result of x is
[['s', 'p', 'a', 'm']]
I don't understand it,and I found that this function seem had get the right value of x through the stdout,
i value is 3
[[['s', 'p', 'a', 'm']]]
start new recursion!
i value is 2
[[[['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']]]
start new recursion!
i value is 1
[[[[['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']]]
start new recursion!
i value is 0
[[[[[['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']]]
callback x"s value: [[[[[['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']]]
callback x"s value: [[[[['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']]
callback x"s value: [[[['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']]
callback x"s value: [[['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']]
Please tell me what happen to x and why the function don't return x's value I wanted.Thanks so much,and apologize for my poor english.
#
Thanks for your all attention.The value of x I want to get is
[[[[[['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']], ['s', 'p', 'a', 'm']]]
I'm sorry that I missed it in the first post.
I'm also not sure what you want to happen, but if you want to split a string into its characters and put them into nested lists, this function works.
def recursion(l,s):
if s == "":
return l;
elif len(l) == 0:
nL = [s[0]]
return recursion(nL,s[1:])
else:
nL = [l,s[0]]
return recursion(nL,s[1:])
So for example
print recursion([],"spam")
would output
[[[['s'], 'p'], 'a'], 'm']
I'm not sure what you want to happen, but here's what is happening:
def recursion(x,i):
x.append(list('spam'))
x=[x]
Here, x becomes [['s','p','a','m']]. But it doesn't change after this. When you call recursion(x,i) a few lines later, this does not affect the original value of x.
Maybe if you do x = recursion(x,i) instead it will give you what you want, because x will actually be change at the top level.
I think you might be confused by the fact that a Python string ("spam" is a string) is in many ways equivalent to a Python list. You can index them, get their len(), etc. In particular, pretty much anything you do in square brackets works for both string and list types.
Your first example is of a single-byte string, [[['a'], 'a'], 'a'] but you don't give us some key details: what was the input that you expected to produce this output?
For example, the input might have been:
func('a', 3)
Or might have been:
func('aaa')
Or might have been:
func(['a'], 3) # or ,2)
Or might have been:
func(['a', 'a', 'a'])
Any of those would be a reasonable starting point for a return value of [[['a'], 'a'], 'a'].
Solution
Because your example function takes a second parameter, i, I'm going to assume there is a real need for it. So let's go with the simplest possible case:
def func(lst, times):
"""
Given a list and a multiplier > 0, return a "nested" list with
the contents of the original list repeated (nested) that many
times:
Input: [a,b],2
Output: [[a,b],a,b]
"""
assert times > 0
if times == 1:
return lst[:]
else:
result = lst[:]
result.insert(0, func(lst, times-1))
return result
for times in range(1,4):
print(func(['a', 'b'], times))
Alternate
Here's a simpler function, that doesn't assume a list:
def func(content, times):
"""
Given content and a multiplier > 0, return a set of nested lists,
with the requested depth, each containing optionally any further
nested lists and the given content.
Input: 'content', 2
Output: [['content'], 'content']
"""
assert(times > 0)
if times == 1:
result = [content]
else:
result = [func(content, times-1)]
result.append(content)
return result
for times in range(1,4):
print(func('a', times))
Related
I wrote a Python3 script to solve a picoCTF challenge. I received the encrypted flag which is:
cvpbPGS{c33xno00_1_f33_h_qrnqorrs}
From its pattern, I thought it is encoded using caesar cipher. So I wrote this script:
alpha_lower = ['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']
alpha_upper = ['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']
text = 'cvpbPGSc33xno00_1_f33_h_qrnqorrs '
for iterator in range(len(alpha_lower)):
temp = ''
for char in text:
if char.islower():
ind = alpha_lower.index(char)
this = ind + iterator
while this > len(alpha_lower):
this -= len(alpha_lower)
temp += alpha_lower[this]
elif char.isupper():
ind = alpha_upper.index(char)
that = ind + iterator
while that > len(alpha_upper):
that -= len(alpha_upper)
temp += alpha_upper[that]
print(temp)
I understand what the error means. I can't understand where the flaw is to fix. Thanks in advance.
Sorrym here is the error:
Desktop>python this.py
cvpbPGScxnofhqrnqorrs
dwqcQHTdyopgirsorpsst
exrdRIUezpqhjstpsqttu
Traceback (most recent call last):
File "C:\Users\user\Desktop\this.py", line 18, in <module>
temp += alpha_lower[this]
IndexError: list index out of range
Your approach has an error because ind + iterator can have a maximum possible value of 50, which is more than len(alpha_lower)
To fix it, you can use the modulus operator: (ind + iterator) % len(alpha_lower)
There is a less complicated way to decode the Caesar cipher. Instead of using two different lists for upper and lower case characters, you should use the ord() and chr() functions to manipulate the unicode values.
Why that break is simple :
If this==len(alpha_lower) then we won't enter your loop:
while this > len(alpha_lower):
And thus when trying temp += alpha_lower[this] it will return an error.
An index must be strictly inferior to the size of the array. Your condition should have been while this >= len(alpha_lower):.
As pointed out, a better method here is to use a modulus.
I have this list which contains letters, and I need to check if a pre-determined word located in another list is horizontally inside this list of letters.
i.e.:
mat_input = [['v', 'e', 'd', 'j', 'n', 'a', 'e', 'o'], ['i', 'p', 'y', 't', 'h', 'o', 'n', 'u'], ['s', 'u', 'e', 'w', 'e', 't', 'a', 'e']]
words_to_search = ['python', 'fox']
I don't need to tell if a word was not found, but if it was I need to tell which one.
My problem is that so far I've tried to compare letter by letter, in a loop similar to this:
for i in range(n): # n = number of words
for j in range(len(word_to_search[i])): # size of the word I'm searching
for k in range(h): # h = height of crossword
for m in range(l): # l = lenght of crossword
But it's not working, inside the last loop I tried several if/else conditions to tell if the whole word was found. How can I solve this?
You can use str.join:
mat_input = [['v', 'e', 'd', 'j', 'n', 'a', 'e', 'o'], ['i', 'p', 'y', 't', 'h', 'o', 'n', 'u'], ['s', 'u', 'e', 'w', 'e', 't', 'a', 'e']]
words_to_search = ['python', 'fox']
joined_input = list(map(''.join, mat_input))
results = {i:any(i in b or i in b[::-1] for b in joined_input) for i in words_to_search}
Output:
{'python': True, 'fox': False}
I'd start by joining each sublist in mat_input into one string:
mat_input_joined = [''.join(x) for x in mat_input]
Then loop over your words to search and simply use the in operator to see if the word is contained in each string:
for word_to_search in words_to_search:
result = [word_to_search in x for x in mat_input_joined]
print('Word:',word_to_search,'found in indices:',[i for i, x in enumerate(result) if x])
Result:
Word: python found in indices: [1]
Word: fox found in indices: []
I have a list of letters in Python that I would like to split into even-length chunks that will display as rows. For pedagogical reasons, I want to do it without using and libraries (including numpy or Pandas). No, this is not a homework question-- I'm teaching myself.
In R I would be using a vector instead of a list; a simple as.matrix(vector, ncol = n) would do the trick. Is there an equivalent in Python?
As an example, I've tried the following based on other SO answers:
alphabet = map(chr, range(65, 91))
print 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']
def chunks(l, n):
n = max(1, n)
return [l[i:i + n] for i in range(0, len(l), n)]
print chunks(alphabet, 4)
> [['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']]
That generally works, but I would like the output to look like this:
[['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']]
Ideally, I will extend the functionality to make the "most square" rectangle. Ie, I will pull out the highest factors of the length of the list and then use the smaller number as the number of columns, so if possible I want a very generalized answer.
I would define a new function that prints the chunks line by line.
def print_chunks(chunk_result):
for chunk in chunks:
print(chunk)
I believe this will give you the output you're looking for.
To get slicing behaviour, you will want to implement your own class. I have quickly whipped out something that should get you started, but I have not checked it thoroughly.
class Chunk(object):
"""docstring for Chunk"""
def __init__(self, l, n):
super(Chunk, self).__init__()
self.chunks = self.chunk(l, n)
def __repr__(self):
"""
Done in a non-standard way.
"""
for chunk in self.chunks:
print(chunk)
def __getitem__(self, key):
if isinstance(key, slice):
return self.chunks[i] for i in xrange(*key.indices(len(self.chunks)))
elif isinstance(key, int):
if key < 0:
key += len(self.chunks)
if key >= len(self):
raise IndexError('The index {0} is out of range'.format(key))
return self.chunks[i]
For reference, I looked at the following SO posts:
Python: Implementing slicing in __getitem__
Just use print each list within:
for line in chunks(alphabet, 4):
print line
This is a problem that could apply to any language, but I'll use python to show it.
Say you have a list of numbers, ls = [0,100,200,300,400]
You can insert an element at any index, but the elements must always stay in numerical order. Duplicates are not allowed.
For example, ls.insert(2, 150) results in ls = [0,100,150,200,300,400]. The elements are in the correct order, so this is correct.
However, ls.insert(3, 190) results in ls = [0,100,200,190,300,400]. This is incorrect.
For any index i, what is the best number x to use in ls.insert(i,x) to minimize the number of sorts?
My first intuition was to add half the difference between the previous and next numbers to the previous one. So to insert a number at index 3, x would equal 200 + (300-200), or 250. However this approaches the asymptote far too quickly. When the differences get too close to 0, I could restore the differences by looping through and changing each number to produce a larger difference. I want to choose the best number for x so to minimize the number of times I need to reset.
EDIT
The specific problem I'm applying this to is a iOS app with a list view. The items in the list are represented in a Set, and each object has an attribute orderingValue. I can't use an Array to represent the list (due to issues with cache-server syncing), so I have to sort the set each time I display the list to the user. In order to do this, the orderingValue must be stored on the ListItem object.
One additional detail is, due to the nature of the UI, the user is probably more likely to add an item to the top or bottom of the list rather than insert it in the middle.
You can generate sort keys indefinitely if you use strings rather than integers. That's because a lexicographical ordering of strings puts an infinite number of values between any two strings (as long as the larger isn't the smaller one followed by "a").
Here's a function to generate a lowercase string key between two other keys:
def get_key_str(low="a", high="z"):
if low == "":
low = "a"
assert(low < high)
for i, (a, b) in enumerate(zip(low, high)):
if a < b:
mid = chr((ord(a) + ord(b))//2) # get the character half-way between a and b
if mid != a:
return low[:i] + mid
else:
return low[:i+1] + get_key_str(low[i+1:], "z")
return low + get_key_str("a", high[len(low):])
It always returns a string s such that "a" <= low < s < high <= "z". "a" and "z" are never used themselves as keys, they're special values to indicate the boundaries of the possible results.
You'd call it with get_key_str([lst[i-1], lst[i]) to get a value to insert before the value at index i. You can insert and generate a value in one go with lst.insert(i, get_key_str(lst[i-1], lst[i])). Obviously though, the ends of the list need special handling.
The default values are set so that you can omit an argument to get a value to insert at the start or the end. That is, call get_key_str(high=lst[0]) to get a value to put at the start of your list or get_key_str(lst[-1]) to get a value to append to at the end. You can also explicitly pass "a" as low or "z" as high, if that's easier. With no arguments, it will return "m", which is a reasonable first value to put in an empty list.
It's possible that you could tune this a bit to give shorter keys when you're mostly adding at the start or end, but that would be a bit more complicated. This version should have its keys grow roughly evenly if you're inserting randomly.
Here's an example of doing some random inserts:
>>> import random
>>> lst = []
>>> for _ in range(10):
index = random.randint(0, len(lst))
print("inserting at", index)
if index == 0:
low = "a"
else:
low = lst[index-1]
if index == len(lst):
high = "z"
else:
high = lst[index]
lst.insert(index, get_key_str(low, high))
print(lst)
inserting at 0
['m']
inserting at 1
['m', 's']
inserting at 2
['m', 's', 'v']
inserting at 2
['m', 's', 't', 'v']
inserting at 2
['m', 's', 'sm', 't', 'v']
inserting at 0
['g', 'm', 's', 'sm', 't', 'v']
inserting at 3
['g', 'm', 's', 'sg', 'sm', 't', 'v']
inserting at 2
['g', 'm', 'p', 's', 'sg', 'sm', 't', 'v']
inserting at 2
['g', 'm', 'n', 'p', 's', 'sg', 'sm', 't', 'v']
inserting at 3
['g', 'm', 'n', 'o', 'p', 's', 'sg', 'sm', 't', 'v']
And here's how it behaves if we then do a bunch of inserts at the start and end:
>>> for _ in range(10):
lst.insert(0, get_key_str(high=lst[0])) # start
lst.insert(len(lst), get_key_str(low=lst[-1])) # end
print(lst)
['d', 'g', 'm', 'n', 'o', 'p', 's', 'sg', 'sm', 't', 'v', 'x']
['b', 'd', 'g', 'm', 'n', 'o', 'p', 's', 'sg', 'sm', 't', 'v', 'x', 'y']
['am', 'b', 'd', 'g', 'm', 'n', 'o', 'p', 's', 'sg', 'sm', 't', 'v', 'x', 'y', 'ym']
['ag', 'am', 'b', 'd', 'g', 'm', 'n', 'o', 'p', 's', 'sg', 'sm', 't', 'v', 'x', 'y', 'ym', 'ys']
['ad', 'ag', 'am', 'b', 'd', 'g', 'm', 'n', 'o', 'p', 's', 'sg', 'sm', 't', 'v', 'x', 'y', 'ym', 'ys', 'yv']
['ab', 'ad', 'ag', 'am', 'b', 'd', 'g', 'm', 'n', 'o', 'p', 's', 'sg', 'sm', 't', 'v', 'x', 'y', 'ym', 'ys', 'yv', 'yx']
['aam', 'ab', 'ad', 'ag', 'am', 'b', 'd', 'g', 'm', 'n', 'o', 'p', 's', 'sg', 'sm', 't', 'v', 'x', 'y', 'ym', 'ys', 'yv', 'yx', 'yy']
['aag', 'aam', 'ab', 'ad', 'ag', 'am', 'b', 'd', 'g', 'm', 'n', 'o', 'p', 's', 'sg', 'sm', 't', 'v', 'x', 'y', 'ym', 'ys', 'yv', 'yx', 'yy', 'yym']
['aad', 'aag', 'aam', 'ab', 'ad', 'ag', 'am', 'b', 'd', 'g', 'm', 'n', 'o', 'p', 's', 'sg', 'sm', 't', 'v', 'x', 'y', 'ym', 'ys', 'yv', 'yx', 'yy', 'yym', 'yys']
['aab', 'aad', 'aag', 'aam', 'ab', 'ad', 'ag', 'am', 'b', 'd', 'g', 'm', 'n', 'o', 'p', 's', 'sg', 'sm', 't', 'v', 'x', 'y', 'ym', 'ys', 'yv', 'yx', 'yy', 'yym', 'yys', 'yyv']
So at the start you may end up with keys prefixed by as, and at the end you'll get keys prefixed by ys.
As far as the 'best' value is concerned, it is always going to be halfway through the previous and the next element. And it is going to reach the asymptote.
One way to delay arrival at the asymptote if there are repeated insertions at a particular index is to decrement the previous and increment the next value (I'm assuming you are allowed to do this) every time you perform the insert.
So, for ls.insert(2,150), after insertion
ls[1] = ls[1] - (ls[1] - ls[0])/2
ls[3] = ls[3] + (ls[4] - ls[3])/2
For every other insertion, this rule will hold, and assuming insertions are at random indices, you would have a fair amount of time before you need to increase each number's value.
Also, the moment you encounter two adjacent numbers with a difference of 1, you would, of course, have to loop through the numbers and increase them.
There is a recursive selection sort in the upcoming question that has to be done.
def selsort(l):
"""
sorts l in-place.
PRE: l is a list.
POST: l is a sorted list with the same elements; no return value.
"""
l1 = list("sloppy joe's hamburger place")
vl1 = l1
print l1 # should be: """['s', 'l', 'o', 'p', 'p', 'y', ' ', 'j', 'o', 'e', "'", 's', ' ', 'h', 'a', 'm', 'b', 'u', 'r', 'g', 'e', 'r', ' ', 'p', 'l', 'a', 'c', 'e']"""
ret = selsort(l1)
print l1 # should be """[' ', ' ', ' ', "'", 'a', 'a', 'b', 'c', 'e', 'e', 'e', 'g', 'h', 'j', 'l', 'l', 'm', 'o', 'o', 'p', 'p', 'p', 'r', 'r', 's', 's', 'u', 'y']"""
print vl1 # should be """[' ', ' ', ' ', "'", 'a', 'a', 'b', 'c', 'e', 'e', 'e', 'g', 'h', 'j', 'l', 'l', 'm', 'o', 'o', 'p', 'p', 'p', 'r', 'r', 's', 's', 'u', 'y']"""
print ret # should be "None"
I know how to get this by using key → l.sort(key=str.lower). But the question wants me to extract the maximum element, instead of the minimum, only to .append(...) it on to a recursively sorted sublist.
If I could get any help I would greatly appreciate it.
So. Do you understand the problem?
Let's look at what you were asked to do:
extract the maximum element, instead of the minimum, only to .append(...) it on to a recursively sorted sublist.
So, we do the following things:
1) Extract the maximum element. Do you understand what "extract" means here? Do you know how to find the maximum element?
2) Recursively sort the sublist. Here, "the sublist" consists of everything else after we extract the maximum element. Do you know how recursion works? You just call your sort function again with the sublist, relying on it to do the sorting. After all, the purpose of your function is to sort lists, so this is supposed to work, right? :)
3) .append() the maximum element onto the result of sorting the sublist. This should not require any explanation.
Of course, we need a base case for the recursion. When do we have a base case? When we can't follow the steps exactly as written. When does that happen? Well, why would it happen? Answer: we can't extract the maximum element if there are no elements, because then there is no maximum element to extract.
Thus, at the beginning of the function we check if we were passed an empty list. If we were, we just return an empty list, because sorting an empty list results in an empty list. (Do you see why?) Otherwise, we go through the other steps.
the sort method should do what you want. If you want the reverse, just use list.reverse()
If your job is to make your own sort method, that can be done.
Maybe try something like this:
def sort(l):
li=l[:] #to make new copy
newlist = [] #sorted list will be stored here
while len(li) != 0: #while there is stuff to be sorted
bestindex = -1 #the index of the highest element
bestchar = -1 #the ord value of the highest character
bestcharrep = -1 #a string representation of the best character
i = 0
for v in li:
if ord(v) < bestchar or bestchar == -1:#check if string is lower than old best
bestindex = i #Update best records
bestchar = ord(v)
bestcharrep = v
i += 1
del li[bestindex] #delete retrieved element from list
newlist.append(bestcharrep) #add element to new list
return newlist #return the sorted list