This is not probably a common question but I want to CREATE duplicates and INSERT it randomly in my String. Just like the following example.
I have this file :
AppleStrawberryBananaCitrusOrange
And I expected this kind of output :
trusppleStrawbeApplertrusryBananaCitrusOrangepple
In this case my program randomly select a substring of length '4' : 'pple' and 'trus' and duplicates him 'twice(2)' before the insertion.
I think that I could run the program by using the fonction copy with copy.copy() and copy.insert() but I don't really know how to use it randomly.
For the moment;I just write the part of the code for read and write and something else:
import copy
chain='*'
contain = ''
file= raw_input ('Filename:')
x = open(file,'r')
for line in x:
if not(chain in line):
contain+=line
e=copy.copy(contain[4:8])
f=copy.copy(contain[8:12])
y = open('copi','w')
y.write(contain)
y.write(f)
x.close()
Result:
AppleStrawberryBananaCitrusOrange
awbe
As you can see; it doesn't really work like I want. :(
Thanks for your help
Not sure if I understand what you are trying to do.
You'll probably need a library for random selection:
import random
Now here is your input string:
s = "AppleStrawberryBananaCitrusOrange"
print s
You can use random.randint to select a random position and extract a 4-character word:
i = random.randint(0, len(s) - 4)
w = s[i:i+4]
print w
Finally, you can select two more random positions and insert the word via string concatenation:
for j in range(2):
i = random.randint(0, len(s) - 4)
s = s[:i] + w + s[i:]
print s
Output:
AppleStrawberryBananaCitrusOrange
yBan
ApyBanpleSyBantrawberryBananaCitrusOrange
Related
I was previously working on a problem of String encryption: How to add randomly generated characters in specific locations in a string? (obfuscation to be more specific).
Now I am working on its second part that is to remove the randomly added characters and digits from the obfuscated String.
My code works for removing one random character and digit from the string (when encryption_str is set to 1) but for removing two, three .. nth .. number of characters (when encryption_str is set to 2, 3 or n), I don't understand how to modify it.
My Code:
import string, random
def decrypt():
encryption_str = 2 #Doesn't produce correct output when set to any other number except 1
data = "osqlTqlmAe23h"
content = data[::-1]
print("Modified String: ",content)
result = []
result[:0] = content
indices = []
for i in range(0, encryption_str+3): #I don't understand how to change it
indices.append(i)
for i in indices:
del result[i+1]
message = "".join(result)
print("Original String: " ,message)
decrypt()
Output for Encryption level 1 (Correct Output)
Output for Encryption level 2 (Incorrect Output)
That's easy to append chars, that's a bit more difficult to remove them, because that changes the string length and the position of the chars.
But there is an easy way : retrieve the good ones, and for that you just need to iterate with the encryption_str+1 as step (that avoid adding an if on the indice)
def decrypt(content, nb_random_chars):
content = content[::-1]
result = []
for i in range(0, len(content), nb_random_chars + 1):
result.append(content[i])
message = "".join(result)
print("Modified String: ", content)
print("Original String: ", message)
# 3 lines in 1 with :
result = [content[i] for i in range(0, len(content), nb_random_chars + 1)]
Both will give hello
decrypt("osqlTqlmAe23h", 2)
decrypt("osqFlTFqlmFAe2F3h", 3)
Why not try some modulo arithmetic? Maybe with your original string, you try something like:
''.join([x for num, x in enumerate(data) if num % encryption_str == 0])
How about a list comprehension (which is really just a slightly more compact notation for #azro's answer)?
result = content[0::(encryption_str+1)]
That is, take every encryption_str+1'd character from content starting with the first.
How do I take the first character from each string in a list, join them together, then the second character from each string, join them together, and so on - and eventually create one combined string?
eg. if I have strings like these:
homanif
eiesdnt
ltiwege
lsworar
I want the end result to be helloitsmeiwaswonderingafter
I put together a very hackneyed version of this which does the job but produces an extra line of gibberish. Considering this is prone to index going out of range, I don't think this is a good approach:
final_c = ['homanif', 'eiesdnt', 'ltiwege', 'lsworar']
final_message = ""
current_char = 0
for i in range(len(final_c[1])):
for c in final_c:
final_message += c[current_char]
current_char += 1
final_message += final_c[0][:-1]
print(final_message)
gives me helloitsmeiwaswonderingafterhomani when it should simply stop at helloitsmeiwaswonderingafter.
How do I improve this?
Problems related to iterating in some convoluted order can often be solved elegantly with itertools.
Using zip
You can use zip and itertools.chain together.
from itertools import chain
final_c = ['homanif', 'eiesdnt', 'ltiwege', 'lsworar']
final_message = ''.join(chain.from_iterable(zip(*final_c))) # 'helloitsmeiwaswonderingafter'
In the event you needed the strings in final_c to be of different lengths, you could tweak your code a bit by using itertools.zip_longest.
final_message = ''.join(filter(None, chain.from_iterable(zip_longest(*final_c))))
Using cycle
The fun part with itertools is that it offers plenty of clever short solutions for iterating over objects. Here is another using itertools.cycle.
from itertools import cycle
final_c = ['homanif', 'eiesdnt', 'ltiwege', 'lsworara']
final_message = ''.join(next(w) for w in cycle(iter(w) for w in final_c))
You can use a nested comprehension:
x = ["homanif",
"eiesdnt",
"ltiwege",
"lsworar"]
y = "".join(x[i][j]
for j in range(len(x[0]))
for i in range(len(x)))
or use nested joins and zip
y = "".join("".join(y) for y in zip(*x))
Here is a code that works for me :
final_c = ["homanif", "eiesdnt", "ltiwege", "lsworar"]
final_message = ""
current_char = 0
for i in range(len(final_c[1])):
for c in final_c:
final_message += c[current_char]
current_char += 1
# final_message += final_c[0][:-1]
print(final_message)
I hope it helps
I don't understand what you are expecting with the line
final_message += final_c[0][:-1]
The code works just fine without that. Either remove that line or go with something like list comprehensions :
final_message = "".join(final_c[i][j] for j in range(len(final_c[0])) for i in range(len(final_c)))
This gives the expected output:
helloitsmeiwaswonderingafter
looks like you can have a matrix of form nxm where n is the number of words and m is the number of character in a word (the following code will work if all your words have the same length)
import numpy as np
n = len(final_c) # number of words in your list
m = len(final_c[0]) # number of character in a word
array = np_array(''.join([list(w) for w in ''.join(final_c)])
# reshape the array
matrix = array.reshape(n,1,m )
''.join(matrix.transpose().flatten())
I am trying to create a loop where I can generate string using loop. What I am trying to achieve is that I want to create a small collection of strings starting from 1 character to up to 5 characters.
So, starting from sting 1, I want to go to 55555 but this is number so it seems easy if I just add them, but when it comes to alpha numeric, it gets tricky.
Here is explanation,
I have collection of alpha-numeric chars as string s = "123ABC" and what I want to do is that I want to create all possible 1 character string out of it, so I will have 1,2,3,A,B,C and after that I want to add one more digit in length of string so I can get 11, 12, 13 and so on until I get all possible combination out of it up to CA, CB, CC and I want to get it up to CCCCCC. I am confused in loop because I can get it to generate a temp sting but looping inside to rotate characters is tricky,
this is what I have done so far,
i = 0
strr = "123ABC"
while i < len(strr):
t = strr[0] * (i+1)
for q in range(0, len(t)):
# Here I need help to rotate more
pass
i += 1
Can anyone explain me or point me to resource where I can find solution for it?
You may want to use itertools.permutations function:
import itertools
chars = '123ABC'
for i in xrange(1, len(chars)+1):
print list(itertools.permutations(chars, i))
EDIT:
To get a list of strings, try this:
import itertools
chars = '123ABC'
strings = []
for i in xrange(1, len(chars)+1):
strings.extend(''.join(x) for x in itertools.permutations(chars, i))
This is a nested loop. Different depths of recursion produce all possible combinations.
strr = "123ABC"
def prod(items, level):
if level == 0:
yield []
else:
for first in items:
for rest in prod(items, level-1):
yield [first] + rest
for ln in range(1, len(strr)+1):
print("length:", ln)
for s in prod(strr, ln):
print(''.join(s))
It is also called cartesian product and there is a corresponding function in itertools.
I am working on a python project, where I am required to include an input, and another value (which will be manipulated).
For example,
If I enter the string 'StackOverflow', and a value to be manipulated of 'test', the program will make the manipulatable variable equal to the number of characters, by repeating and trimming the string. This means that 'StackOverflow' and 'test' would output 'testtesttestt'.
This is the code I have so far:
originalinput = input("Please enter an input: ")
manipulateinput = input("Please enter an input to be manipulated: ")
while len(manipulateinput) < len(originalinput):
And I was thinking of including a for loop to continue the rest, but am not sure how I would use this to effectively manipulate the string. Any help would be appreciated, Thanks.
An itertools.cycle approach:
from itertools import cycle
s1 = 'Test'
s2 = 'StackOverflow'
result = ''.join(a for a, b in zip(cycle(s1), s2))
Given you mention plaintext - a is your key and b will be the character in the plaintext - so you can use this to also handily manipuate the pairing...
I'm taking a guess you're going to end up with something like:
result = ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(cycle(s1), s2))
# '\x07\x11\x12\x17?*\x05\x11&\x03\x1f\x1b#'
original = ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(cycle(s1), result))
# StackOverflow
There are some good, Pythonic solutions here... but if your goal is to understand while loops rather than the itertools module, they won't help. In that case, perhaps you just need to consider how to grow a string with the + operator and trim it with a slice:
originalinput = input("Please enter an input: ")
manipulateinput = input("Please enter an input to be manipulated: ")
output = ''
while len(output) < len(originalinput):
output += manipulateinput
output = output[:len(originalinput)]
(Note that this sort of string manipulation is generally frowned upon in real Python code, and you should probably use one of the others (for example, Reut Sharabani's answer).
Try something like this:
def trim_to_fit(to_trim, to_fit):
# calculate how many times the string needs
# to be self - concatenated
times_to_concatenate = len(to_fit) // len(to_trim) + 1
# slice the string to fit the target
return (to_trim * times_to_concatenate)[:len(to_fit)]
It uses slicing, and the fact that a multiplication of a X and a string in python concatenates the string X times.
Output:
>>> trim_to_fit('test', 'stackoverflow')
'testtesttestt'
You can also create an endless circular generator over the string:
# improved by Rick Teachey
def circular_gen(txt):
while True:
for c in txt:
yield c
And to use it:
>>> gen = circular_gen('test')
>>> gen_it = [next(gen) for _ in range(len('stackoverflow'))]
>>> ''.join(gen_it)
'testtesttestt'
What you need is a way to get each character out of your manipulateinput string over and over again, and so that you don't run out of characters.
You can do this by multiplying the string so it is repeated as many times as you need:
mystring = 'string'
assert 2 * mystring == 'stringstring'
But how many times to repeat it? Well, you get the length of a string using len:
assert len(mystring) == 6
So to make sure your string is at least as long as the other string, you can do this:
import math.ceil # the ceiling function
timestorepeat = ceil(len(originalinput)/len(manipulateinput))
newmanipulateinput = timestorepeat * manipulateinput
Another way to do it would be using int division, or //:
timestorepeat = len(originalinput)//len(manipulateinput) + 1
newmanipulateinput = timestorepeat * manipulateinput
Now you can use a for loop without running out of characters:
result = '' # start your result with an empty string
for character in newmanipulateinput:
# test to see if you've reached the target length yet
if len(result) == len(originalinput):
break
# update your result with the next character
result += character
# note you can concatenate strings in python with a + operator
print(result)
I was doing excercise no.3 from http://cscircles.cemc.uwaterloo.ca/15b-python-pushups/, I made the code work but was wondering if it was possible to do it in fewer lines? Here is my solution:
los = [] # short for list of strings
while True:
s = input()
if s == '###': break
los += s.lower().split() # making a list of lower case words from the input sentences
test = []
for x in los:
test += str(los.count(x)) # made a new list of the frequency of each word
a = test.index(max(test)) # variable a provides the location of them most frequent word
print (los[a]) # we know the position of the most frequent string, so find it in los.
# a is not needed but it looks neater
So this part in particular is what i'm not happy with:
for x in los:
test += str(los.count(x))
I want to re write it like:
test += str(list.count(x)) for x in los
but it tells me invalid syntax..any tips?
I think the syntax you want is:
# No need for test = []
test = [str(list.count(x)) for x in los]