1

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.

Rick
  • 43,029
  • 15
  • 76
  • 119
  • what's the question again?... – Karoly Horvath Jan 26 '15 at 18:18
  • Is this a homework question? It's ok if it is, but the help suggests that you say so in your question up front. It lets people help you more effectively. Also: try to include at least some code you've tried taking a crack at it. – Rick Jan 26 '15 at 18:18
  • This is the question that I have been given: "The keyword is repeated enough times to match the length of the plaintext message.". The rest of the program I am able to add onto the section of code I already have, and this is just me finishing some of my classwork :) – Kieron Holmes Jan 26 '15 at 18:22

4 Answers4

3

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
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
2

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'
Community
  • 1
  • 1
Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88
2

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).

xnx
  • 24,509
  • 11
  • 70
  • 109
  • seems like the goal of the assignment is to understand string manipulation more than `while` loops. – Rick Jan 26 '15 at 18:33
  • I have just tried this program, and it seems to work perfectly, as it allows me to manipulate the string, to match the character length of the original input. Sorry I was a bit vague on my instructions, but thanks @xnx :) – Kieron Holmes Jan 26 '15 at 18:37
  • @xnx Sorry to bother you, but do you know how I could improve this program so it will ignore spaces in the inputs? – Kieron Holmes Jan 26 '15 at 19:08
  • I'm not quite sure what you mean, but you could simply replace all spaces with the empty string: `a.replace(' ','')` turns `'no spaces now'` into `'nospacesnow'` – xnx Jan 26 '15 at 19:15
0

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)
Rick
  • 43,029
  • 15
  • 76
  • 119
  • 1
    No prob. Code wasn't working. Fixed now. BTW the best way to say "thanks" to people is to upvote their answer, and/or to mark it as accepted. – Rick Jan 26 '15 at 18:42
  • I can't seem to upvote, due to me having less than 15 reputation, but I am going to try all of these (and if it lets me), I will mark the most relevant one as accepted. Thanks again – Kieron Holmes Jan 26 '15 at 18:45
  • You'll be able to soon. Doesn't take long to get to 15. – Rick Jan 26 '15 at 19:03
  • I seem to be on 8 now, but I have another question I shall post, about the implementation of some of this code into the section of code I have currently got, but I think I should have a go at it myself first :) – Kieron Holmes Jan 26 '15 at 19:04