Returning the range of a number as a palindrome

5

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.

ArnoldM904

Posted 2015-10-06T21:24:24.223

Reputation: 153

2range(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. – 301_Moved_Permanently – 2015-10-06T21:44:08.550

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. – 301_Moved_Permanently – 2015-10-07T05:23:39.063

3What's the input range? 1 to 9? 0 to 9? – Martin Ender – 2015-10-07T11:33:08.770

Answers

11

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.

MegaTom

Posted 2015-10-06T21:24:24.223

Reputation: 3 787

241 as a lambda, the apparent minimum, so I dare say you've nailed it :) (assuming input from 1-9) – Sp3000 – 2015-10-07T15:17:26.867

@Sp3000 thank you! added to answer. – MegaTom – 2015-10-07T15:28:40.667

2

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.

user62131

Posted 2015-10-06T21:24:24.223

Reputation:

2

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)
    

Janne Karila

Posted 2015-10-06T21:24:24.223

Reputation: 129

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. – Zach Gates – 2015-10-07T15:55:21.377

1

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.

ferada

Posted 2015-10-06T21:24:24.223

Reputation: 111

1Since 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) – Sp3000 – 2015-10-07T13:22:07.187

It pings. I can't delete the answer, but I'm removing that part at least. – ferada – 2015-10-07T14:12:52.853