Stripped Python code below. Create a .py file and paste the code therein. Don't forget to create your "DestDir" folder in same directory. (There are much neater scripts elsewhere on the web on this topic. Analytical solutions in Python are not my strong suit...)
*
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as N
from   scipy import interpolate
from   sympy import N as symN
from   sympy.solvers import solve
from   sympy import sqrt,atan,sin,cos,Symbol,re,im,diff
import scipy.linalg as SLA
def mm(* args):
    tmp=N.dot(args[0],args[1])
    for ii in range(len(args)-2):
        tmp=N.dot(tmp,args[ii+2])
    return tmp
def myangle(xp1,yp1):
    if xp1<0 and yp1<0:
        ang = N.pi+N.arctan(yp1/xp1)
    elif xp1>0 and yp1<0:
        ang = N.arctan(yp1/xp1)
    return ang
NN=10000
mycircle = N.array([[1.01*N.cos(2*N.pi*ii/NN),\
                     1.01*N.sin(2*N.pi*ii/NN)] for ii in range(NN)]).T
#Parameters
g             = 9.81 #acceleration
startposition = -.5  #along x axis. 0 is center of circle
noballs       = 10   #number of balls
jumps         = 5    #number of bounces
dt            = .005 #time increment, should be small
eps           = 1e-2 #difference between adjacent balls
def findpaths(xp1,yp1,v0):
    for kk in range(jumps):
        angle = myangle(xp1,yp1)
        dvec = [-N.sin(angle),N.cos(angle)]
        nvec = [-dvec[1],dvec[0]]
        nvec = nvec/N.sqrt(mm(nvec,nvec))
        if kk == 0:
            ivec = [0,-1]
            ivec = N.array([float(ivec[0]),float(ivec[1])])
            ivec = ivec/SLA.norm(ivec)
        else:
            ivec = [1,slope]
            ivec = N.array([float(ivec[0]),float(ivec[1])])
            ivec = ivec/SLA.norm(ivec)
            if slope>0 and xp1<0:
                ivec[0] = -abs(ivec[0])
                ivec[1] = -abs(ivec[1])
            if slope<0 and xp1<0:
                ivec[0] = -abs(ivec[0])
                ivec[1] = abs(ivec[1])
            if slope>0 and xp1>0:
                ivec[0] = -abs(ivec[0])
                ivec[1] = -abs(ivec[1])
            if slope<0 and xp1>xp0:
                ivec[0] = abs(ivec[0])
                ivec[1] = -abs(ivec[1])
            if slope>0 and xp1>xp0:    
                ivec[0] = abs(ivec[0])
                ivec[1] = abs(ivec[1])
        rvec = (ivec-mm(2*mm(ivec,nvec),nvec))
        rvec = N.array([float(rvec[0]),float(rvec[1])])
        rvec = rvec/SLA.norm(rvec)
        v0 = v0*rvec
        vx = v0[0]
        vy0 = v0[1]
        x = Symbol('x')
        sol = solve(x**2 + (vy0/vx*(x-xp1)-g/2/vx**2*(x-xp1)**2+yp1)**2 - 1,x)
        for ii in range(len(sol)):
            if abs(re(sol[ii])-xp1)>1e-8 and abs(im(sol[ii]))<1e-4: 
                soln = re(sol[ii])
        xi,xe = xp1,soln
        xp0 = xp1
        yp0 = yp1
        pathx = N.arange(xi,xe,dt*vx)
        pathy = vy0/vx*(pathx-xi)-g/2/vx**2*(pathx-xi)**2+yp1
        xs = Symbol('xs')
        slope = diff(vy0/vx*(xs-xi)-g/2/vx**2*(xs-xi)**2+yp1).evalf(subs={xs:xe})
        yp1 = vy0/vx*(xe-xi)-g/2/vx**2*(xe-xi)**2+yp1
        yp1 = float(yp1)
        xp1 = float(xe)
        slope = float(slope)
        Etot = g*(1+y0)
        Ep = g*(1+yp1)
        v0 = (2*(Etot-Ep))**.5
        ballpaths.append([pathx,pathy])
    return ballpaths
ball = []
for ll in range(noballs):
    print('ball',ll)
    x0 = startposition+ll*eps 
    y0 = .0
    xp1 = x0
    yp1 = -N.sqrt(1-xp1**2)
    ds = N.sqrt((y0-yp1)**2)
    t0 = N.sqrt(2*ds/g)
    v0 = g*t0
    xtot0,ytot0 = [],[]
    tt = 0
    while dt*tt<t0:
        ytot0.append(y0-g*(dt*tt)**2/2)
        xtot0.append(x0)
        tt+=1
    xtot,ytot = N.array(xtot0),N.array(ytot0)
    ballpaths = []
    p = findpaths(xp1,yp1,v0)
    xtot = N.concatenate([xtot,p[0][0]])
    ytot = N.concatenate([ytot,p[0][1]])
    #ytot = p[0][1]
    for ii in range(1,jumps):
        xtot = N.concatenate([xtot,p[ii][0]])
        ytot = N.concatenate([ytot,p[ii][1]])
    ball.append([xtot,ytot])
print(len(ball))
for ii in range(len(xtot)):
    print(ii,'of',len(xtot))
    plt.plot(mycircle[0],mycircle[1])
    for bb in range(noballs):
        plt.plot(ball[bb][0][ii],ball[bb][1][ii],marker='.')
    plt.savefig('DestDir/fig'+f"{ii:05d}.png",bbox_inches='tight',pad_inches=0)
    plt.clf()