5
\$\begingroup\$

I like to do programming challenges in my free time to teach myself and keep fresh, this one I can't seem to optimize though and it's driving me insane.

The goal is essentially, "Given a number, return the numbers leading up to it as a palindrome."

For example if you are given the input 5 the answer your program should return is: 123454321

The catch? You have to solve it in as few characters as possible. The minimum needed seems to be 41 characters and I can't condense it past 76.

I have tried all sorts of solutions, here are a few:

# Note: "Palindromic_Number" is required. "def P(N):" will not work.
def Palindromic_Number(N):
    a = ''
    for x in range(1,N+1):
        a += str(x)
    return a + a[::-1][1:]


def Palindromic_Number(N):
    a = ''.join(map(str, range(1,N+1)))
    return a + a[::-1][1:]


def Palindromic_Number(N):
    a = ''.join([str(x) for x in range(1, N+1)])
    return a + a[::-1][1:]


# This one uses Python 2.7
Palindromic_Number = lambda N: ''.join(map(str, range(1,N+1) + range(1,N+1)[::-1][1:]))

Does anyone have any ideas as to how I could shorten my code? I'm just looking for a point in the right direction where to look as this point.

\$\endgroup\$

migrated from codereview.stackexchange.com Oct 7 '15 at 10:28

This question came from our site for peer programmer code reviews.

  • 2
    \$\begingroup\$ range(1,N)+range(N,0,-1) should be shorter than using a+a[::-1][1:] afterwards as it allows you to not define a at all. \$\endgroup\$ – Mathias Ettinger Oct 6 '15 at 21:44
  • \$\begingroup\$ Forget it, it won't be so usefull. You can't add ranges in python 3. Only in python 2 where the builtin returns a list. \$\endgroup\$ – Mathias Ettinger Oct 7 '15 at 5:23
  • 3
    \$\begingroup\$ What's the input range? 1 to 9? 0 to 9? \$\endgroup\$ – Martin Ender Oct 7 '15 at 11:33
11
\$\begingroup\$

You could try:

def Palindromic_Number(N):
    return int('1'*N)**2

just preforms 11111 * 11111 which equals 123454321

47 chars.


Or, as a lambda:

Palindromic_Number=lambda N:int('1'*N)**2

41 chars.

\$\endgroup\$
  • 2
    \$\begingroup\$ 41 as a lambda, the apparent minimum, so I dare say you've nailed it :) (assuming input from 1-9) \$\endgroup\$ – Sp3000 Oct 7 '15 at 15:17
  • \$\begingroup\$ @Sp3000 thank you! added to answer. \$\endgroup\$ – MegaTom Oct 7 '15 at 15:28
2
\$\begingroup\$

In the last solution (that takes advantage of Python 2 style ranges) you could reduce this

range(1,N+1) + range(1,N+1)[::-1][1:]

in a couple of ways:

  1. Instead of slicing the second range, create the reversed range directly as range(N-1,0,-1)
  2. Making N come out of the second range allows changing N+1 and N-1 to N and N:

    range(1,N) + range(N,0,-1)
    
\$\endgroup\$
  • \$\begingroup\$ Slicing with [-2::-1] is shorter than [::-1][1:] by two bytes/chars. You can also remove the spaces on either side of the plus sign. \$\endgroup\$ – Zach Gates Oct 7 '15 at 15:55
2
\$\begingroup\$

Python 2, 40 bytes

Palindromic_Number=lambda n:(10**n/9)**2

Try it online! (Includes test code to actually run the program.)

I know that you claimed that 41 is the minimum, but it's actually possible to do it in 40.

This uses the same strategy seen in the other answers, of squaring a repunit (a number made out of repetitions of the digit 1). However, instead of using string operations to produce the repunit (and thus having to pay for int to convert string to integer), it generates the palindrome entirely arithmetically.

The basic idea here is that 10n is a 1 followed by n 0s; if we subtract 1 we therefore get n 9s, and dividing by 9 gives us n 1s. Because Python 2 rounds integer arithmetic downwards, we can omit the subtraction of 1 (as it'll leave the answer higher by ⅑ than it should, which is a fraction that will disappear in the rounding), and we'll still get the correct answer.

\$\endgroup\$
1
\$\begingroup\$

range is a rather long name; with lambda N,r=range:/def ...(N,r=range): you can shave off a few characters if you also remove all unnecessary whitespace.

\$\endgroup\$
  • 1
    \$\begingroup\$ Since this question migrated from Code Review I'm not sure whether it'll ping, but in any case aliasing range (5 chars) doesn't save any bytes when it's only used twice (compare range;range vs r=range;r;r) \$\endgroup\$ – Sp3000 Oct 7 '15 at 13:22
  • \$\begingroup\$ It pings. I can't delete the answer, but I'm removing that part at least. \$\endgroup\$ – ferada Oct 7 '15 at 14:12

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.