I am writing a program that looks for keith numbers in different bases. Is there a way to iterate through numbers in a certain base? I have a program that can convert decimal to any base, but I'm not sure how to proceed.
This is my code so far.
def is_keith_number(n,base):
# Find sum of digits by first getting an array of all digits then adding them
c = str(n)
a = list(map(int, c))
b = sum(a)
# Now check if the number is a keith number
while b < n:
a = a[1:] + [b]
b = sum(a)
return (b == n) & (len(c) > 1)
I also have a function,
convert()
which converts a number from one base to another. Its unneccesary to show that code, but it does work. Any help?
Related
This is the description of the problem I am trying to solve.
Hey, I Already Did That!
Commander Lambda uses an automated algorithm to assign minions randomly to tasks, in order to keep minions on their toes. But you've noticed a flaw in the algorithm -- it eventually loops back on itself, so that instead of assigning new minions as it iterates, it gets stuck in a cycle of values so that the same minions end up doing the same tasks over and over again. You think proving this to Commander Lambda will help you make a case for your next promotion.
You have worked out that the algorithm has the following process:
Start with a random minion ID n, which is a nonnegative integer of length k in base b
Define x and y as integers of length k. x has the digits of n in descending order, and y has the digits of n in ascending order
Define z = x - y. Add leading zeros to z to maintain length k if necessary
Assign n = z to get the next minion ID, and go back to step 2
For example, given minion ID n = 1211, k = 4, b = 10, then x = 2111, y = 1112 and z = 2111 - 1112 = 0999. Then the next minion ID will be n = 0999 and the algorithm iterates again: x = 9990, y = 0999 and z = 9990 - 0999 = 8991, and so on.
Depending on the values of n, k (derived from n), and b, at some point the algorithm reaches a cycle, such as by reaching a constant value. For example, starting with n = 210022, k = 6, b = 3, the algorithm will reach the cycle of values [210111, 122221, 102212] and it will stay in this cycle no matter how many times it continues iterating. Starting with n = 1211, the routine will reach the integer 6174, and since 7641 - 1467 is 6174, it will stay as that value no matter how many times it iterates.
Given a minion ID as a string n representing a nonnegative integer of length k in base b, where 2 <= k <= 9 and 2 <= b <= 10, write a function solution(n, b) which returns the length of the ending cycle of the algorithm above starting with n. For instance, in the example above, solution(210022, 3) would return 3, since iterating on 102212 would return to 210111 when done in base 3. If the algorithm reaches a constant, such as 0, then the length is 1.
My solution isn't passing 5 of the 10 test cases for the challenge. I don't understand if there's a problem with my code, as it's performing exactly as the problem asked to solve it, or if it's inefficient.
Here's my code for the problem. I have commented it for easier understanding.
def convert_to_any_base(num, b): # returns id after converting back to the original base as string
digits = []
while(num/b != 0):
digits.append(str(num % b))
num //= b
result = ''.join(digits[::-1])
return result
def solution(n, b):
minion_id_list = [] #list storing all occurrences of the minion id's
k = len(n)
while n not in minion_id_list: # until the minion id repeats
minion_id_list.append(n) # adds the id to the list
x = ''.join(sorted(n, reverse = True)) # gives x in descending order
y = x[::-1] # gives y in ascending order
if b == 10: # if number is already a decimal
n = str(int(x) - int(y)) # just calculate the difference
else:
n = int(x, b) - int(y, b) # else convert to decimal and, calculate difference
n = convert_to_any_base(n, b) # then convert it back to the given base
n = (k-len(n)) * '0' + n # adds the zeroes in front to maintain the id length
if int(n) == 0: # for the case that it reaches a constant, return 1
return 1
return len(minion_id_list[minion_id_list.index(n):]) # return length of the repeated id from
# first occurrence to the end of the list
I have been trying this problem for quite a while and still don't understand what's wrong with it. Any help will be appreciated.
The code is to find the largest possible product of 13 consecutive digits of a 1000 digit number. When I tried to run it on IDLE, it just gave RESTART and the directory where I saved the .py file. When I tried this on Pycharm(I know its not the IDE's problem, but I just had to try), no output. Am I doing something wrong?
n=7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
s=[]
j=13
def product(j):
p = 1
for i in range(j,j+13):
p=p*s[i]
return(p)
for i in range(0,1000):
s=s+[n%10]
n=n//10
k = product(0)
c=k
while j<1000:
if s[j]==0:
j=j+1
c=product(j)
while c==0:
j=j+13
c=product(j)
else:
c=(c*s[j+13])/s[j]
if c>k:
k=c
print(k)
Try this:
>>> n=7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
>>> digits = str(n)
>>> from numpy import prod
>>> products = [prod( map( int, digits[i:i+13])) for i in range(len(digits)-13)]
>>> max(products)
23514624000
Here's the quick explanation. First line -- this is your number. Second line -- I convert the number (like, 123) into the string "123", so I can take it digit by digit, hence the name of the variable digits.
I'm lazy to write multiplication routine, so I use a ready-made from numpy package, it's called prod and computes a product of the list, for example, prod( [1,2,3] ) = 6.
The next line is kind of complicated, but all it does -- going over your digits, selecting 13 of them at at time (digits[i:i+13]) and multiply them, saving the results in products.
Finally, the last line finds the maximum number in the products.
Your original code can be simplified to the following.
n=7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
def product(j):
p = 1
for i in range(j,j+13):
p=p*s[i]
return(p)
s=[]
for i in range(0,1000):
s=s+[n%10]
n=n//10
k = 0
N = len(s)
j = 0
while j<N-13: #need to 13 elements before end
c = product(j)
if c>k:
k=c
j = j + 1
print(k)
Result: 23514624000
This can be generated more easily even without resorting to Numpy by:
digits = str(n) # generates digits of number
products = [product(j) for j in range(1000-13)] # list comprehension
# uses you product function
print(max(products))
Place value (positional) encoded numbers
To make it possible to multiply a number in a place value based fashion, I have encoded numbers in a list format, digit by digit in reverse order. Say for example 34 is [4 3] and 12 is [2 1].
To encode numbers I use:
def eN(n):
return list(map(int, reversed(str(n))))
To decode I use:
def dN(l):
return int(''.join(map(str, reversed(l))))
So that: dN(eN(34)) -> 34
Positive integers can be from 0 to any digits long.
Multiplication constraints
Now, I need to create a multiplication algorithm with the next constraints:
1.
Division method to find out integer and remainder part of the divided number that satisfy this function:
from math import floor
# div(5, 3) -> [1, 2]
def div(n, base = 10):
return [floor(n / base), n % base]
only permitted arithmetic operations are div, * and + methods, which however can be used in conjunction with recursion
numbers must be encoded as stated above except the base is given as a native integer from 2 and up
at any part of the algorithm numbers cannot exceed two digits. For example 9+9 = 18 or 9*9=81 are good, but 100 is too much
result should also be a list of numbers encoded in a reverse list format. numbers in a list must be in single digits so that we can use decode function (dN) to transform it back to native integer
algorithm should work with any number base by using div or builtin Python divmod as suggested by #ShadowRanger.
Maybe other restrictions becomes necessary to stress, when answers are suggested.
Alleged algorithm
I would think of a root function similar to this, where two encoded numbers are given as arguments, plus an optional base number, default is 10:
def mul(a, b, base = 10):
def _(c, d, e):
# arithmetics, carrying digits, list processing, recursive calls goes here
pass
# initially, the first digit of the number a is reduced and 10^0 parts of the both numbers are multiplied and "div"ided
return _(a[1:], b, div(a[0]*b[0], base))
Finally, the expected result is:
mul(eN(34), eN(12)) # [8, 0, 4]
or
dN([8, 0, 4]) # 408
If necessary, I can add more to the multiplication _ function, which only has pass at the moment...
Added later...
Working, but messy and unoptimized version of the algo
One might want to use this as a starting point for optimization. I should note, that this should already do the job exactly as I need, but other approaches are welcome:
def mul(a, b, base = 10):
# init function with some default values
def _(c, d, f = [], g = [], h = [], e = 0):
# if there are no more items in list d, this is the end result
if not d:
return h + f
# if there are items in list list c, get integer and reminder parts and other stuff
# and proceed with the rest of the list c
if c:
x = divmod(c[0] * d[0] + (f.pop(1) if len(f) > 1 else 0) + e, base)
return _(c[1:], d, f, g + [x[1]], h, x[0])
# else we have reached the end of the list c and must begin again with the rest of the list d!
# also append reminders to the result lists h and f, not that content of f comes from g at this point
return _(a, d[1:], (g + [e] if e else g), [], (h + [f[0]] if f else h))
# start calling the recursive function and return the end result
return _(a, b)
I will accept any answer that does the same job, even the ones using above code, if solution makes good improvements like minifies the need of lists i.e. usage of memory, or other way simplifies and explains the solution.
Multiple number inputs
below is just how I chose to start writing my code
def main():
numbers = input()
if numbers == "0":
exit()
else:
number_list = [int(i) for i in numbers.split()]
def calculate_gcd(number_list):
for i in range(1,smallest_number(number_list)+1):
for n in range(0,len(number_list)):
if number_list[n] % i == 0:
check_list += number_list[n]
more code - but not important for the question im asking
my code was hardly complete and only worked for max 3 size lists, sadly.
How I thought of logic
Read input -> split by space, put it in list
sort the list
make a variable (divisor), and set it to 1
while divisor <= sortedlist[0] (which is smallest in list)
5. if every element % divisor == 0, then gcd = divisor, then divisor+=1
loop until it is no longer true
Problem I found
It requires stupid effort, it will actually not run and give runtime error.
I'm having trouble finding a way to check No.5 (in bold)
I know that there is gcd function, but it only deals with two inputs.
and it comes down to same question, how do I make sure 'all' elements divides down to zero?
Any suggestion of making gcd logic and comment on No.5 (bold) ?
Thank you
Instead of tackling the bigger problem, why not tackle a smaller problem. How do you find the gcd of two numbers? Well, there are multiple algorithms for this. Let us use the iterative one:
def gcd_iterative(a, b):
while b:
a, b = b, a % b
return a
Now, one thing to realize is that, if you have multiple numbers, and you want to find the gcd of all numbers, then it is simply:
gcd(gcd(...(a, b), c), ...)
In simpler terms, if you want to find the gcd of three numbers (a, b, c), then you would do the following:
gcd = gcd_iterative(a, b)
gcd = gcd_iterative(gcd, c)
So, now if you have a list of numbers, lst, you can do the following:
>>> gcd = lst[0]
>>> for num in lst[1:]:
gcd = gcd_iterative(gcd, num)
>>> print(gcd)
Again firstly I am sorry because keep asking the same question.I am new to python programming. I am now trying to build a program which convert every element in a list of numbers of base 10 into its base 4. For example here, say i have numbers from 0 to 20 or more, I want to convert every number starting from 0 to numbers of base 4. The result should be like this
[[0,0],[0,1],...[1,1,0]
for numbers starting from 0 to 20. For the code,here is what I wrote so far
for n in range(21):
def base(n,b):
result = []
while n > 0:
result.insert(0, n % b)
n = n // b
return result
print(base(n, 4))
For the result I got only for number 20 which is
[1,1,0]
Did I missed something here or there is another option to make it work?
Thank you for the answer
The issue is that you are defining the function inside the loop body, and only call it once. The structure you actually need is
<define the function>
for n in range(21):
print(base(n, 4))
The results will print out, but each one on a separate line. To create a list of the results you should replace the two lines of the loop with a single line that prints a list of all results, like
print([base(n, 4) for n in range(21)])
The problem is that you're defining the function inside the loop. What you want to do is define the function first, then construct your desired list:
def base(n,b):
result = []
while n > 0:
result.insert(0, n % b)
n = n // b
return result
print [base(n, 4) for n in range(21)]
(See this article if you're new to list comprehensions.)
If you want all the numbers, then indent your print statement, so that it's part of the loop.
If you want these as strings, then convert the digits to characters and concatenate them.
I've done both here:
def base(n, b):
result = []
while n > 0:
result.insert(0, n % b)
n = n / b
return result
for decimal in range(21):
print(''.join(str(digit) for digit in base(decimal, 4)))
You can manually compute the base of a number by doing something like this:
from math import log
from math import floor
def n_to_base(n, b):
num = n
lead_idx = floor(log(num, b))
b_rep = int(10**lead_idx)
b_rep = str(b_rep)
rep = 0
for i in range(len(b_rep)-1, -1, -1):
coeff = floor(num/(b**i))
rep += int(coeff*(10**i))
num -= int(coeff*(b**i))
return rep