Kaprekar numbers in Python - python

I aas solving a problem on HackerRank and the problem is as follows:
A modified Kaprekar number is a positive whole number n with d digits, such that when we split its square into two pieces - a right hand piece r with d digits and a left hand piece l that contains the remaining d or d−1 digits, the sum of the pieces is equal to the original number (i.e. l + r = n).
Alternatively, a modified Kaprekar number is a positive whole number n with 2d digits (if its number of digits is even) or 2d + 1 digits (if its number of digits is odd), such that when we split its square into two pieces, a right hand piece r containing d or d + 1 digits, and a left piece l containing the remaining d digits, the sum of the two pieces is equal to the original number.
We need to find Kaprekar numbers within a given range. So I wrote the following piece of code:
def checkIsKaprekar( num ):
string_num = str(num**2)
if num == int(string_num[:len(string_num)//2]) + int(string_num[len(string_num)//2:]):
return True
kaprekars = [ str(i) for i in range(int(input()),int(input())) if checkIsKaprekar(i) == True ]
print (' '.join(kaprekars))
The problem with the above solution is when we pass single digit numbers, they are converted into a string of which the right half is the number itself and the left half is ''. Now I am converting these strings to int(), which throws an exception.
To avoid this situation, I changed my code to this:
def checkIsKaprekar( num ):
string_num = str(num**2)
left_string = string_num[:len(string_num)//2]
right_string = string_num[len(string_num)//2:]
left_num = int(left_string) if left_string != '' else 0
right_num = int(right_string) if right_string != '' else 0
if num == left_num + right_num:
return True
kaprekars = [ str(i) for i in range(int(input()),int(input())) if checkIsKaprekar(i) == True ]
print (' '.join(kaprekars))
But I don't like this code even though it does solve the purpose. How can I tweak my original code to produce the right output?
Link to the question: https://www.hackerrank.com/challenges/kaprekar-numbers
Is there any way I can specify a default value of 0 if the string is ''?

As answered by B.M. int('0'+string_num[:len(string_num)//2]) works perfectly. int('0'+'') produces 0.

Maybe the cleanest way would be to define a function like this:
def to_int(s)
return int(s) if s else 0
But it may not be worth the overhead in this case.

It's often convenient to solve problems on integers ... with integers:
def kaprekar(n):
l=1
while l<=n : l*=10
return n== (n*n)//l + (n*n)%l
[print(x,end=' ') for x in range(1,100) if kaprekar(x)]
# 1 9 45 55 99

def checkIsKaprekar( num ):
if(num==1):
return True
elif((num**2)<15):
return False
string_num = str(num**2)
if num == int(string_num[:len(string_num)//2]) + int(string_num[len(string_num)//2:]):
return True

You can find Kaprekar numbers within a given range by testing each number for the given condition in the given range. For example,
def print_Kaprekar_nums(start, end):
for i in range(start, end + 1):
# Get the digits from the square in a list:
sqr = i ** 2
digits = str(sqr)
# Now loop from 1 to length of the number - 1, sum both sides and check
length = len(digits)
for x in range(1, length):
left = int("".join(digits[:x]))
right = int("".join(digits[x:]))
if (left + right) == i:
print("Number: " + str(i) + "Left: " + str(left) + " Right: " + str(right))
print_Kaprekar_nums(150, 8000)
This will give the output:
Number: 297Left: 88 Right: 209
Number: 703Left: 494 Right: 209
Number: 999Left: 998 Right: 1
Number: 1000Left: 1000 Right: 0
Number: 2223Left: 494 Right: 1729
Number: 2728Left: 744 Right: 1984
Number: 4879Left: 238 Right: 4641
Number: 4950Left: 2450 Right: 2500
Number: 5050Left: 2550 Right: 2500
Number: 5292Left: 28 Right: 5264
Number: 7272Left: 5288 Right: 1984
Number: 7777Left: 6048 Right: 1729

Related

sum of every other digit and doubling the rest

I'm working on a card number check code, for now I created a function that asks for the card number and checks if it is 8 digits or not (it has to be 8) and then calls another function that will do the math and check if the card is valid. For this function:
Starting from the rightmost digit, form the sum of every other digit. For example, if the card number is 1234 5678, then you form the sum 8 + 6 + 4 + 2 = 20
Double each of the digits that were not included in the preview step and then add all digits of the resulting numbers. For example, the digits that were not included are 7 5 3 1, we double the, 14 10 6 2, and then we sum each digit, 1 + 4 + 1 + 0 + 6 + 2 = 14
Add the sums of the two steps, 20 + 14 = 34, if the last digit is 0 then the card is valid, otherwise it is not valid (which is our case)
My problem is that I don't know how to iterate and get the sum of every other digit or double the other number which were not included in step 2. My thought was to use a while loop but then what?
EDIT: since some answers used lists... we didn't study lists yet, so I should not use it, we are only allowed to use sample stuff, loops, functions, etc.. even sum(map()) we didn't study
That is my code for now (its not much but just thought put it anyway)
def getCard():
CardInput = int(input("Enter your 8 digit credit card number: "))
if len(CardInput) == 8:
CardCheck(CardInput)
else:
print("Invalid Input: Should be exactly 8 digits!")
getCard()
def CardCheck(CardNumber):
Position = 0
Sum = 0
DoubleSum = 0
FinalSum = 0
while CardNumber >= 0:
Position += 1
So, the ugly way of doing is, you can write a for loop and use indexing for access specific elements
for i in range(len(CardInput)):
# it will iterate from 0 to 7
print(CardInput[i]) # here you get ith element
if i % 2 == 1:
print("I am other!") # you can sum your things here into another variable
Or with while:
while position < len(CardInput):
print(CardInput[position])
position += 1
It assumes CardInput is str, so I recommend to not convert it earlier.
However pythonic way would be
sum(map(int, CardInput[1::2])))
CardInput[1::2] returns list of every second element starting from second (0 is first).
map converts every element to in.
sum sums elements.
prompt = "Enter the eight-digit number: "
while True:
number = input(prompt)
if len(number) == 8 and number.isdigit():
break
prompt = "Oops, try again: "
first_digits = number[1::2] # If the user entered '12345678', this will be the substring '2468'
first_sum = sum(map(int, first_digits)) # Take each digit (character), map it to a single-digit integer, and take the sum of all single-digit integers
second_digits = number[0::2] # If the user entered '12345678', this will be the substring '1357'
doubled_ints = [int(char) * 2 for char in second_digits] # Take each digit (character), turn it into an integer, double it, and put it in a list.
second_sum = sum(map(int, "".join(map(str, doubled_ints)))) # Merge all integers in 'doubled_ints' into a single string, take each character, map it to a single digit integer, and take the sum of all integers.
total_sum = first_sum + second_sum
total_sum_last_digit = str(total_sum)[-1]
is_valid_card = (total_sum_last_digit == '0')
if is_valid_card:
print("Your card is valid (total sum: {})".format(total_sum))
else:
print("Your card is NOT valid (total sum: {})".format(total_sum))
def getCard():
CardInput = input("Enter your 8 digit credit card number: ")
if len(CardInput) == 8:
CardCheck(CardInput)
else:
print("Invalid Input: Should be exactly 8 digits!")
getCard()
def CardCheck(CardNumber):
list_CardNumber = [x for x in "25424334"]
Sum = sum(int(x) for x in list_CardNumber[1:8:-2])
DoubleSum = 2*sum(int(x) for x in list_CardNumber[0:8:-2])
FinalSum = Sum + DoubleSum
if str(FinalSum)[-1] == "0":
print("Valid Input")
else:
print("Invalid Input")
To get you started, you should check out enumerate(), it'll simplify things if you're just going to use loops by giving you easy access to both the index and value every loop.
step1 = 0
for i, x in enumerate(number):
if i % 2:
print('index: '+ str(i), 'value: '+ x)
step1 += int(x)
print('step 1: ', step1)
Output:
index: 1 value: 2
index: 3 value: 4
index: 5 value: 6
index: 7 value: 8
step 1: 20
You can use:
# lets say
CardNumber = '12345678'
# as mentioned by kosciej16
# get every other digit starting from the second one
# convert them to integers and sum
part1 = sum(map(int, CardNumber[1::2]))
# get every other digit starting from the first one
# convert them to integers and double them
# join all the digits into a string then sum all the digits
part2 = sum(map(int,''.join(list(map(lambda x: str(int(x)*2), CardNumber[0::2])))))
result = part1 + part2
print(result)
Output:
34
Edit:
Only with loops you can use:
# lets say
CardNumber = '12345678'
total_sum = 0
for idx, digit in enumerate(CardNumber):
if idx % 2 == 1:
total_sum += int(digit)
else:
number = str(int(digit)*2)
for d in number:
total_sum += int(d)
print(total_sum)
output:
34
Since you need to iterate over the digits, it's actually easier IMO if you leave it as a string, rather than converting the input to an int; that way you can just iterate over the digits and convert them to int individuall to do math on them.
Given an 8-digit long string card, it might look like this, broken into steps:
even_sum = sum(int(n) for n in card[1::2])
double_odds = (2 * int(n) for n in card[0::2])
double_odd_sum = sum(int(c) for do in double_odds for c in str(do))
All together with some logic to loop while the input is invalid:
def get_card() -> str:
"""Returns a valid card number, or raises ValueError."""
card = input("Enter your 8 digit credit card number: ")
if len(card) != 8 or not card.isdecimal():
raise ValueError("Invalid input: Should be exactly 8 digits!")
card_check(card)
return card
def card_check(card: str) -> None:
"""Raises ValueError if card checksum fails, otherwise returns None."""
even_sum = sum(int(n) for n in card[1::2])
double_odds = (2 * int(n) for n in card[::2])
double_odd_sum = sum(int(c) for do in double_odds for c in str(do))
if (even_sum + double_odd_sum) % 10:
raise ValueError("Card checksum failed!")
while True:
try:
print(f"{get_card()} is a valid card number!")
except ValueError as e:
print(e)

swap output the order of the digits

I have one code here
and need to change the order of the digits
import math
def sucet_cisel(number):
bla: int = 0
while number > 0:
xyzpremenna = number % 10
bla += xyzpremenna
number = (number - xyzpremenna) / 10
return bla
def digit_root(n):
if n == 0: return 0
return (n - 1) % 9 + 1
if __name__ == '__main__':
n = int(input("od čisla:"))
m = int(input("do čisla:"))
for i in range(1,m + 1):
sucet: int = math.floor(sucet_cisel(n*i))
t=(n*i)*(2)
x=' ';
print(n,"*",i,"=",n*i,(x*4),"*2","=",t,sep='')
they need to add () to this code so that in each result where there are 4 numbers they are moved
therefore print (t) need this script to run at that number
t=(ni)(2)
and the result of this to turn into this code
val = list(str(i))
digit = val.pop(-3)
new = int(''.join(val+[digit]))
od čisla:2554
do čisla:4505
2554*4505=11505770 *2=23011540
23011540
23011405
the script stops at the number I enter where is the problem?
20*1=20 *2=40
20*2=40 *2=80
20*3=60 *2=120
20*4=80 *2=160
20*5=100 *2=200
20*6=120 *2=240
20*7=140 *2=280
20*8=160 *2=320
20*9=180 *2=360
20*10=200 *2=400
20*11=220 *2=440
20*12=240 *2=480
20*13=260 *2=520
20*14=280 *2=560
20*15=300 *2=600
20*16=320 *2=640
20*17=340 *2=680
20*18=360 *2=720
20*19=380 *2=760
20*20=400 *2=800
this makes a code if I give
n = int (input ("from number:"))
m = int (input ("to number:"))
n20
m20
however, if in this script there is i
val = list (page (s))
digit = val.pop (-3)
new = int (''. join (val + [digit]))
does it calculate only one result where is the error?
Very similar to the answer from Tim Roberts, but using slices and format strings.
n = 12345678
s = str(n)
x = int(f"{s[:-5]}{s[::-1][:4]}")
s is '12345678', s[:-5] is '1234', s[::-1] is '87654321', and s[::-1][:4] is '8765'. Put it all together and x is 12348765.
OK, let's rewrite your problem to "given a number of greater than 4 digits, I want that same number but with all permutations of the last 4 digits.
import itertools
def permute(number):
val = str(number)
prefix = val[:-4]
for combo in itertools.permutations(val[-4:]):
yield int(prefix+''.join(combo))
print(list(permute(12345678)))

How to reverse an int in python?

I'm creating a python script which prints out the whole song of '99 bottles of beer', but reversed. The only thing I cannot reverse is the numbers, being integers, not strings.
This is my full script,
def reverse(str):
return str[::-1]
def plural(word, b):
if b != 1:
return word + 's'
else:
return word
def line(b, ending):
print b or reverse('No more'), plural(reverse('bottle'), b), reverse(ending)
for i in range(99, 0, -1):
line(i, "of beer on the wall")
line(i, "of beer"
print reverse("Take one down, pass it around")
line(i-1, "of beer on the wall \n")
I understand my reverse function takes a string as an argument, however I do not know how to take in an integer, or , how to reverse the integer later on in the script.
Without converting the number to a string:
def reverse_number(n):
r = 0
while n > 0:
r *= 10
r += n % 10
n /= 10
return r
print(reverse_number(123))
You are approaching this in quite an odd way. You already have a reversing function, so why not make line just build the line the normal way around?
def line(bottles, ending):
return "{0} {1} {2}".format(bottles,
plural("bottle", bottles),
ending)
Which runs like:
>>> line(49, "of beer on the wall")
'49 bottles of beer on the wall'
Then pass the result to reverse:
>>> reverse(line(49, "of beer on the wall"))
'llaw eht no reeb fo selttob 94'
This makes it much easier to test each part of the code separately and see what's going on when you put it all together.
Something like this?
>>> x = 123
>>> str(x)
'123'
>>> str(x)[::-1]
'321'
best way is
x=12345
a=str(x)[::-1]\\ In this process i have create string of inverse of integer (a="54321")
a=int(a) \\ Here i have converted string a in integer
or
one line code is
a=int(str(x)[::-1]))
def reverse(x):
re = 0
negative = x < 0
MAX_BIG = 2 ** 31 -1
MIN_BIG = -2 ** 31
x = abs(x)
while x != 0:
a = int(x % 10)
re = re * 10 + a
x = int(x // 10)
reverse = -1 * re if negative else re
return 0 if reverse < MIN_BIG or reverse > MAX_BIG else reverse
this is for 32 - bit integer ( -2^31 ; 2^31-1 )
def reverse_number(n):
r = 0
while n > 0:
r = (r*10) + (n % 10)
print(r)
r *=10
n //= 10
return r
print(reverse_number(123))
You can cast an integer to string with str(i) and then use your reverse function.
The following line should do what you are looking for:
def line(b, ending):
print reverse(str(b)) or reverse('No more'), plural(reverse('bottle'),reverse(str(b))), reverse(ending)
Original number is taken in a
a = 123
We convert the int to string ,then reverse it and again convert in int and store reversed number in b
b = int("".join(reversed(str(a))))
Print the values of a and b
print(a,b)
def reverse_number(n):
r = 0
while n > 0:
r *= 10
r += n % 10
n /= 10
return r
print(reverse_number(123))
This code will not work if the number ends with zeros, example 100 and 1000 return 1
def reverse(num):
rev = 0
while(num != 0):
reminder = num % 10
rev = (rev * 10 ) + reminder
num = num // 10
print ("Reverse number is : " , rev )
num=input("enter number : ")
reverse(int(num))
#/ always results into float
#// division that results into whole number adjusted to the left in the number line
I think the following code should be good to reverse your positive integer.
You can use it as a function in your code.
n = input() # input is always taken as a string
rev = int(str(n)[::-1])
If you are having n as integer then you need to specify it as str here as shown. This is the quickest way to reverse a positive integer
import math
def Function(inputt):
a = 1
input2 = inputt
while(input2 > 9):
input2 = input2/10
a = a + 1
print("There are ", a, " numbers ")
N = 10
m = 1
print(" THe reverse numbers are: ")
for i in range(a):
l = (inputt%N)/m
print(math.floor(l), end = '')
N = N*10
m = m*10
print(" \n")
return 0
enter = int(input("Enter the number: "))
print(Function(enter))
More robust solution to handle negative numbers:
def reverse_integer(num):
sign = [1,-1][num < 0]
output = sign * int(str(abs(num))[::-1])
An easy and fast way to do it is as follows:
def reverse(x: int|str) -> int:
reverse_x = int(''.join([dgt for dgt in reversed(num:=str(x)) if dgt != '-']))
if '-' in num:
reverse_x = -reverse_x'
return reverse_x
First we create a list (using list comprehension) of the digits in reverse order. However, we must exclude the sign (otherwise the number would turn out like [3, 2, 1, -]). We now turn the list into a string using the ''.join() method.
Next we check if the original number had a negative sign in it. If it did, we would add a negative sign to reverse_x.
Easily you can write this class:
class reverse_number:
def __init__(self,rvs_num):
self.rvs_num = rvs_num
rvs_ed = int(str(rvs_num)[::-1])
print(rvs_ed)
You can use it by writing:
reverse_number(your number)
I have written it in a different way, but it works
def isPalindrome(x: int) -> bool:
if x<0:
return False
elif x<10:
return True
else:
rev=0
rem = x%10
quot = x//10
rev = rev*10+rem
while (quot>=10):
rem = quot%10
quot = quot//10
rev = rev*10+rem
rev = rev*10+quot
if rev==x:
return True
else:
return False
res=isPalindrome(1221)

Add numbers in hexadecimal base without converting bases?

I need to write a function which gets two numbers in hexadecimal base, and calculates the sum of both of them, I'm not allowed to convert them to decimal base, the code is supposed to calculate it "manually" using loops.
for example this is how it should work:
1
1 f 5 (A)
+ 5 a (B)
-------------
= 2 4 f
Here is an input example:
>>> add("a5", "17")
'bc'
I've started building my code but I got stuck, I thought I would divide into three ifs, one that would sum up only numbers, other sums numbers and letters, and the third one sums letters, but I don't know how to continue from here:
def add_hex(A,B):
lstA = [int(l) for l in str(A)]
lstB = [int(l) for l in str(B)]
if len(A)>len(B):
A=B
B=A
A='0'*(len(B)-len(A))+A
remainder=False
result=''
for i in range(len(B)-1)
if (A[i]>0 and A[i]<10) and (B[i]>0 and B[i]<10):
A[i]+B[i]=result
if A[i]+B[i]>10:
result+='1'
Any help is greatly appreciated, I have no clue how to start on this!
You can have a sub-function that adds two single-digit hex numbers and returns their single-digit sum and a carry (either 0 or 1). This function will take three inputs: two numbers you want to add and a carry-in. You can then loop through the digits of the two numbers you want to add from least significant to most significant, and apply this function for every pair of digits while taking into account the carry at each stage.
So let's try your example:
A 5
1 7 +
We start at the least significant digits, 5 and 7, and perform the 1-digit addition. 516 + 716 = 1210. 1210 is less than 1610, so the output of our 1-digit add is 1210 = C16 with a carry of 0.
Now we add A and 1 (our carry-in is 0 so we can just add them normally). A16 + 116 = 1110. 1110 is less than 1610, so the output of our 1-digit add is 1110 = B16 with a carry of 0. (If we had a non-zero carry-in, we would just add 1 to this value.)
Hence, our overall result is:
A 5
1 7 +
-----
B C
I think we just remember the pattern of addition. Like following.
"0" + "0" = "0"
"0" + "1" = "1"
"0" + "2" = "2"
.
.
.
"f" + "d" = "1b"
"f" + "e" = "1c"
"f" + "f" = "1e"
We have dictionary of all of the pattern because we've learned it in school or somewhere. And we've also learned carry.
So I think this seems like manual addition algorithm.
Remembering the pattern include carry.
Calculating
Translate two digit to one digit(a+b->c).
Treat carry correctly.
And here is my code for that. But it may be a bit tricky.
import itertools
def add_hex(A,B):
A = "0"+A
B = "0"+B
#Remember all pattern include carry in variable d.
i2h = dict(zip(range(16), "0123456789abcdef"))
a = [(i,j) for i in "0123456789abcdef" for j in "0123456789abcdef"]
b = list(map(lambda t: int(t[0],16)+int(t[1],16), a))
c = ["0"+i2h[i] if i<16 else "1"+i2h[i-16] for i in b]#list of digit include carry
d = dict(zip(a,c))#d={(digit,digit):digit,,,}
#Calculate with variable d.
result = ""
cur = "0"
nex = "0"
for i in itertools.izip_longest(A[::-1], B[::-1], fillvalue = "0"):
cur = d[(nex, d[i][1])][1] #cur = carry + digit + digit
if d[i][0]=='1' or d[(nex, d[i][1])][0]=='1':#nex = carry = carry + digit + digit
nex = "1"
else:
nex = "0"
result += cur
return result[::-1]
#Test
A = "fedcba"
B = "012346"
print add_hex(A,B)
print hex(int(A,16)+int(B,16))#For validation
I hope it helps. :)

python - print squares of numbers which are palindromes : improve efficiency

I have an assignment to do. The problem is something like this. You give a number, say x. The program calculates the square of the numbers starting from 1 and prints it only if it's a palindrome. The program continues to print such numbers till it reaches the number x provided by you.
I have solved the problem. It works fine for uptil x = 10000000. Works fine as in executes in a reasonable amount of time. I want to improve upon the efficiency of my code. I am open to changing the entire code, if required. My aim is to make a program that could execute 10^20 within around 5 mins.
limit = int(input("Enter a number"))
def palindrome(limit):
count = 1
base = 1
while count < limit:
base = base * base #square the number
base = list(str(base)) #convert the number into a list of strings
rbase = base[:] #make a copy of the number
rbase.reverse() #reverse this copy
if len(base) > 1:
i = 0
flag = 1
while i < len(base) and flag == 1:
if base[i] == rbase[i]: #compare the values at the indices
flag = 1
else:
flag = 0
i += 1
if flag == 1:
print(''.join(base)) #print if values match
base = ''.join(base)
base = int(base)
base = count + 1
count = count + 1
palindrome(limit)
He're my version:
import sys
def palindrome(limit):
for i in range(limit):
istring = str(i*i)
if istring == istring[::-1]:
print(istring,end=" ")
print()
palindrome(int(sys.argv[1]))
Timings for your version on my machine:
pu#pumbair: ~/Projects/Stackexchange time python3 palin1.py 100000
121 484 676 10201 12321 14641 40804 44944 69696 94249 698896 1002001 1234321
4008004 5221225 6948496 100020001 102030201 104060401 121242121 123454321 125686521
400080004 404090404 522808225 617323716 942060249
real 0m0.457s
user 0m0.437s
sys 0m0.012s
and for mine:
pu#pumbair: ~/Projects/Stackexchange time python3 palin2.py 100000
0 1 4 9
121 484 676 10201 12321 14641 40804 44944 69696 94249 698896 1002001 1234321
4008004 5221225 6948496 100020001 102030201 104060401 121242121 123454321 125686521
400080004 404090404 522808225 617323716 942060249
real 0m0.122s
user 0m0.104s
sys 0m0.010s
BTW, my version gives more results (0, 1, 4, 9).
Surely something like this will perform better (avoiding the unnecessary extra list operations) and is more readable:
def palindrome(limit):
base = 1
while base < limit:
squared = str(base * base)
reversed = squared[::-1]
if squared == reversed:
print(squared)
base += 1
limit = int(input("Enter a number: "))
palindrome(limit)
I think we can do it a little bit easier.
def palindrome(limit):
count = 1
while count < limit:
base = count * count # square the number
base = str(base) # convert the number into a string
rbase = base[::-1] # make a reverse of the string
if base == rbase:
print(base) #print if values match
count += 1
limit = int(input("Enter a number: "))
palindrome(limit)
String into number and number into string conversions were unnecessary. Strings can be compared, this is why you shouldn't make a loop.
You can keep a list of square palindromes upto a certain limit(say L) in memory.If the Input number x is less than sqrt(L) ,you can simply iterate over the list of palindromes and print them.This way you wont have to iterate over every number and check if its square is palindrome .
You can find a list of square palindromes here : http://www.fengyuan.com/palindrome.html
OK, here's my program. It caches valid suffixes for squares (i.e. the values of n^2 mod 10^k for a fixed k), and then searches for squares which have both that suffix and start with the suffix reversed. This program is very fast: in 24 seconds, it lists all the palindromic squares up to 10^24.
from collections import defaultdict
# algorithm will print palindromic squares x**2 up to x = 10**n.
# efficiency is O(max(10**k, n*10**(n-k)))
n = 16
k = 6
cache = defaultdict(list)
print 0, 0 # special case
# Calculate everything up to 10**k; these will be the prefix/suffix pairs we use later
tail = 10**k
for i in xrange(tail):
if i % 10 == 0: # can't end with 0 and still be a palindrome
continue
sq = i*i
s = str(sq)
if s == s[::-1]:
print i, s
prefix = int(str(sq % tail).zfill(k)[::-1])
cache[prefix].append(i)
prefixes = sorted(cache)
# Loop through the rest, but only consider matching prefix/suffix pairs
for l in xrange(k*2+1, n*2+1):
for p in prefixes:
low = (p * 10**(l-k))**.5
high = ((p+1) * 10**(l-k))**.5
low = int(low / tail) * tail
high = (int(high / tail) + 1) * tail
for n in xrange(low, high, tail):
for suf in cache[p]:
x = n + suf
s = str(x*x)
if s == s[::-1]:
print x, s
Sample output:
0 0
1 1
2 4
3 9
11 121
22 484
26 676
101 10201
111 12321
121 14641
202 40804
212 44944
<snip>
111010010111 12323222344844322232321
111100001111 12343210246864201234321
111283619361 12384043938083934048321
112247658961 12599536942224963599521
128817084669 16593841302620314839561
200000000002 40000000000800000000004

Categories

Resources