## loading python libraries
# necessary to display plots inline:
%matplotlib inline
# load the libraries
import matplotlib.pyplot as plt # 2D plotting library
import numpy as np # package for scientific computing
import sympy as sympy # package for symbolic computation
from sympy import *
from math import * # package for mathematics (pi, arctan, sqrt, factorial ...)
def ProductOfDigits(n):
# input: integer n
# output: product of digits of n
if n<10:
return n
else:
return n%10*ProductOfDigits(n//10)
ProductOfDigits(2281)
#T=500
#plt.plot([ProductOfDigits(n) for n in range(T)],'.')
#plt.plot([k**(np.log(9)/np.log(10)) for k in range(T)])
#plt.show()
32
For an integer $n$, we consider the following procedure. Multiply all the digits of $n$ by each other, repeating with the product until a single digit is obtained. Let us denote by $\mathrm{M}(n)$ the number of steps required to get one single digit number, starting from $n$. (If $n<10$ we set $\mathrm{M}(n)=0$.)
For example, for $n=2281$:
$$
2281 \stackrel{\text{1st step}}{\longrightarrow} 2\times 2\times 8\times 1= 32 \stackrel{\text{2d step}}{\longrightarrow} 3\times 2 =6.
$$
Therefore $\mathrm{M}(2281)=2$.
def MultiplicativePersistence(n):
# input: n=integers
# output: mult.persistence
if n<10:
return 0
else:
return MultiplicativePersistence(ProductOfDigits(n))+1
print(MultiplicativePersistence(2281))
2
n=1
PersistenceLargerThanSeven = False
while PersistenceLargerThanSeven == False:
n=n+1
if MultiplicativePersistence(n) > 6:
PersistenceLargerThanSeven=True
print(str(n)+' has a persistence equal to '+str(MultiplicativePersistence(n)))
68889 has a persistence equal to 7
# Script A
# Computing the first bound
n=1
u=(9/10)**(np.floor(np.log(n)/np.log(10)))
while u>0.5:
u=(9/10)**(np.floor(np.log(n)/np.log(10)))
n=n+1
print('Above ',n,' the ratio is less than 0.5')
Above 10000001 the ratio is less than 0.5
# Script B
# maximal persistence up to M
n=1
M=10**7
record=0
while n<= M:
record=max(record,MultiplicativePersistence(n))
n=n+1
print(record)
8
This problem is defined as follows. Let $L=[a_1,a_2,\dots,a_k]$ be a list of distinct positive integers.
For a fixed integer $n\geq 1$ we want to find the number of solutions $(x_1,\dots,x_k)$ to the equation
$$
a_1 x_1 +a_2 x_2 + \dots a_k x_k=n, \qquad\qquad (\star)
$$
where $x_i$'s are non-negative integers.
We denote by $H_n(L)$ be the number of such solutions. For example if $L=[1,2,5]$ then $H_6([1,2,5])=5$, since
In other words, the solutions to $(\star)$ are: $$ (x_1,x_2,x_3)=(1,0,1),\quad (0,3,0),\quad (2,2,0),\quad (4,1,0),\quad (6,0,0) $$
The typical questions we will ask are:
Throughout the exercise we focus on the case $L=[1,2,5]$.
def H_12(n):
# return the number of solutions H_n([1,2])
if n<=1:
return 1
elif n==2:
return 2 # (2 solutions: 1+1 or 2)
else:
return 1+H_12(n-2)
print([H_12(k) for k in range(14)])
def H_125(n):
# return the number of solutions H_n([1,2,5])
if n<=4:
return H_12(n) # one cannot use 5
elif n==5:
return H_12(n)+1 # one other solution: 5
else:
return 1+H_12(n-2)+H_125(n-5)
print(H_125(30))
NN=range(300,1000,2)
Y=[H_125(n)/(n**2/20) for n in NN]
plt.plot(NN,Y,'o-')
plt.show()
[1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7] 58
def FirstDigit(n):
# input: integer n
# output: First digit (in {1,...,9})
if n<10:
return n
else:
return FirstDigit(n//10)
# test
print(FirstDigit(516))
5
The Benford distribution is the probability distribution $(p_k)_{1\leq k\leq 9}$ on $\{1,2,\dots, 9\}$ defined by $$ p_k=\log_{10}(k+1)-\log_{10}(k), $$ where $\log_{10}$ stands for the logarithm in basis $10$. Benford's law of anomalous numbers states that for many data sets the leftmost digit is not uniformly distributed but follows rather the Benford distribution. We want to illustrate the fact that the data set $2,2^2,2^3,2^4,2^5,\dots,2^n$ satisfies Benford's law (when $n$ is large).
n=80
FirstDigitPowersOfTwo=[FirstDigit(2**i) for i in range(n)]
Benford=[np.log((k+1.0)/k)/np.log(10) for k in range(1,10)]
#print(FirstDigitPowersOfTwo)
plt.plot(np.arange(1,10),Benford,'ro',label='Benford distribution')
plt.hist(FirstDigitPowersOfTwo, bins= [k+0.5 for k in range(10)], density=True, ec='k')#,facecolor='g', alpha=0.2,label='Frequency of digits') # Histogramme normalise
plt.legend()
plt.show()
The Kruskal–Katona decomposition states that for every integers $n,\ell\geq 1$ there exists an integer $t$ and $a_\ell>a_{\ell-1}>a_{\ell-2}>\dots >a_1$ with $$ n=\binom{a_\ell}{\ell} + \binom{a_{\ell-1}}{\ell-1} + \dots + \binom{a_t}{t}. $$ The decomposition is explicit and given by the following greedy recursive algorithm:
For example for $n=62$, $\ell=5$ one gets \begin{align*} 62&=\binom{8}{5}+\binom{5}{4}+\binom{3}{3}\\ &= 56+5+1 \end{align*}
import scipy.special
int(scipy.special.binom(8, 5))
def a_max(n,l):
# input: integers n,l
# output: largest a such that \binom{a}{l} \leq n
a=l
#while int(scipy.special.binom(a,l))<=n:
while scipy.special.binom(a,l)<=n:
a=a+1
return a-1
#print(scipy.special.binom(8,5))
#print(scipy.special.binom(21,2))
print(a_max(0,5))
def Katona(n,l):
# input: integers n,l \geq 1
# output: Katona's decomposition of n,l
#if l>n:
# return []
if n==0:
return []
elif l==1:
return [[n,1]]
else:
a=a_max(n,l)
#return [[a,l]]+Katona(n-int(scipy.special.binom(a,l)),l-1)
return [[a,l]]+Katona(n-scipy.special.binom(a,l),l-1)
print(Katona(300,11))
4 [[13, 11], [12, 10], [11, 9], [10, 8], [9, 7], [7, 6], [6, 5], [5, 4], [3, 3], [2, 2]]