Convert decimal to ternary(base3) in python - python

I am trying to make a decimal number ternary in a python function. My idea was to keep dividing until the quotient and remainder were equal, but I can't seem to get that to work. Here's my code:
l = 1
#problem code
def ternary(n):
e = n/3
q = n%3
e= n/3
q= e%3
print q
r = input("What number should I convert?: ")
k = bin(r)
v = hex(r)
i = oct(r)
print k+"(Binary)"
print v+"(Hex)"
print i+"(Octals)"
ternary(r)
l+=1
# Variables:
#l,r,k,v,i
#n,q,e

My idea was to keep dividing until the quotient and remainder were equal, but I can't seem to get that to work.
Yeah, something like that. Essentially, you want to keep dividing by 3, and collect the remainders. The remainders then make up the final number. In Python, you can use divmod to divide and collect the remainder.
def ternary (n):
if n == 0:
return '0'
nums = []
while n:
n, r = divmod(n, 3)
nums.append(str(r))
return ''.join(reversed(nums))
Examples:
>>> ternary(0)
'0'
>>> ternary(1)
'1'
>>> ternary(2)
'2'
>>> ternary(3)
'10'
>>> ternary(12)
'110'
>>> ternary(22)
'211'

You can also use the implementation of NumPy:
https://numpy.org/doc/stable/reference/generated/numpy.base_repr.html?highlight=base_repr#numpy.base_repr
Though, I agree that a function for ternary exclusively is faster.
import numpy as np
number=100 # decimal
ternary=np.base_repr(number,base=3)
print(ternary)
#10201

This can also be done with recursion.
def ternary(n):
e = n//3
q = n%3
if n == 0:
return '0'
elif e == 0:
return str(q)
else:
return ternary(e) + str(q)
More generally, you can convert to any base b (where 2<=b<=10) with the following recursive function.
def baseb(n, b):
e = n//b
q = n%b
if n == 0:
return '0'
elif e == 0:
return str(q)
else:
return baseb(e, b) + str(q)

Related

Figure out where decimal point goes when dividing floats as integers

I'm wanting to make a script that can perform maths on large numbers while keeping the precision as high as required. I attempted ones ages ago and division was the worst part by far, so I thought I'd try start with it this time.
Basically, I'm using str inputs, as they obviously remain perfectly accurate, and I'd like to perform calculations on them as integers so that nothing is lost to floating point numbers. I'm doing that currently by removing the decimal point before the calculation, then trying to re-add it, but I can't figure out how.
With multiplication, you can figure out the decimal by adding how many numbers are left of the decimal point in both numbers. Unfortunately that method doesn't seem to work with division. I previously tried coding long division, but again it's an awkward one if there's floats involved.
Here's the current code I've got, with some of the non working parts removed:
from __future__ import division
def _divide(a, b, precision):
count = 0
while a and count < precision:
for num in str(int(a // b)):
yield int(num)
count += 1
a = a % b * 10
def divide(a, b, precision=100, round_int=True):
result = []
a = str(a)
b = str(b)
#Check for negative numbers
a_neg = a[0] == '-'
b_neg = b[0] == '-'
if a_neg and not b_neg or b_neg and not a_neg:
result.append('-')
#Process number strings
a_split = a.split('.')
b_split = b.split('.')
try:
a = abs(int(a_split[0] + a_split[1]))
except IndexError:
a = abs(int(a_split[0]))
try:
b = abs(int(b_split[0] + b_split[1]))
except IndexError:
b = abs(int(b_split[0]))
#Calculate number
result += list(_divide(a, b, precision=precision+round_int))
if not round_int:
return ''.join(map(str, result))
#Round last integer
last_int = int(result.pop(-1))
index = -1
if last_int >= 5:
try:
result[index] += 1
except TypeError:
index -= 1
result[index] += 1
#Lower any integers above 10
while True:
if result[index] == '.':
index -= 1
if result[index] > 9:
result[index] -= 10
if result[index-1] == '.':
index -= 1
result[index-1] += 1
else:
return ''.join(map(str, result)).rstrip('.')
index -= 1
a = '365.72'
b = '2247.7'
print divide(a, b, 9, False)
print float(a) / float(b)
I just drew up a quick hacky way which uses the inbuilt float division to figure out where the decimal is, but obviously it's not ideal as it'll fail after 1e300:
cheat_div = str(abs(float(a) / float(b)))
if 'e' in cheat_div:
num_decimals = int(cheat_div.split('e')[1])
if num_decimals > 1:
num_decimals += 1
else:
if cheat_div.startswith('0.'):
num_decimals = 2 + len(cheat_div[2:].lstrip('0')) - len(cheat_div)
else:
try:
num_decimals = cheat_div.index('.')
except ValueError:
num_decimals = 0
while not result[is_negative]:
del result[is_negative]
if num_decimals:
if num_decimals > 0:
result = result[:is_negative+num_decimals] + ['.'] + result[is_negative+num_decimals:]
else:
result = result[:is_negative] + ['0', '.'] + ['0'] * -num_decimals + result[is_negative:]

Python: Create a list of all four digits numbers with all different digits within it

I was wondering if there is any easier way to achieve what this code is achieving. Now the code creates all 4-digits number in a list (if the number starts with a 0 is doesn't count as a 4-digit, for example 0123) and no digit is repeated within the number. So for example 1231 is not in the list. Preferable I want a code that does what this one is doing but a depending on what argument N is given to the function upon calling it creates this kind of list with all numbers with N digits. I hope this wasn't impossible to understand since Im new to programing.
def guessables():
'''creates a list of all 4 digit numbers wherest every
element has no repeating digits inside of that number+
it doesn't count as a 4 digit number if it starts with a 0'''
guesses=[]
for a in range(1,10):
for b in range(0,10):
if a!=b:
for c in range(0,10):
if b!=c and a!=c:
for d in range(0,10):
if c!=d and d!=b and d!=a:
guesses.append(str(a)+str(b)+str(c)+str(d))
return guesses
This can be expressed more easily.
def all_digits_unique(number):
# `set` will only record unique elements.
# We convert to a string and check if the unique
# elements are the same number as the original elements.
return len(str(number)) == len(set(str(number)))
Edit:
def guesses(N):
return filter(all_digits_unique, range(10**(N-1), 10**N))
print guesses(4)
I'd use itertools for this which is in my opinion the simplest generic answer:
import itertools
def guessables(num):
guesses = []
for p in itertools.permutations(xrange(10),num):
if p[0] != 0:
guesses.append(''.join(map(str, p)))
return guesses
Simply call this function with guessables(4) and get a list with all the numbers you want.
You can do in one line:
print([str(a)+str(b)+str(c)+str(d) for a in range(1,10) for b in range(0,10) if a!=b for c in range(0,10) if b!=c and a!=c for d in range(0,10) if c!=d and d!=b and d!=a])
Try the following:
def guessables(n):
''' Returns an array with the combination of different digits of size "n" '''
if n > 10:
raise ValueError("The maximum number of different digits is 10.")
elif n < 1:
raise ValueError("The minimum number of digits is 1.")
else:
results = []
for i in range(1, 10):
_recursiveDigit([i], n, results)
return results
def _formatDigit(l):
''' Return a formated number from a list of its digits. '''
return "".join(map(str, l))
def _recursiveDigit(l, n, results):
''' Recursive function to calculate the following digit. '''
if len(l) < n:
for i in range(0, 10):
if i not in l:
_recursiveDigit(l + [i], n, results)
else:
results.append(_formatDigit(l))
The functions that are prefixed with an underscore(_) should not be called from outside of this script. If you prefer to have the result as something different than an array of strings, such as an array of ints for example, you can change the _formatDigit() function as follows:
def _formatDigit(l):
''' Return a formated number from a list of its digits. '''
return int("".join(map(str, l)))
c=list(range(10))
print c
def fun(n,k,i,getnum): # function , result in getnum
if n==0:
if k not in getnum and len(set(list(k)))==len(k) and k[0]!='0':
getnum.append(k)
return
if i>=len(c):
return
fun(n-1,k+str(c[i]),0,getnum)
fun(n,k,i+1,getnum)
getnum=[]
d=fun(4,"",0,getnum)
print getnum
These types of problems are easily solved with recursion.
def gen(num, n, saveto):
if len(num) == 1 and num[0] == '0':
return
if len(num) == n:
saveto.append(int(''.join(num)))
return
for i in range(0, 10):
i= str(i)
if i not in num:
gen(num+[i], n, saveto)
saveto= []
# generate 4 digit numbers
gen([], 4, saveto)
print(saveto)
Here I'm using the list num to construct the numbers by placing one digit at each call. When there are four digits added, it stores the number to the saveto list.
Edit: Here's a version of the above function that returns the list of numbers instead of appending them to a list.
def gen(num, n):
if len(num) == 1 and num[0] == '0':
return []
if len(num) == n:
return [int(''.join(num))]
ans = []
for i in range(0, 10):
i= str(i)
if i not in num:
ans.extend(gen(num+[i], n))
return ans
saveto= gen([], 4)
print(saveto)
numPool = []
for i in range(0, 10):
for j in range(0, 10):
for k in range(0,10):
for l in range(0,10):
if i != j and i != k and i != l and j != k and j != l and k != l :
numPool.append(str(i) + str(j) + str(k) + str(l))
This works, but keep in mind that this will also add "0123" or "0234" to the list as well. If you do not want the numbers that are starting with zero, you might want to add "i != 0" to the if query. Hope it helps.
I try to write it clear for absolute beginers ^^ Ofcourse it is possible to make it faster and shorter if you use combianations and advance array methods.
def f(n)
s = list(range(10**(n-1), 10**n))
number_list = []
for ss in s:
test_list = []
a = ss
while ss:
if ss % 10 in test_list:
break
test_list.append(ss % 10)
ss = ss // 10
if len(test_list) == n:
number_list.append(a)
return number_list
print(f(4))
This would sovlve the problem, without repeating digits:
from itertools import permutations
myperm = permutations([0,1,2,3,4,5,6,7,8,9],4)
for digits in list(myperm):
print(digits)
How about this?
def check_count(num):
if isinstance(num, str) == False:
num = str(num) # Convert to str
if len(num) == 1: # If total length number is single, return False
return False
return any(num.count(x) > 1 for x in num) # Check here
Return False if numbers all different, else return True
Usage:
# Get all numbers has all different. (1000-9999)
[x for x in range(1000, 10000) if check_count(x) == False]

List of prime numbers - unexpected output

output: <generator object <genexpr> at 0x00000293AA2F8E60> instead of the list of prime numbers that I was attempting to obtain.
import math
#here i try to use trial division to validate whether a number is false or not
def isPrime(n):
d = {}
u = math.floor(math.sqrt(n))
i = 2
while (i <= u):
if (n % i == 0):
return False
i +=1
return True
#here I attempt to find all the prime numbers between 1 and 5000
print(isPrime(n) for n in range(1,5000))
You built a generator, and then told Python to print that object. That's what you got. From your description, I think that you want a list comprehension that will give you a list of primes.
Try this:
print ( [n for n in range(1, 5000) if isPrime(n) ] )
Note that you want to print the prime number, not the return value from isPrime.
I think what you're trying to do is this:
import math
def isPrime(n):
u = math.floor(math.sqrt(n))
i = 2
while (i <= u):
if (n % i == 0):
return False
i +=1
return True
for n in range(1, 5000):
print(isPrime(n))

Evenly intermix two lists of elements (load balance)

Let's say I have two strings made with only 1 character:
'aaaaaaa'
'bbb'
I'd like to find an algorithm to produce a combined string of:
'aabaabaaba'
The two are merged so that there is the fewest # of consecutive characters from either list (in this case that # is 2). The length of each string is arbitrary, and I'd like for it to be symmetrical. Bonus points for extending it to more than just 2 strings.
I am doing this in python, but the language doesn't matter. This is for a load balancing problem I'm working on.
You can use the elements alternatively and use a letter of the longer string if necessary. You can determine whether an additional letter is possible with integer arithmetics: A fraction tells you how many letters come between each letter pair. You accumulate this fraction and use letters from the longer array as long as that accumulated fraction is larger than ½:
def intertwine(a, b):
""" Return a combination of string with fewest number of
consecutive elements from one string
"""
if len(b) > len(a):
return intertwine(b, a)
if not b:
return a
a = list(a)
b = list(b)
num = len(a) - len(b)
denom = len(b)
acc = 0
res = []
while a or b:
acc += num
while acc >= denom / 2:
if a: res += a.pop(0)
acc -= num
if a: res += a.pop(0)
if b: res += b.pop(0)
return "".join(res)
print intertwine("aaabaaa", "bbb") # "aababbaaba"
print intertwine("aaaaaaa", "b") # "aaabaaaa"
print intertwine("aaaaaa", "b") # "aaabaaa"
print intertwine("aa", "bbbbbb") # "bbabbabb"
print intertwine("", "bbbbbb") # "bbbbbb"
print intertwine("", "") # ""
import itertools
def intermix(*containers):
mix = []
for c in sorted(containers, key=lambda c: len(c)):
if len(c) >= len(mix):
bigger, smaller = c, mix
else:
bigger, smaller = mix, c
ratio, remainder = divmod(len(bigger), len(smaller) + 1)
chunk_sizes = (ratio + (1 if i < remainder else 0) for i in range(len(smaller) + 1))
chunk_offsets = itertools.accumulate(chunk_sizes)
off_start = 0
new_mix = []
for i, off in enumerate(chunk_offsets):
new_mix.extend(bigger[off_start:off])
if i == len(smaller):
break
new_mix.append(smaller[i])
off_start = off
mix = new_mix
return mix

Prime factorization - list

I am trying to implement a function primeFac() that takes as input a positive integer n and returns a list containing all the numbers in the prime factorization of n.
I have gotten this far but I think it would be better to use recursion here, not sure how to create a recursive code here, what would be the base case? to start with.
My code:
def primes(n):
primfac = []
d = 2
while (n > 1):
if n%d==0:
primfac.append(d)
# how do I continue from here... ?
A simple trial division:
def primes(n):
primfac = []
d = 2
while d*d <= n:
while (n % d) == 0:
primfac.append(d) # supposing you want multiple factors repeated
n //= d
d += 1
if n > 1:
primfac.append(n)
return primfac
with O(sqrt(n)) complexity (worst case). You can easily improve it by special-casing 2 and looping only over odd d (or special-casing more small primes and looping over fewer possible divisors).
The primefac module does factorizations with all the fancy techniques mathematicians have developed over the centuries:
#!python
import primefac
import sys
n = int( sys.argv[1] )
factors = list( primefac.primefac(n) )
print '\n'.join(map(str, factors))
This is a comprehension based solution, it might be the closest you can get to a recursive solution in Python while being possible to use for large numbers.
You can get proper divisors with one line:
divisors = [ d for d in xrange(2,int(math.sqrt(n))) if n % d == 0 ]
then we can test for a number in divisors to be prime:
def isprime(d): return all( d % od != 0 for od in divisors if od != d )
which tests that no other divisors divides d.
Then we can filter prime divisors:
prime_divisors = [ d for d in divisors if isprime(d) ]
Of course, it can be combined in a single function:
def primes(n):
divisors = [ d for d in range(2,n//2+1) if n % d == 0 ]
return [ d for d in divisors if \
all( d % od != 0 for od in divisors if od != d ) ]
Here, the \ is there to break the line without messing with Python indentation.
I've tweaked #user448810's answer to use iterators from itertools (and python3.4, but it should be back-portable). The solution is about 15% faster.
import itertools
def factors(n):
f = 2
increments = itertools.chain([1,2,2], itertools.cycle([4,2,4,2,4,6,2,6]))
for incr in increments:
if f*f > n:
break
while n % f == 0:
yield f
n //= f
f += incr
if n > 1:
yield n
Note that this returns an iterable, not a list. Wrap it in list() if that's what you want.
Most of the above solutions appear somewhat incomplete. A prime factorization would repeat each prime factor of the number (e.g. 9 = [3 3]).
Also, the above solutions could be written as lazy functions for implementation convenience.
The use sieve Of Eratosthenes to find primes to test is optimal, but; the above implementation used more memory than necessary.
I'm not certain if/how "wheel factorization" would be superior to applying only prime factors, for division tests of n.
While these solution are indeed helpful, I'd suggest the following two functions -
Function-1 :
def primes(n):
if n < 2: return
yield 2
plist = [2]
for i in range(3,n):
test = True
for j in plist:
if j>n**0.5:
break
if i%j==0:
test = False
break
if test:
plist.append(i)
yield i
Function-2 :
def pfactors(n):
for p in primes(n):
while n%p==0:
yield p
n=n//p
if n==1: return
list(pfactors(99999))
[3, 3, 41, 271]
3*3*41*271
99999
list(pfactors(13290059))
[3119, 4261]
3119*4261
13290059
Here is my version of factorization by trial division, which incorporates the optimization of dividing only by two and the odd integers proposed by Daniel Fischer:
def factors(n):
f, fs = 3, []
while n % 2 == 0:
fs.append(2)
n /= 2
while f * f <= n:
while n % f == 0:
fs.append(f)
n /= f
f += 2
if n > 1: fs.append(n)
return fs
An improvement on trial division by two and the odd numbers is wheel factorization, which uses a cyclic set of gaps between potential primes to greatly reduce the number of trial divisions. Here we use a 2,3,5-wheel:
def factors(n):
gaps = [1,2,2,4,2,4,2,4,6,2,6]
length, cycle = 11, 3
f, fs, nxt = 2, [], 0
while f * f <= n:
while n % f == 0:
fs.append(f)
n /= f
f += gaps[nxt]
nxt += 1
if nxt == length:
nxt = cycle
if n > 1: fs.append(n)
return fs
Thus, print factors(13290059) will output [3119, 4261]. Factoring wheels have the same O(sqrt(n)) time complexity as normal trial division, but will be two or three times faster in practice.
I've done a lot of work with prime numbers at my blog. Please feel free to visit and study.
def get_prime_factors(number):
"""
Return prime factor list for a given number
number - an integer number
Example: get_prime_factors(8) --> [2, 2, 2].
"""
if number == 1:
return []
# We have to begin with 2 instead of 1 or 0
# to avoid the calls infinite or the division by 0
for i in xrange(2, number):
# Get remainder and quotient
rd, qt = divmod(number, i)
if not qt: # if equal to zero
return [i] + get_prime_factors(rd)
return [number]
Most of the answer are making things too complex. We can do this
def prime_factors(n):
num = []
#add 2 to list or prime factors and remove all even numbers(like sieve of ertosthenes)
while(n%2 == 0):
num.append(2)
n /= 2
#divide by odd numbers and remove all of their multiples increment by 2 if no perfectlly devides add it
for i in xrange(3, int(sqrt(n))+1, 2):
while (n%i == 0):
num.append(i)
n /= i
#if no is > 2 i.e no is a prime number that is only divisible by itself add it
if n>2:
num.append(n)
print (num)
Algorithm from GeeksforGeeks
prime factors of a number:
def primefactors(x):
factorlist=[]
loop=2
while loop<=x:
if x%loop==0:
x//=loop
factorlist.append(loop)
else:
loop+=1
return factorlist
x = int(input())
alist=primefactors(x)
print(alist)
You'll get the list.
If you want to get the pairs of prime factors of a number try this:
http://pythonplanet.blogspot.in/2015/09/list-of-all-unique-pairs-of-prime.html
def factorize(n):
for f in range(2,n//2+1):
while n%f == 0:
n //= f
yield f
It's slow but dead simple. If you want to create a command-line utility, you could do:
import sys
[print(i) for i in factorize(int(sys.argv[1]))]
Here is an efficient way to accomplish what you need:
def prime_factors(n):
l = []
if n < 2: return l
if n&1==0:
l.append(2)
while n&1==0: n>>=1
i = 3
m = int(math.sqrt(n))+1
while i < m:
if n%i==0:
l.append(i)
while n%i==0: n//=i
i+= 2
m = int(math.sqrt(n))+1
if n>2: l.append(n)
return l
prime_factors(198765430488765430290) = [2, 3, 5, 7, 11, 13, 19, 23, 3607, 3803, 52579]
You can use sieve Of Eratosthenes to generate all the primes up to (n/2) + 1 and then use a list comprehension to get all the prime factors:
def rwh_primes2(n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
""" Input n>=6, Returns a list of primes, 2 <= p < n """
correction = (n%6>1)
n = {0:n,1:n-1,2:n+4,3:n+3,4:n+2,5:n+1}[n%6]
sieve = [True] * (n/3)
sieve[0] = False
for i in xrange(int(n**0.5)/3+1):
if sieve[i]:
k=3*i+1|1
sieve[ ((k*k)/3) ::2*k]=[False]*((n/6-(k*k)/6-1)/k+1)
sieve[(k*k+4*k-2*k*(i&1))/3::2*k]=[False]*((n/6-(k*k+4*k-2*k*(i&1))/6-1)/k+1)
return [2,3] + [3*i+1|1 for i in xrange(1,n/3-correction) if sieve[i]]
def primeFacs(n):
primes = rwh_primes2((n/2)+1)
return [x for x in primes if n%x == 0]
print primeFacs(99999)
#[3, 41, 271]
from sets import Set
# this function generates all the possible factors of a required number x
def factors_mult(X):
L = []
[L.append(i) for i in range(2,X) if X % i == 0]
return L
# this function generates list containing prime numbers upto the required number x
def prime_range(X):
l = [2]
for i in range(3,X+1):
for j in range(2,i):
if i % j == 0:
break
else:
l.append(i)
return l
# This function computes the intersection of the two lists by invoking Set from the sets module
def prime_factors(X):
y = Set(prime_range(X))
z = Set(factors_mult(X))
k = list(y & z)
k = sorted(k)
print "The prime factors of " + str(X) + " is ", k
# for eg
prime_factors(356)
Simple way to get the desired solution
def Factor(n):
d = 2
factors = []
while n >= d*d:
if n % d == 0:
n//=d
# print(d,end = " ")
factors.append(d)
else:
d = d+1
if n>1:
# print(int(n))
factors.append(n)
return factors
This is the code I made. It works fine for numbers with small primes, but it takes a while for numbers with primes in the millions.
def pfactor(num):
div = 2
pflist = []
while div <= num:
if num % div == 0:
pflist.append(div)
num /= div
else:
div += 1
# The stuff afterwards is just to convert the list of primes into an expression
pfex = ''
for item in list(set(pflist)):
pfex += str(item) + '^' + str(pflist.count(item)) + ' * '
pfex = pfex[0:-3]
return pfex
I would like to share my code for finding the prime factors of number given input by the user:
a = int(input("Enter a number: "))
def prime(a):
b = list()
i = 1
while i<=a:
if a%i ==0 and i!=1 and i!=a:
b.append(i)
i+=1
return b
c = list()
for x in prime(a):
if len(prime(x)) == 0:
c.append(x)
print(c)
def prime_factors(num, dd=2):
while dd <= num and num>1:
if num % dd == 0:
num //= dd
yield dd
dd +=1
Lot of answers above fail on small primes, e.g. 3, 5 and 7. The above is succinct and fast enough for ordinary use.
print list(prime_factors(3))
[3]

Categories

Resources