# Tips on golfing this Python program to generate a palindrome from a string

I wrote this function in 48 bytes and I wonder, is there any way to write this code 2 characters shorter?

p=lambda n,c:(n*c)[:n//2]+(n*c)[:n//2+n%2][::-1]


The point of the function is to create a palindrome of length n by using all the characters from the string c. Example: n = 3, c = 'ab'. Result is 'aba'.

Is there something I am missing that can be shortened or is there no other way to make it shorter? Thanks!

• Welcome to Code Golf and nice first question! I've cleaned up your question a bit to be closer to our standards (changed the title, added some correct tags). Feel free to edit anything you dislike – caird coinheringaahing Jun 30 at 23:44
• Thank you very much for your edit! :) – Diana Andrei Jun 30 at 23:47
• If you need to use all of c, why is n necessary? I can see if that's the control for whether or not the palindrome has a central, unmatched character (odd number of output) or if each character is paired up (even number of chars). But what would you want the output to be for n=9, c="ab" or n=3, c="abdefg"? – cnamejj Jul 1 at 0:19
• Why, precisely, 2 bytes shorter? – Shaggy Jul 1 at 0:21
• @Shaggy This is a Codewars problem, A 2-byte improvement would be needed to pass in Python. – dingledooper Jul 1 at 1:12

In general, slicing twice usually results in extraneous code.

Here, you use [:n//2+n%2][::-1]. The first part means "get from 0 to n//2+n%2", left-inclusive right-exclusive. The second part reverses it. Thus, what you are actually trying to do is get from n//2+n%2-1 to -1, stepping by -1, left-inclusive right-exclusive. Thus, you can do [n//2-n%2-1:-1:-1]. The stop argument is excessive there.

p=lambda n,c:(n*c)[:n//2]+(n*c)[n//2+n%2-1::-1]


Then, since n%2-1 gives 0 for odd numbers and -1 for even numbers, we can also get 0 for odd numbers and 1 for even numbers via ~n%2, and then subtract that:

p=lambda n,c:(n*c)[:n//2]+(n*c)[n//2-~n%2::-1]


(The following is found by dingledooper)

Finally, we can optimize that part even further, as what we are asking for is n//2-1 for even numbers and n//2 for odd numbers. Notice that if we subtract one, then (n-1)//2 solves this. For integers, n-1 is equivalent to ~-n (remember that ~ is complement, and ~n == -1 - n so ~-n == -1 + n == n - 1). Therefore, we can shorten that part down to [~-n//2::-1].

Remember the ~- trick for decrementing (as well as -~ for incrementing) as it saves 2 bytes for (n+1) and (n-1) where brackets would otherwise be needed, since unary operators have very high precedence.

# Python 3, 43 bytes

p=lambda n,c:(n*c)[:n//2]+(n*c)[~-n//2::-1]


Try it online!

(Thanks to Jo King for spotting this one)

If you can use Python 3.8, inline assignment with the walrus operator saves a byte:

# Python 3.8 (pre-release), 42 bytes

p=lambda n,c:(r:=n*c)[:n//2]+r[~-n//2::-1]


Try it online!

• Yes, exactly 2 characters! Incredible idea, thank you so much! – Diana Andrei Jun 30 at 23:48
• I've checked out n//2-~n%2, and seems to be equal to ~-n//2 (that's a 3 byte save). – dingledooper Jun 30 at 23:49
• @dingledooper Oh yeah, that makes sense. Thank you, I will include that and add an explanation. – hyper-neutrino Jun 30 at 23:49