5
\$\begingroup\$

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!

\$\endgroup\$
5
  • 2
    \$\begingroup\$ 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 \$\endgroup\$ – caird coinheringaahing Jun 30 at 23:44
  • \$\begingroup\$ Thank you very much for your edit! :) \$\endgroup\$ – Diana Andrei Jun 30 at 23:47
  • 2
    \$\begingroup\$ 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"? \$\endgroup\$ – cnamejj Jul 1 at 0:19
  • \$\begingroup\$ Why, precisely, 2 bytes shorter? \$\endgroup\$ – Shaggy Jul 1 at 0:21
  • 1
    \$\begingroup\$ @Shaggy This is a Codewars problem, A 2-byte improvement would be needed to pass in Python. \$\endgroup\$ – dingledooper Jul 1 at 1:12
6
\$\begingroup\$

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!

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.