How to shuffle two strings to a set of string in Python3 - python-3.x

How can I shuffle two strings s||t (shuffle(s, t)) with the given requirement that the first char always stands in front of the second one in s and t as well no matter we shuffle. The result returns as a set of strings without duplicates.
I have the following test:
print(shuffle('ab', 'cd'))
Result:
['abcd', 'acbd', 'acdb', 'cabd', 'cadb', 'cdab']
Thanks a lot.

This method will shuffle two strings and return a list of shuffles between them where the order of the characters is the same as in the original strings. If there are duplicate characters there will be duplicate results as well.
def shuffle(s1, s2):
if len(s1) == 1:
return [s2[:i] + s1 + s2[i:] for i in range(len(s2) + 1)]
if len(s2) == 1:
return [s1[:i] + s2 + s1[i:] for i in range(len(s1) + 1)]
return [s1[0]+ s for s in shuffle(s1[1:], s2)] + [s2[0] + s for s in shuffle(s1, s2[1:])]
print shuffle("ab", "cd")
It works by getting the first character of each string and recursively shuffling the rest and adding this character to each element in the list. When there is one character remaining on each of the strings it returns a list where the character is added in each position of the other string. Hope it helps.

So you can apply a condition on final shuffled list to generate a new list from the shuffled one:
S=shuffle('ab','cd')
nl=[]
for w in S:
if(w.index('a')<w.index('b') and w.index('c')<w.index('d')):
nl.append(w)
So nl is your new list as per your requirement:)

If I understood the question correctly, this should work. Note, as you add letters to this, it becomes a long running problem. 4 letters have 6 possible combination for each entry in the list. 8 letters have 5,040 possible combinations for each entry in the list.
import random
import math
InputList = ['ab','cd']
PossibleUniqueCombinations = math.factorial(len("".join(InputList))-1)
print (PossibleUniqueCombinations)
TargetList = []
UniqueCombinationList = []
for lst in InputList:
UniqueCnt = 0
FirstChar = lst[0]
TheRest = list(lst[1:])
while UniqueCnt < PossibleUniqueCombinations:
if InputList.index(lst) == 0:
LeftList = []
else:
LeftList = InputList[0:InputList.index(lst)]
RightList = list(InputList[InputList.index(lst)+1:])
TargetList = LeftList + TheRest + RightList
TargetStr = ''.join(TargetList)
TargetStr = ''.join(random.sample(TargetStr, len(TargetStr)))
ShuffledStr = FirstChar + ''.join(TargetStr)
try:
FndIdx = UniqueCombinationList.index(ShuffledStr)
except ValueError:
UniqueCombinationList.append(ShuffledStr)
UniqueCnt += 1
for combo in UniqueCombinationList:
print(combo)

Related

How do you check if a given input is a palindrome?

I need to check if the input is a palindrome.
I converted the input to a string and compared the input with the reverse of the input using list slicing. I want to learn a different way without converting input to a string.
def palindrome(n):
num = str(n)
if num == num[::-1]:
return True
Assuming that n is a number, you can get digits from right to left and build a number with those digits from left to right:
n = 3102
m = n
p = 0
while m:
p = p*10 + m%10 # add the rightmost digit of m to the right of p
m //= 10 # remove the rightmost digit of m
print(p) # 2013
Hence the function:
def palindrome(n):
m = n
p = 0
while m:
p = p*10 + m%10
m //= 10
return p == n
Note that:
if num == num[::-1]:
return True
will return None if num != num[::-1] (end of the function). You should write:
if num == num[::-1]:
return True
else:
return False
Or (shorter and cleaner):
return num == num[::-1]
There can be 2 more approaches to that as follows:
Iterative Method: Run loop from starting to length/2 and check first character to last character of string and second to second last one and so on. If any character mismatches, the string wouldn’t be palindrome.
Sample Code Below:
def isPalindrome(str):
for i in xrange(0, len(str)/2):
if str[i] != str[len(str)-i-1]:
return False
return True
One Extra Variable Method: In this method, user take a character of string one by one and store in a empty variable. After storing all the character user will compare both the string and check whether it is palindrome or not.
Sample Code Below:
def isPalindrome(str):
w = ""
for i in str:
w = i + w
if (str==w):
return True
return False
You can try the following approach:
Extract all the digits from the number n
In each iteration, append the digit to one list (digits) and at that digit at the beginning of another list (reversed_digits)
Once all digits have been extracted, compare both lists
def palindrome(n):
digits = []
reversed_digits = []
while n > 0:
digit = n % 10
digits.append(digit)
reversed_digits.insert(0, digit)
n //= 10
return digits == reversed_digits
Note: this might not be the most efficient way to solve this problem, but I think it is very easy to understand.

How can I generate a list starting with the first value in a range?

I have a string that indicates a range of values: "A1C - A1H"
I need to be able to create a list of all the values in that range, meaning: ['A1C', 'A1D', 'A1E', 'A1F', 'A1G', 'A1H']
list = []
range = "A1C - A1H"
code = range[:2]
range_end = range[-3:]
for letter in ascii_uppercase:
order = code+letter
if order not in range_end:
list.append(order)
else:
list.append(range_end)
break
print(list)
The code runs, as is but it creates a list with the first 'A1A', 'A1B' values which I don't need:
['A1A', 'A1B', 'A1C', 'A1D', 'A1E', 'A1F', 'A1G', 'A1H']
How can I generate the list starting with 'A1C'?
Start the "for letter in ascii_uppercase" two char later
list = []
range = "A1C - A1H"
code = range[:2]
range_end = range[-3:]
count = 0
for letter in ascii_uppercase:
if count > 1:
order = code+letter
if order not in range_end:
list.append(order)
else:
list.append(range_end)
break
count += 1
print(list)
You can use the built-in ord and chr functions with a list comprehension instead to generate the desired list:
l = ['A1' + chr(i) for i in range(ord('C'), ord('H') + 1)]
l would become:
['A1C', 'A1D', 'A1E', 'A1F', 'A1G', 'A1H']
You can compare letter code and start loop when it is greater than starting point of string :
import string
def generate(string_data):
code = string_data[:2]
range_end = string_data[-3:]
sub_range = string_data[2:-6]
result=[]
for letter in string.ascii_uppercase:
if ord(letter)< ord(sub_range):
pass
elif code+letter == range_end:
result.append(code+letter)
break
else:
result.append(code+letter)
return result
output:
['A1C', 'A1D', 'A1E', 'A1F', 'A1G', 'A1H']
alternative solution:
This is not best solution but you can also slice the list from list in your code:
list_data = []
range_data = "A1C - A1H"
code = range_data[:2]
range_end = range_data[-3:]
for letter in string.ascii_uppercase:
order = code+letter
if order not in range_end:
list_data.append(order)
else:
list_data.append(range_end)
break
print(list_data[list_data.index(range_data[:3]):list_data.index(range_end)+1])
Note: Don't use list and range as variable name , They have special meaning in Python.

Python lists and ranges

I'm trying to practice my python so I can improve. I'm kinda stuck and not sure how to proceed. I get an error saying "can only concatenate list(not 'int') to list." I'll leave my code and what I'm trying to do below.
Input a word string (word)
find the string length of word
use range() to iterate through each letter in word (can use to range loops)
Save odd and even letters from the word as lists
odd_letters: starting at index 0,2,...
even_letters: starting at index 1,3,...
print odd and even lists
word = input("Type: ")
word = list(word)
print(word)
odd_letters = []
even_letters = []
length = int(len(word))
for i in range(length):
if i/2 == 0:
even_letters = even_letters + i
elif i/2 != 0:
odd_letters = odd_letters + i
print(even_letters)
print(odd_letters)
I wrote this... Let me know what you think...
word = input("Choose a word to test: ")
word_len = len(word)
print(word," contains ",word_len," letters")
odd_letters = []
even_letters = []
for i in range(1,len(word),2):
even_letters.append(word[i])
for i in range(0,word_len,2):
odd_letters.append(word[i])
print("Odd letters are: ",odd_letters)
print("Even letters are: ",even_letters)
Your code is good, but i decided to find a quicker solution for the program you want. This is my code:
word = str(input("Enter word:"))
store_1 = [x for x in word]
store_2 = []
for idx, val in enumerate(store_1):
store_2.append(idx)
even_numbers = [y for y in store_2 if y%2 == 0]
odd_numbers = [z for z in store_2 if z%2 == 1]
print("List of Even numbers:",even_numbers)
print("List of Odd numbers:",odd_numbers)
The variable 'word' takes in the word from the user. The list 'store_1' uses list comprehension to separate the letters the in the word and store it. Next, i enumerate through 'store_1' and use the variable 'store_2' to only store the indexes of 'store_1'.
Next, I declare another variable 'even_numbers' that uses list comprehension to iterate through 'store_2' and find the even numbers. The next variable 'odd_numbers' also uses list comprehension to find the odd numbers in 'store_2'.
Then, it just prints the even and odd lists to the user. Hope this helps :)
You cannot add an integer to a list, as you have attempted to do here:
even_letters = even_letters + i
You can instead do this (which is now adding a list to a list, which is valid):
even_letters = even_letters + [i]
Or, use append to alter the list in-place, adding the new element to the end:
even_letters.append(i)
Few things:
You cannot "add" an integer directly to a list using '+'. Using append() would be best.
str and str types can be concatenated using '+' so you could change odd_letters and even_letters to str as shown below.
also, by adding 'i' to even and odd, you are adding the iteration variable value.
Since you want the letter to be appended, you need to refer the list index i.e word[i]
and the first letter of what is entered will be at an odd position :)
word = input("Type: ")
word = list(word)
print(word)
odd_letters = ''
even_letters = ''
length = int(len(word))
for i in range(1,length+1):
if i%2 == 0:
even_letters = even_letters + word[i-1]
else:
odd_letters = odd_letters + word[i-1]
print("even_letters",even_letters)
print("odd_letters",odd_letters)
word=input()
word_num=len(word)
print(word_num)
odd_num=[]
even_num=[]
for letters in range(0,word_num,2):
odd_num.append(word[letters])
for letters in range(1,word_num,2):
even_num.append(word[letters])
print(odd_num)
print(even_num)
This is the answer it works with every word, and follows all the requirements.

python3 Why does max( listOfStrings) not return the longest element? [duplicate]

I have a list of variable length and am trying to find a way to test if the list item currently being evaluated is the longest string contained in the list. And I am using Python 2.6.1
For example:
mylist = ['abc','abcdef','abcd']
for each in mylist:
if condition1:
do_something()
elif ___________________: #else if each is the longest string contained in mylist:
do_something_else()
Surely there's a simple list comprehension that's short and elegant that I'm overlooking?
From the Python documentation itself, you can use max:
>>> mylist = ['123','123456','1234']
>>> print max(mylist, key=len)
123456
def longestWord(some_list):
count = 0 #You set the count to 0
for i in some_list: # Go through the whole list
if len(i) > count: #Checking for the longest word(string)
count = len(i)
word = i
return ("the longest string is " + word)
or much easier:
max(some_list , key = len)
What should happen if there are more than 1 longest string (think '12', and '01')?
Try that to get the longest element
max_length,longest_element = max([(len(x),x) for x in ('a','b','aa')])
And then regular foreach
for st in mylist:
if len(st)==max_length:...
To get the smallest or largest item in a list, use the built-in min and max functions:
lo = min(L)
hi = max(L)
As with sort, you can pass in a "key" argument that is used to map the list items before they are compared:
lo = min(L, key=int)
hi = max(L, key=int)
http://effbot.org/zone/python-list.htm
Looks like you could use the max function if you map it correctly for strings and use that as the comparison. I would recommend just finding the max once though of course, not for each element in the list.
len(each) == max(len(x) for x in myList) or just each == max(myList, key=len)
def LongestEntry(lstName):
totalEntries = len(lstName)
currentEntry = 0
longestLength = 0
while currentEntry < totalEntries:
thisEntry = len(str(lstName[currentEntry]))
if int(thisEntry) > int(longestLength):
longestLength = thisEntry
longestEntry = currentEntry
currentEntry += 1
return longestLength

Is there a pythonic way to insert space characters at random positions of an existing string?

is there a pythonic way to implement this:
Insert /spaces_1/ U+0020 SPACE
characters into /key_1/ at random
positions other than the start or end
of the string.
?
There /spaces_1/ is integer and /key_1/ is arbitrary existing string.
Thanks.
strings in python are immutable, so you can't change them in place. However:
import random
def insert_space(s):
r = random.randint(1, len(s)-1)
return s[:r] + ' ' + s[r:]
def insert_spaces(s):
for i in xrange(random.randrange(len(s))):
s = insert_space(s)
return s
Here's a list based solution:
import random
def insert_spaces(s):
s = list(s)
for i in xrange(len(s)-1):
while random.randrange(2):
s[i] = s[i] + ' '
return ''.join(s)
I'm going to arbitrarily decide you never want two spaces inserted adjacently - each insertion point used only once - and that "insert" excludes "append" and "prepend".
First, construct a list of insertion points...
insert_points = range (1, len (mystring))
Pick out a random selection from that list, and sort it...
import random
selected = random.sample (insert_points, 5)
selected.sort ()
Make a list of slices of your string...
selected.append (len (mystring)) # include the last slice
temp = 0 # start with first slice
result = []
for i in selected :
result.append (mystring [temp:i])
temp = i
Now, built the new string...
" ".join (result)
Just because no one used map yet:
import random
''.join(map(lambda x:x+' '*random.randint(0,1), s)).strip()
This method inserts a given number of spaces to a random position in a string and takes care that there are no double spaces after each other:
import random
def add_spaces(s, num_spaces):
assert(num_spaces <= len(s) - 1)
space_idx = []
space_idx.append(random.randint(0, len(s) - 2))
num_spaces -= 1
while (num_spaces > 0):
idx = random.randint(0, len(s) - 2)
if (not idx in space_idx):
space_idx.append(idx)
num_spaces -= 1
result_with_spaces = ''
for i in range(len(s)):
result_with_spaces += s[i]
if i in space_idx:
result_with_spaces += ' '
return result_with_spaces
If you want to add more than one space, then go
s[:r] + ' '*n + s[r:]
Here it comes...
def thePythonWay(s,n):
n = max(0,min(n,25))
where = random.sample(xrange(1,len(s)),n)
return ''.join("%2s" if i in where else "%s" for i in xrange(len(s))) % tuple(s)
We will randomly choose the locations where spaces will be added - after char 0, 1, ... n-2 of the string (n-1 is the last character, and we will not place a space after that); and then insert the spaces by replacing the characters in the specified locations with (the original character) + ' '. This is along the lines of Steve314's solution (i.e. keeping the assumption that you don't want consecutive spaces - which limits the total spaces you can have), but without using lists.
Thus:
import random
def insert_random_spaces(original, amount):
assert amount > 0 and amount < len(original)
insert_positions = sorted(random.sample(xrange(len(original) - 1), amount))
return ''.join(
x + (' ' if i in insert_positions else '')
for (i, x) in enumerate(original)
)

Resources