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.
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:
p=lambda n,c:(r:=n*c)[:n//2]+r[~-n//2::-1]
Try it online!
c
, why isn
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 forn=9, c="ab"
orn=3, c="abdefg"
? \$\endgroup\$