Whats happening this code. Anagram as a substring in a string - python

I found this question posted on here, but couldn't comment or ask a question, so I am creating a new question.
The original post stated the following:
t = "abd"
s = "abdc"
s trivially contains t. However, when you sort them, you get the strings abd and abcd, and the in comparison fails. The sorting gets other letters in the way.
Instead, you need to step through s in chunks the size of t.
t_len = len(t)
s_len = len(s)
t_sort = sorted(t)
for start in range(s_len - t_len + 1):
chunk = s[start:start+t_len]
if t_sort == sorted(chunk):
# SUCCESS!!
In the for loop why are they taking S-len then subtracting t_len? Why are they adding 1 at the end?

alvits and d_void already explained the value of start; I won't repeat that.
I strongly recommend that you learn some basic trace debugging. Insert some useful print statements to follow the execution. For instance:
Code:
t = "goal"
s = "catalogue"
t_len = len(t)
s_len = len(s)
t_sort = sorted(t)
print "lengths & sorted", t_len, s_len, t_sort
for start in range(s_len - t_len + 1):
chunk = s[start:start+t_len]
print "LOOP start=", start, "\tchunk=", chunk, sorted(chunk)
if t_sort == sorted(chunk):
print "success"
Output:
lengths & sorted 4 9 ['a', 'g', 'l', 'o']
LOOP start= 0 chunk= cata ['a', 'a', 'c', 't']
LOOP start= 1 chunk= atal ['a', 'a', 'l', 't']
LOOP start= 2 chunk= talo ['a', 'l', 'o', 't']
LOOP start= 3 chunk= alog ['a', 'g', 'l', 'o']
success
LOOP start= 4 chunk= logu ['g', 'l', 'o', 'u']
LOOP start= 5 chunk= ogue ['e', 'g', 'o', 'u']
Does that help illustrate what's happening in the loop?

Related

Scratch lottery function

I am working on a scratch lottery command on my python game.
My Scratch lottery function is below.
def lottery(player_money):
print('scratch lottery :')
print('price: 500')
print('wins :')
print(' all 6 same : $100000')
print(' all 5 same : $50000')
print(' all 4 same : $10000')
print(' all 3 same : $1000')
print(' all 2 same : $300')
print('do you want to buy it?? yes/no')
buy = input('> ')
if buy == 'no':
print('please come back later!!')
return player_money
elif buy == 'yes':
print('_____________')
lottery_results = ['x', 'o', 'p', 'k', 'm', 'e', 'a', 'w']
a = random.choice(lottery_results)
b = random.choice(lottery_results)
c = random.choice(lottery_results)
d = random.choice(lottery_results)
e = random.choice(lottery_results)
f = random.choice(lottery_results)
print('| ' + a + ' | ' + b + ' | ' + c + ' |')
print('|_' + d + '_|_' + e + '_|_' + f + '_|')
if...
I Have no idea what to put after
if...
I don't want to make if for all possible solutions since that would be like 2 million ifs.
I want to make it like below
If 2 of the str in a or b or c or d or e or f is the same:
print('Since 2 matched, you won $300!')
player_money += 300
return player_money
I don't know how to code(ify) the phrase that goes after if and the phrase that goes after if that I put in wouldn't work and there would be a error
Any suggestions on how I could make this work?
You're off to a good start, but there is something that could make your life a lot easier. Firstly, lets use random.choices to create a list from the possible letters:
import random
pool = ['x', 'o', 'p', 'k', 'm', 'e', 'a', 'w']
results = random.choices(pool, k=len(pool))
Note: k can be any integer - it determines the length of the resulting list
This is going to yield a list with random letters from the pool:
['e', 'x', 'a', 'm', 'x', 'k', 'o', 'p']
Now, you can think about how you can build your if statement off of a list.
If 2 of the str in a or b or c or d or e or f is the same:
This sounds like a job for iteration. Remember, we don't have the variables a, b, c, etc. anymore; rather, they're stored in a list.
for letter in pool:
if results.count(letter) > 1:
# match found
Above, you iterate through the pool variable, which holds all of the possible values. On every loop of that iteration, we check if the current letter that resides inside the pool list exists more than once in the results list. This means that there was a match.
More
You can dynamically increase the player's money count with only a few lines if you keep a list of the possible winnings that correspond with a certain number of matches. For example,
winnings = [100, 200, 300, 400, 500, 600, 700, 800]
Here, 100 is chosen if there are two of the same letter (1 match). If there are three of the same letter (2 matches), 200 is chosen.
player_money = 0
for letter in pool:
result_count = results.count(letter)
player_money += winnings[result_count-2] if result_count > 1 else 0
Above, the line winnings[result_count-2] if result_count > 1 else 0 determines how much the player should receive based off of their matches. We have to subtract 2 from result_count because, remember, python indexing starts from 0, and if there are two of the same letter in the resulting list (1 match), we need to subtract 2 to make it 0, which selects the correct winnings.
If you want to go by your own code then, You can use Counter.
from itertools import Counter
then you can use it like:
Counter([a,b,c,d,e,f]))
to check if any of the values is 2.
Use random.sample() to gather 6 results in a single line.
Then we can simply loop over the sample and check if each draw exists in lottery_results. It also may be better to store the winnings in a dict so we can easily retrieve the amount without too much hassle.
import random
winnings = {6: 100000, 5: 50000, 4: 10000, 3: 1000, 2: 300}
lottery_results = ['x', 'o', 'p', 'k', 'm', 'e', 'a', 'w']
user_numbers = random.sample(lottery_results, 6)
#['m', 'k', 'e', 'a', 'x', 'p']
matches = 0
for draw in user_numbers:
if draw in lottery_results:
matches += 1
print(f'Congrats! You matched {matches} and won ${winnings[matches]}')
#Congrats! You matched 6 and won $100000
You have further issues with the way you have set out to achieve your goal. You're generating the results for the draw from the results of the house. This means you will always match 6.
We can show this by implementing a possible_draws to generate both our results and user draws from. We will use the alphabet as an example.
import string
possible_draws = list(string.ascii_lowercase)
#['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']
lottery_results = random.sample(possible_draws, 8)
#['x', 'h', 'o', 'p', 'j', 'n', 'm', 'c']
user_draws = random.sample(possible_draws, 6)
#['h', 'r', 'u', 't', 'f', 'n']
matches = 0
for draw in user_draws:
if draw in lottery_results:
matches += 1
if matches < 2:
print('No win this time!')
else:
print(f'Congrats! You matched {matches} and won ${winnings[matches]}')

How do I alphabetically sort an array of strings without any sort functions? Python

When solving the following problem:
"Assuming you have a random list of strings (for example: a, b, c, d, e, f, g), write a program that will sort the strings in alphabetical order.
You may not use the sort command."
I run into the problem of running strings through the following code, which sometimes gets me duplicated strings in final list
I am fairly new to python and our class just started to look at numpy, and functions in that module, and im not sure of any being used in the code (except any sort function).
import numpy as np
list=[]
list=str(input("Enter list of string(s): "))
list=list.split()
print() # for format space purposes
listPop=list
min=listPop[0]
newFinalList=[]
if(len(list2)!=1):
while(len(listPop)>=1):
for i in range(len(listPop)):
#setting min=first element of list
min=listPop[0]
if(listPop[i]<=min):
min=listPop[i]
print(min)
listPop.pop(i)
newFinalList.append(min)
print(newFinalList)
else:
print("Only one string inputted, so already alphabatized:",list2)
Expected result of ["a","y","z"]
["a","y","z"]
Actual result...
Enter list of string(s): a y z
a
a
a
['a', 'a', 'a']
Enter list of string(s): d e c
d
c
d
d
['c', 'd', 'd']
Selection sort: for each index i of the list, select the smallest item at or after i and swap it into the ith position. Here's an implementation in three lines:
# For each index i...
for i in range(len(list)):
# Find the position of the smallest item after (or including) i.
j = list[i:].index(min(list[i:])) + i
# Swap it into the i-th place (this is a no-op if i == j).
list[i], list[j] = list[j], list[i]
list[i:] is a slice (subset) of list starting at the ith element.
min(list) gives you the smallest element in list.
list.index(element) gives you the (first) index of element in list.
a, b = b, a atomically swaps the values of a and b.
The trickiest part of this implementation is that when you're using index to find the index of the smallest element, you need to find the index within the same list[i:] slice that you found the element in, otherwise you might select a duplicate element in an earlier part of the list. Since you're finding the index relative to list[i:], you then need to add i back to it to get the index within the entire list.
You can implement Quick sort for same:
def partition(arr,low,high):
i = ( low-1 )
pivot = arr[high]
for j in range(low , high):
if arr[j] <= pivot:
i = i+1
arr[i],arr[j] = arr[j],arr[i]
arr[i+1],arr[high] = arr[high],arr[i+1]
return ( i+1 )
def quickSort(arr,low,high):
if low < high:
pi = partition(arr,low,high)
quickSort(arr, low, pi-1)
quickSort(arr, pi+1, high)
arr = ['a', 'x', 'p', 'o', 'm', 'w']
n = len(arr)
quickSort(arr,0,n-1)
print ("Sorted list is:")
for i in range(n):
print ("%s" %arr[i]),
output:
Sorted array is:
a m o p w x
Mergesort:
from heapq import merge
from itertools import islice
def _ms(a, n):
return islice(a,n) if n<2 else merge(_ms(a,n//2),_ms(a,n-n//2))
def mergesort(a):
return type(a)(_ms(iter(a),len(a)))
# example
import string
import random
L = list(string.ascii_lowercase)
random.shuffle(L)
print(L)
print(mergesort(L))
Sample run:
['h', 'g', 's', 'l', 'a', 'f', 'b', 'z', 'x', 'c', 'r', 'j', 'q', 'p', 'm', 'd', 'k', 'w', 'u', 'v', 'y', 'o', 'i', 'n', 't', 'e']
['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']

Solving a "colored Quxes" coding challenge with recursion

I am trying to solve some of the coding challenges that I find online. However I was stopped by the below problem. I tried to solve it using recursion but I feel I am missing a very important concept in recursion. My code works for all of the below examples except the last one it will break down.
Can someone point to me the mistake that I made in this recursion code? Or maybe guide me through solving the issue?
I know why my code breaks but I don't know how to get around the "pass by object reference" in Python which I think creating the bigger problem for me.
The coding question is:
On a mysterious island there are creatures known as Quxes which come in three colors: red, green, and blue. One power of the Qux is that if two of them are standing next to each other, they can transform into a single creature of the third color.
Given N Quxes standing in a line, determine the smallest number of them remaining after any possible sequence of such transformations.
For example, given the input ['R', 'G', 'B', 'G', 'B'], it is possible to end up with a single Qux through the following steps:
Arrangement | Change
----------------------------------------
['R', 'G', 'B', 'G', 'B'] | (R, G) -> B
['B', 'B', 'G', 'B'] | (B, G) -> R
['B', 'R', 'B'] | (R, B) -> G
['B', 'G'] | (B, G) -> R
['R'] |
________________________________________
My code is:
class fusionCreatures(object):
"""Regular Numbers Gen.
"""
def __init__(self , value=[]):
self.value = value
self.ans = len(self.value)
def fusion(self, fus_arr, i):
color = ['R','G','B']
color.remove(fus_arr[i])
color.remove(fus_arr[i+1])
fus_arr.pop(i)
fus_arr.pop(i)
fus_arr.insert(i, color[0])
return fus_arr
def fusionCreatures1(self, arr=None):
# this method is to find the smallest number of creature in a row after fusion
if arr == None:
arr = self.value
for i in range (0,len(arr)-1):
#print(arr)
if len(arr) == 2 and i >= 1 or len(arr)<2:
break
if arr[i] != arr[i+ 1]:
arr1 = self.fusion(arr, i)
testlen = self.fusionCreatures1(arr)
if len(arr) < self.ans:
self.ans = len(arr)
return self.ans
Testing array (all of them work except the last one):
t1 = fusionCreatures(['R','G','B','G','B'])
t2 = fusionCreatures(['R','G','B','R','G','B'])
t3 = fusionCreatures(['R','R','G','B','G','B'])
t4 = fusionCreatures(['G','R','B','R','G'])
t5 = fusionCreatures(['G','R','B','R','G','R','G'])
t6 = fusionCreatures(['R','R','R','R','R'])
t7 = fusionCreatures(['R', 'R', 'R', 'G', 'G', 'G', 'B', 'B', 'B'])
print(t1.fusionCreatures1())
print(t2.fusionCreatures1())
print(t3.fusionCreatures1())
print(t4.fusionCreatures1())
print(t5.fusionCreatures1())
print(t6.fusionCreatures1())
print(t7.fusionCreatures1())
I'll start by mentioning that there is a deductive approach that works in O(n) and is detailed in this blog post. It boils down to checking the parity of the counts of the three types of elements in the list to determine which of a few fixed outcomes occurs.
You mention that you'd prefer to use a recursive approach, which is O(n!). This is a good start because it can be used as a tool for helping arrive at the O(n) solution and is a common recursive pattern to be familiar with.
Because we can't know whether a given fusion between two Quxes will ultimately lead to an optimal global solution we're forced to try every possibility. We do this by walking over the list and looking for potential fusions. When we find one, perform the transformation in a new list and call fuse_quxes on it. Along the way, we keep track of the smallest length achieved.
Here's one approach:
def fuse_quxes(quxes, choices="RGB"):
fusion = {x[:-1]: [x[-1]] for x in permutations(choices)}
def walk(quxes):
best = len(quxes)
for i in range(1, len(quxes)):
if quxes[i-1] != quxes[i]:
sub = quxes[:i-1] + fusion[quxes[i-1], quxes[i]] + quxes[i+1:]
best = min(walk(sub), best)
return best
return walk(quxes)
This is pretty much the direction your provided code is moving towards, but the implementation seems unclear. Unfortunately, I don't see any single or quick fix. Here are a few general issues:
Putting the fusionCreatures1 function into a class allows it to mutate external state, namely self.value and self.ans. self.value in particular is poorly named and difficult to keep track of. It seems like the intent is to use it as a reference copy to reset arr to its default value, but arr = self.value means that when fus_arr is mutated in fusion(), self.value is as well. Everything is pretty much a reference to one underlying list.
Adding slices to these copies at least makes the program easier to reason about, for example, arr = self.value[:] and fus_arr = fus_arr[:] in the fusion() function. In short, try to write pure functions.
self.ans is also unclear and unnecessary; better to keep the result value relegated to a local variable within the recursive function.
It seems unnecessary to put a stateless function into a class unless it's a purely static method and the class is acting as a namespace.
Another cause of cognitive overload are branching statements like if and break. We want to minimize the frequency and nesting of these. Here is fusionCreatures1 in pseudocode, with annotations for mutations and complex interactions:
def fusionCreatures1():
if ...
read mutated global state
for i in len(arr):
if complex length and index checks:
break
if arr[i] != arr[i+ 1]:
impure_func_that_changes_arr_length(arr)
recurse()
if new best compared to global state:
mutate global state
You'll probably agree that it's pretty difficult to mentally step through a run of this function.
In fusionCreatures1(), two variables are unused:
arr1 = self.fusion(arr, i)
testlen = self.fusionCreatures1(arr)
The assignment arr1 = self.fusion(arr, i) (along with the return fus_arr) seems to indicate a lack of understanding that self.fusion is really an in-place function that mutates its argument array. So calling it means arr1 is arr and we have another aliased variable to reason about.
Beyond this, neither arr1 or testlen are used in the program, so the intent is unclear.
A good linter will pick up these unused variables and identify most of the other complexity issues I've mentioned.
Mutating a list while looping over it is usually disastrous. self.fusion(arr, i) mutates arr inside a loop, making it very difficult to reason about its length and causing an index error when the range(len(arr)) no longer matches the actual len(arr) in the function body (or at least necessitating an in-body precondition). Making self.fusion(arr, i) pure using a slice, as mentioned above, fixes this problem but reveals that there is no recursive base case, resulting in a stack overflow error.
Avoid variable names like arr, arr1, value unless the context is obvious. Again, these obfuscate intent and make the program difficult to understand.
Some minor style suggestions:
Use snake_case per PEP-8. Class names should be TitleCased to differentiate them from functions. No need to inherit from object--that's implicit.
Use consistent spacing around functions and operators: range (0,len(arr)-1): is clearer as range(len(arr) - 1):, for example. Use vertical whitespace around blocks.
Use lists instead of typing out t1, t2, ... t7.
Function names should be verbs, not nouns. A class like fusionCreatures with a method called fusionCreatures1 is unclear. Something like QuxesSolver.minimize(creatures) makes the intent a bit more obvious.
As for the solution I provided above, there are other tricks worth considering to speed it up. One is memoization, which can help avoid duplicate work (any given list will always produce the same minimized length, so we just store this computation in a dict and spit it back out if we ever see it again). If we hit a length of 1, that's the best we can do globally, so we can skip the rest of the search.
Here's a full runner, including the linear solution translated to Python (again, defer to the blog post to read about how it works):
from collections import defaultdict
from itertools import permutations
from random import choice, randint
def fuse_quxes_linear(quxes, choices="RGB"):
counts = defaultdict(int)
for e in quxes:
counts[e] += 1
if not quxes or any(x == len(quxes) for x in counts.values()):
return len(quxes)
elif len(set(counts[x] % 2 for x in choices)) == 1:
return 2
return 1
def fuse_quxes(quxes, choices="RGB"):
fusion = {x[:-1]: [x[-1]] for x in permutations(choices)}
def walk(quxes):
best = len(quxes)
for i in range(1, len(quxes)):
if quxes[i-1] != quxes[i]:
sub = quxes[:i-1] + fusion[quxes[i-1], quxes[i]] + quxes[i+1:]
best = min(walk(sub), best)
return best
return walk(quxes)
if __name__ == "__main__":
tests = [
['R','G','B','G','B'],
['R','G','B','R','G','B'],
['R','R','G','B','G','B'],
['G','R','B','R','G'],
['G','R','B','R','G','R','G'],
['R','R','R','R','R'],
['R', 'R', 'R', 'G', 'G', 'G', 'B', 'B', 'B']
]
for test in tests:
print(test, "=>", fuse_quxes(test))
assert fuse_quxes_linear(test) == fuse_quxes(test)
for i in range(100):
test = [choice("RGB") for x in range(randint(0, 10))]
assert fuse_quxes_linear(test) == fuse_quxes(test)
Output:
['R', 'G', 'B', 'G', 'B'] => 1
['R', 'G', 'B', 'R', 'G', 'B'] => 2
['R', 'R', 'G', 'B', 'G', 'B'] => 2
['G', 'R', 'B', 'R', 'G'] => 1
['G', 'R', 'B', 'R', 'G', 'R', 'G'] => 2
['R', 'R', 'R', 'R', 'R'] => 5
['R', 'R', 'R', 'G', 'G', 'G', 'B', 'B', 'B'] => 2
Here is my suggestion.
First, instead of "R", "G" and "B" I use integer values 0, 1, and 2. This allows nice and easy fusion between a and b, as long as they are different, by simply doing 3 - a - b.
Then my recursion code is:
def fuse_quxes(l):
n = len(l)
for i in range(n - 1):
if l[i] == l[i + 1]:
continue
else:
newn = fuse_quxes(l[:i] + [3 - l[i] - l[i + 1]] + l[i+2:])
if newn < n:
n = newn
return n
Run this with
IN[5]: fuse_quxes([0, 0, 0, 1, 1, 1, 2, 2, 2])
Out[5]: 2
Here is my attempt of the problem
please find the description in comment
inputs = [['R','G','B','G','B'],
['R','G','B','R','G','B'],
['R','R','G','B','G','B'],
['G','R','B','R','G'],
['G','R','B','R','G','R','G'],
['R','R','R','R','R'],
['R', 'R', 'R', 'G', 'G', 'G', 'B', 'B', 'B'],]
def fuse_quxes(inp):
RGB_set = {"R", "G", "B"}
merge_index = -1
## pair qux with next in line and loop through all pairs
for i, (q1, q2) in enumerate(zip(inp[:-1], inp[1:])):
merged = RGB_set-{q1,q2}
## If more than item remained in merged after removing q1 and q2 qux can't fuse
if(len(merged))==1:
merged = merged.pop()
merge_index=i
merged_color = merged
## loop through the pair until result of fuse is different from qux in either right
## or left side
if (i>0 and merged!=inp[i-1]) or ((i+2)<len(inp) and merged!=inp[i+2]):
break
print(inp)
## merge two qux which results to qux differnt from either its right or left else do any
## possible merge
if merge_index>=0:
del inp[merge_index]
inp[merge_index] = merged_color
return fuse_quxes(inp)
else:
## if merge can't be made break the recurssion
print("Result", len(inp))
print("_______________________")
return len(inp)
[fuse_quxes(inp) for inp in inputs]
output
['R', 'G', 'B', 'G', 'B']
['R', 'R', 'G', 'B']
['R', 'B', 'B']
['G', 'B']
['R']
Result 1
_______________________
['R', 'G', 'B', 'R', 'G', 'B']
['R', 'G', 'B', 'R', 'R']
['R', 'G', 'G', 'R']
['B', 'G', 'R']
['B', 'B']
Result 2
_______________________
['R', 'R', 'G', 'B', 'G', 'B']
['R', 'B', 'B', 'G', 'B']
['G', 'B', 'G', 'B']
['R', 'G', 'B']
['R', 'R']
Result 2
_______________________
['G', 'R', 'B', 'R', 'G']
['G', 'G', 'R', 'G']
['G', 'B', 'G']
['R', 'G']
['B']
Result 1
_______________________
['G', 'R', 'B', 'R', 'G', 'R', 'G']
['G', 'G', 'R', 'G', 'R', 'G']
['G', 'B', 'G', 'R', 'G']
['R', 'G', 'R', 'G']
['B', 'R', 'G']
['B', 'B']
Result 2
_______________________
['R', 'R', 'R', 'R', 'R']
Result 5
_______________________
['R', 'R', 'R', 'G', 'G', 'G', 'B', 'B', 'B']
['R', 'R', 'B', 'G', 'G', 'B', 'B', 'B']
['R', 'G', 'G', 'G', 'B', 'B', 'B']
['B', 'G', 'G', 'B', 'B', 'B']
['R', 'G', 'B', 'B', 'B']
['R', 'R', 'B', 'B']
['R', 'G', 'B']
['R', 'R']
Result 2
_______________________
[1, 2, 2, 1, 2, 5, 2]

Why do these two programs return different output?

I have two programs that are supposed to reverse a list of chars (strings with length 1). While the second program gives the correct output, the first one doesn't.
Here is program #1:
string = ['h', 'e', 'l', 'l', 'l', 'o']
y = len(string) / 2
for letter in string:
x = string.index(letter)
if x < y:
string[x], string[-1-x] = string[-1-x], string[x]
Here is program #2:
string = ['h', 'e', 'l', 'l', 'l', 'o']
y = len(string) / 2
x = 0
while x < y:
if x < y:
string[x], string[-1-x] = string[-1-x], string[x]
x += 1
My second program successfully reverses the string, but the first one returns ['o', 'e', 'l', 'l', 'l', 'h']. I'm glad I found a solution but would prefer to use .index() rather than counting each loop.
There is an anti-pattern in your first program.
x = string.index(letter)
Consider when you're indexing for the 2nd or 3rd 'l'... x will always be 2. The condition x < y will kick in and reverse the positions of 'e' and the second 'l'.
Here's some debugging:
(Notice that x is 2 at the second, third, and fourth iterations when it should be 2, 3, and 4 respectively.)
Iter 0:
letter = 'h'; x = 0; swap √; string = ['o', 'e', 'l', 'l', 'l', 'h']
# ^------------------------^
Iter 1:
letter = 'e'; x = 1; swap √; string = ['o', 'l', 'l', 'l', 'e', 'h']
# ^--------------^
Iter 2:
letter = 'l'; x = 2; swap √; string = ['o', 'l', 'l', 'l', 'e', 'h']
# ^----^
Iter 3: !
letter = 'l'; x = 2; swap √; string = ['o', 'l', 'l', 'l', 'e', 'h']
# ^----^
Iter 4: !
letter = 'l'; x = 2; swap √; string = ['o', 'e', 'l', 'l', 'l', 'h']
# ^--------------^
Iter 5:
letter = 'l'; x = 5; swap X; string = ['o', 'e', 'l', 'l', 'l', 'h']
Pythonically, you should use enumerate to keep track of the index:
y = len(string) / 2
for i, _ in enumerate(string):
if i < y:
string[i], string[-1-i] = string[-1-i], string[i]
(An underscore was substituted for letter following PEP8 style guides.)
Or even better:
string = string[::-1]
I see that the variable "string" is list of strings. You can reverse it as simple as this:
string = ['h', 'e', 'l', 'l', 'l', 'o']
string.reverse()
string
This should print ['o', 'l', 'l', 'l', 'e', 'h']

Python Itertools Code Optimisation

Given question (the contest is now over)
a password consists of exactly n lowercase English letters.
the password is melodious, meaning that consonants can only be next to
vowels and vowels can only be next to consonants. Example: bawahaha
the password cannot contain the letter y (because it's both a
consonant and vowel).
the first letter of the password can be either
a vowel or consonant.
Given the length, n, of the password,
print all of the possible passwords that meet the conditions above.
Input Format
The line of input contains the integer (the length of the password).
Constraints
Output Format
Print each of the possible passwords, one per line. The order of the passwords does not matter.
My Code in Python:
import sys
import itertools
n = int(raw_input().strip())
consonants = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z']
vowels = ['a', 'e', 'i', 'o', 'u']
test4 = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z', 'a', 'e', 'i', 'o', 'u']
answer = set(itertools.product(test4, repeat=n))
for letters in answer:
for j in xrange(len(letters)):
flag = 1
if j != len(letters) - 1:
if letters[j] in vowels and letters[j+1] in vowels:
flag = 0
break
if letters[j] in consonants and letters[j+1] in consonants:
flag = 0
break
if flag:
for j in letters:
sys.stdout.write(j)
print ""
Is there a better way to do this?
Of course there's a better way (if you mean faster). You can generate a itertools.product where you don't have to "discard" items.
You can simply create a product of vowel, consonant, vowel, consonant, ... (alternating both lists n times) and one which starts with consonant, vowel, consonant, vowel, .... The returned items will always satisfy the condition so all that needs to be done is printing them.
import itertools
def alternating(seq1, seq2, length):
"""Generator that alternatingly yields seq1 and seq2, `length` times"""
assert length >= 0
for _ in range(length // 2):
yield seq1
yield seq2
if length % 2 == 1:
yield seq1
consonants = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z']
vowels = ['a', 'e', 'i', 'o', 'u']
n = int(raw_input().strip())
# Starts with vowel
for comb in itertools.product(*list(alternating(vowels, consonants, n))):
print(''.join(comb))
# Starts with consonant
for comb in itertools.product(*list(alternating(consonants, vowels, n))):
print(''.join(comb))
That way you can reduce the number of possible candidates.
Your approach gave 25**n items, while the new approach only generates 2 * 5**(n//2)*20**(n//2) (if n even) or 5**(n//2 + 1) * 20 ** (n//2) + 5**(n//2) * 20 ** (n//2 + 1) (if n odd) items.
For n=5 that means: What generated originally 9765625 items (almost 10 million!) from product will now only generate 250000 items. Even ignoring the (possibly very expensive) check if your sequence satisfies the problem-condition (which is obsolete now) you generated 40 times more items in your product!

Categories

Resources