Esta versión solo encuentra la mínima diferencia. Esta encuentra

Anuncio
corregidor Toggle Home Published Log Settings Help Report a Problem Sign out
The Sage
Notebook
Version 5.2
nombre.apellido_Final2013_resuelto
Save
Save & quit
Discard & quit
last edited May 21, 2013 6:25:18 PM by corregidor
Action...
File...
Data...
sage
Typeset
Print Worksheet Edit Text Revisions Share Publish
Nombre: ........................................ Apellidos:............................................
Grupo: ................ DNI:............................
Instrucciones
Rellena con tus datos la parte superior de este cuadro.
Renombra la hoja de sage, con el siguiente formato: nombre.apellido_Final2013. Por supuesto, cambia el nombre.apellido por tu nombre.apellido (tal y como
aparecen en tu dirección de correo de estudiante).
Ejercicio 1 (1 punto) Encuentra, por ejemplo "por fuerza bruta", la resta entre dos números de tres cifras escritos usando (todos) los seis dígitos 1, 3, 4, 5, 6, 8 con resultado positivo y mínimo entre todos las restas que se pueden formar con esas cifras.
#Versión 1
nums=[1,3,4,5,6,8]
restas=set()
for pp in Permutations(nums,6):
p1=sum([10^j*pp[j] for j in range(3)])
p2=sum([10^j*pp[j+3] for j in range(3)])
restas.add(abs(p1-p2))
min(restas)
)WXE ZIVWM¶R WSPS IRGYIRXVE PE Q°RMQE
HMJIVIRGME
27
#Versión 2
nums=[1,3,4,5,6,8]
restas=dict()
for pp in Permutations(nums,6):
p1=sum([10^j*pp[j] for j in range(3)])
p2=sum([10^j*pp[j+3] for j in range(3)])
resta=abs(p1-p2)
if resta not in restas:
restas[resta]=[(p1,p2)]
else:
restas[resta].append((p1,p2))
m=min(restas)
restas[m],m
)WXE IRGYIRXVE EHIQ¤W XSHEW PEW
GSQFMREGMSRIW UYI HER IWE Q°RMQE
HMJIVIRGME
([(513, 486), (486, 513)], 27)
#Versión 3
nums=[1,3,4,5,6,8]
%UY° IQTMI^E YRE
ll=[]
for trio in Combinations(nums,3):
TSV JYIV^E FVYXE
ll2=[]
for terna in Permutations(trio):
ll2.append(sum([terna[j]*10^j for j in range(3)]))
ll.append((trio,ll2))
ll
TSWMFPI VIWTYIWXE
[([1, 3, 4], [431, 341, 413, 143, 314, 134]), ([1, 3, 5], [531, 351,
513, 153, 315, 135]), ([1, 3, 6], [631, 361, 613, 163, 316, 136]), ([1,
3, 8], [831, 381, 813, 183, 318, 138]), ([1, 4, 5], [541, 451, 514, 154,
415, 145]), ([1, 4, 6], [641, 461, 614, 164, 416, 146]), ([1, 4, 8],
[841, 481, 814, 184, 418, 148]), ([1, 5, 6], [651, 561, 615, 165, 516,
156]), ([1, 5, 8], [851, 581, 815, 185, 518, 158]), ([1, 6, 8], [861,
681, 816, 186, 618, 168]), ([3, 4, 5], [543, 453, 534, 354, 435, 345]),
([3, 4, 6], [643, 463, 634, 364, 436, 346]), ([3, 4, 8], [843, 483, 834,
384, 438, 348]), ([3, 5, 6], [653, 563, 635, 365, 536, 356]), ([3, 5,
8], [853, 583, 835, 385, 538, 358]), ([3, 6, 8], [863, 683, 836, 386,
638, 368]), ([4, 5, 6], [654, 564, 645, 465, 546, 456]), ([4, 5, 8],
[854, 584, 845, 485, 548, 458]), ([4, 6, 8], [864, 684, 846, 486, 648,
468]), ([5, 6, 8], [865, 685, 856, 586, 658, 568])]
restas=[]
for par1 in ll:
for par2 in ll:
if set(par1[0]+par2[0])==set(nums):
for n1 in par1[1]:
for n2 in par2[1]:
restas.append((n1,n2,abs(n1-n2)))
len(restas)
720
m=min([restas[j][-1] for j in range(len(restas))])
solorestas=[resta[-1] for resta in restas]
j=solorestas.index(m)
restas[j]
(513, 486, 27)
Ejercicio 2 (1 punto) Usando el "alfabeto" que el siguiente cuadro de comandos guarda en la variable AByz, escribir código que, a partir de una palabra dada,
produzca otra del modo siguiente:
cambiar cada letra por la letra que ocupa en AByz su misma posición (midiendo con el índice) multiplicada por 3. Si al multiplicar sobrepasamos la longitud de
AByz, empezaremos, con lo que reste, por el principio (alfabeto circular).
AByz=join([chr(j) for j in range(65,91)] + [chr(j) for j in range(97,123)],''); AByz
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
def codifica(palabra,clave=3,alfabeto=AByz):
if any([not(letra in AByz) for letra in palabra]):
print u'La palabra %s tiene alguna letra inválida'%palabra
return None
L=len(AByz)
pal=''
for letra in palabra:
pal+=AByz[(AByz.index(letra)*clave)%L]
return pal
2S WI TMHI TIVS IW VIGSQIRHEFPI
clave=3
L=len(AByz)
contraclave=clave.inverse_mod(L)
codifica(codifica(AByz),contraclave)
)R IWXI GYEHVS WI TVYIFE PE JYRGM¶R
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
codifica(codifica(AByz),contraclave)==AByz
3XVE GSQTVSFEGM¶R 7M WEPMIVE *EPWI RS WIV°E GSVVIGXE
True
Ejercicio 3 (1 punto) Elabora código que encuentre tres primos consecutivos mayores que 103 de manera que el menor y el mayor disten exactamente 50 unidades.
N=10^3
objetivo=50
n1=next_prime(N)
8VIW TVMQIVSW TVMQSW
n2=next_prime(n1)
n3=next_prime(n2)
while (n3-n1)!=objetivo:
'SRHMGM¶R
n1,n2,n3=n2,n3,next_prime(n3)
n1,n2,n3
GSRWIGYXMZSW "
B
HI RS TEVEHE ! RS WI LE PPIKEHS EP SFNIXMZS
'EQFMEQSW EGXYEPM^EQSW PSW XVIW TVMQSW
(9551, 9587, 9601)
2SXE EJSVXYREHEQIRXI EPKYRE ZI^ WI EPGER^E IP SFNIXMZS
Ejercicio 4 (4 puntos) Ordenar una lista de enteros desordenados es una de las operaciones básicas que se pueden hacer con un ordenador, y, cuando la lista es
enorme, puede exigir demasiado tiempo de cálculo. En este ejercicio hay que programar dos de los métodos existentes para ordenar listas, vamos a ordenarlas en
orden creciente, y compararemos los resultados.
1. Primer algoritmo (Insertion sort):
1. Define una función de SAGE intercambiar(L, i), con argumentos una lista y un entero, y tal que devuelva la lista que se obtiene intercambiando el
elemento i­ésimo de la lista con el i − 1­ésimo si el i­ésimo es menor que el i − 1­ésimo. El entero i debe estar comprendido entre 0 y len(L) − 1 , y si
no lo está la función debe devolver un mensaje de error.
2. Define una segunda función ordenar1(L) que, usando intercambiar(L, i), devuelva la lista L ordenada. Obsérvese que para que la lista quede
ordenada hay que comparar cada elemento de la lista con TODOS los anteriores.
2. Segundo algoritmo (Mergesort):
1. Este es un algoritmo recursivo que también utiliza una función auxiliar. Define una función de SAGE intercalar(L, L1, L2) de tres listas que haga lo
siguiente: si el primer elemento de L1 es menor o igual que el primero de L2 debe quitar el primer elemento de L1, añadirlo a L y volver a llamar a la
función intercalar(L, L1, L2); en caso contrario quitar el primer elemento de L2, añadirlo a L y volver a llamar a la función intercalar(L, L1, L2).
Las recursiones deben parar cuando una de las dos listas (L1 o L2) sea vacía y devolver la suma de las tres listas L + L1 + L2.
2. Define una función de SAGE ordenar2(L) que primero trate los casos en que len(L) ≤ 2 y devuelva intercalar([], L1, L2) con L1 y L2 las listas
que se obtienen aplicando ordenar2 a las dos "mitades" de L (si el número de elementos de L es impar una de las "mitades"tiene un elemento más que
la otra). Es importante observar que cuando llamamos a intercalar las listas L1 y L2 ya están ordenadas.
Compara la eficiencia de los dos métodos generando una lista de 800 enteros aleatorios comprendidos entre −1000 y 1000 y midiendo el tiempo que el ordenador
tarda en ordenarlas.
def intercambiar(LL,i):
L=list(LL)
if not(0<=i<=len(L)-1):
print u'La operación no es posible'
return None
if L[i]<L[i-1]:
L[i-1],L[i]=L[i],L[i-1]
return L
%TEVXEHS
intercambiar([2,1,3,2],1)
[1, 2, 3, 2]
intercambiar([1,3,2],2)
4VYIFEW
[1, 2, 3]
intercambiar([1,3],2)
La operación no es posible
def ordenar1(ll):
l=list(ll)
L=len(l)
for j in range(L-1,0,-1):
l=intercambiar(l,j)
for k in range(L-1,0,-1):
l=intercambiar(l,k)
return l
%TEVXEHS
ordenar1([randint(0,15) for j in range(20)])
9RE GSQTVSFEGM¶R GSR YRE PMWXE HI
EP E^EV
R½QIVSW
[0, 0, 0, 2, 3, 5, 5, 5, 6, 6, 6, 7, 7, 8, 9, 10, 10, 12, 13, 14]
Segundo algoritmo (Mergesort):
1. Este es un algoritmo recursivo que también utiliza una función auxiliar. Define una función de SAGE intercalar(L, L1, L2) de tres listas que haga lo
siguiente: si el primer elemento de L1 es menor o igual que el primero de L2 debe quitar el primer elemento de L1, añadirlo a L y volver a llamar a la función
intercalar(L, L1, L2); en caso contrario quitar el primer elemento de L2, añadirlo a L y volver a llamar a la función intercalar(L, L1, L2). Las recursiones
deben parar cuando una de las dos listas (L1 o L2) sea vacía y devolver la suma de las tres listas L + L1 + L2.
2. Define una función de SAGE ordenar2(L) que primero trate los casos en que len(L) ≤ 2 y devuelva intercalar([], L1, L2) con L1 y L2 las listas que se
obtienen aplicando ordenar2 a las dos "mitades" de L (si el número de elementos de L es impar una de las "mitades"tiene un elemento más que la otra). Es
importante observar que cuando llamamos a intercalar las listas L1 y L2 ya están ordenadas.
def intercalar(L,L1,L2):
if not L1 or not L2:
return L+L1+L2
if L1[0]<=L2[0]:
L.append(L1[0])
L1.remove(L1[0])
else:
L.append(L2[0])
L2.remove(L2[0])
return intercalar(L,L1,L2)
%TEVXEHS
intercalar([2],[3,2],[1,4])
[2, 1, 3, 2, 4]
4VYIFE
def ordenar2(L):
if len(L)==0 or len(L)==1:
%TEVXEHS
return L
m=len(L)//2
L1=L[:m]
L2=L[m:]
return intercalar([],ordenar2(L1),ordenar2(L2))
ordenar2([randint(1,15) for _ in range(20)])
4VYIFE
[1, 2, 3, 4, 4, 5, 6, 6, 7, 7, 7, 7, 7, 9, 9, 10, 13, 14, 15, 15]
Compara la eficiencia de los dos métodos generando una lista de 800 enteros aleatorios comprendidos entre −1000 y 1000 y midiendo el tiempo que el ordenador
tarda en ordenarlas.
L=[randint(-10^3,10^3) for _ in range(800)]
'SQTEVEGM¶R TIHMHE
%time
ordenar1(L)
print ''
CPU time: 4.10 s, Wall time: 4.11 s
%time
ordenar2(L)
print ''
CPU time: 0.02 s, Wall time: 0.02 s
Ejercicio 5 (4 puntos) La curva plana
se obtiene de la siguiente parametrización: G : [0, 2π] −→ ℝ2, con
G(t) = (cos(4t) + 4 cos(t), sin(3t)) .
Algunos puntos de la misma, de los que caen en el eje OX, se han marcado en la siguiente figura:
Se pretende aproximar, por el método de Monte Carlo, el área encerrada por la curva
π 2
4 5
G = {G(t) : t ∈ [ , π] ⋃ [ π, π] } :
3 3
3 3
evaluate
(0.5 puntos) Evaluar el siguiente cuadro de comandos, y explicar, brevemente, su contenido.
var('t')
X(t)= cos(4*t) + 4*cos(t)
Y(t)=sin(3*t)
G(t)=(X(t),Y(t))
figura=parametric_plot( G(t), (t, 0, 2*pi), axes=False, figsize=6)
PuntosX=[G(k*pi/3) for k in range(7)]
figura+points(PuntosX)
Se muestra la gráfica de la curva G(t) = (X(t), Y (t)) = (cos(4t) + 4 cos t, sin(3t)), marcando los puntos sobre el eje OX . Hay 4 puntos de la curva en dicho eje,
por los que se pasa para los 7 valores 0, π/3, 2π/3, π, 4π/3, 5π/3 y 2π. Es claro que G(0) = G(2π), G(π/3) = G(5π/3) y G(2π/3) = G(4π/3).
(0.25 puntos)
Definir una función, recorte(a,b), que devuelva la porción de figura dada por los valores de t entre a y b.
¿Cómo utilizarías la función recorte() para obtener cada una de las siguientes porciones de G ? Guarda en variables, cabeza, tronco, ambas imágenes.
def recorte(a,b):
return parametric_plot( G(t), (t, a,b), axes=False, figsize=6)
cabeza=recorte(0,pi/3)+recorte(5*pi/3,2*pi)
cabeza.show(figsize=2)
tronco=recorte(pi/3,2*pi/3)+recorte(4*pi/3,5*pi/3)
tronco.show(figsize=2)
(1 punto) En lo que sigue vamos a construir un rectángulo que contiene la mitad de la curva "tronco" para facilitar la aplicación del método Monte Carlo.
˙ e Y˙ (t), para las
Denotaremos por X(t), Y (t) a las coordenadas x e y, respectivamente, de un punto G(t). Además, usaremos la notación estándar, X(t)
respectivas derivadas respecto de la variable t. Como la curva es simétrica respecto al eje OX, basta calcular el área de la parte contenida en el semiplano
superior. ˙ o Y˙ (t), y a
Calcula las coordenadas cartesianas de los puntos marcados, que corresponden a puntos que anulan a alguna de las funciones derivadas, X(t)
los puntos de corte de la curva con el eje OX.
Indicación: si definimos Dx(t)=X.derivative(t), podemos aplicar a Dx el método .find_root(). En particular Dx.find_root(c,d), nos devuelve una raíz (de las varias
˙
˙ ) = 0. Así, en el punto G(t ), la recta tangente es vertical. Lo análogo, con
que podría haber) en el intervalo [c, d], es decir, un valor, t0 entre c y d tal que X(t
0
0
Dy(t)=Y.derivate(t), se aplica para encontrar puntos con tangente horizontal. Es conveniente asegurarse, al menos gráficamente, de que no hay varias raíces en el
intervalo [c, d], de forma que cada vez que aplicamos .find_root() estemos razonablemente seguros de que la raíz devuelta es la única que hay en el intervalo.
Nota: obsérvese que el punto con tangente vertical está más a la derecha que el extremo de la derecha de la curva.
Dx(t)=X.derivative(t)
t00=Dx.find_root(4*pi/3,5*pi/3)
A=G(t00)
Dy(t)=Y.derivative(t)
t01=Dy.find_root(4*pi/3,5*pi/3)
B=G(t01)
medio=recorte(4*pi/3,5*pi/3)+points([A,B])
(medio).show(figsize=5)
(0.25 puntos) Con los resultados del apartado anterior, determina los vértices del rectángulo R, con lados paralelos a los ejes, más pequeño que contenga la
curva.
a,b=X(4*pi/3),X(t00)
c,d=Y(4*pi/3),Y(t01)
R=line([(a,c),(a,d),(b,d),(b,c),(a,c)])
medio+R
(0.5 puntos) Definir una función, thorizontal(yy), que, aplicada a la segunda coordenada, yy, de un punto dentro del rectángulo R del apartado anterior,
devuelva los dos valores, t1 y t2 (con t1 ≤ t2), tales que Y (ti ) = yy. (Sugerencia: aplicar el método .find_root() a (Y(t)­yy), eligiendo adecuadamente el
intervalo en el que se va a buscar la raíz).
def thorizontal(yy,tt=t01):
t1=(Y(t)-yy).find_root(4*pi/3,tt)
t2=(Y(t)-yy).find_root(tt,5*pi/3)
return t1,t2
t1,t2=thorizontal(random())
medio+line([G(t1),G(t2)],linestyle=':')+points([G(t1),G(t2)])
4VYIFE GSR YR ZEPSV Z¤PMHS
G! ] H! IR IWXI TVSFPIQE
EP E^EV
(0.5 puntos) Definir una función, dentro_tronco(xx,yy), que, aplicada a las coordenadas de un punto dentro del rectángulo R, devuelva True si el punto se
encuentra en el interior de tronco, y False en caso contrario.
Indicación: será muy útil la función thorizontal(), antes definida.
def dentro_tronco(xx,yy):
t1,t2=thorizontal(yy)
return X(t1)<=xx<=X(t2)
(1 punto) Genera N = 104 puntos, (xx, yy), de manera aleatoria en el rectángulo R y cuenta el número de los que caen entre la curva y el eje OX. Dar la
aproximación al área interior de tronco que puedes obtener con los N puntos anteriores (como queremos el área dentro de la curva "tronco" debemos
multiplicar por 2 la que obtenemos usando la parte de la curva contenida en el semiplano).
Sugerencia: Utilizar la función uniforme(), que aplicada a un intervalo [a, b), genera, aleatoriamente, un valor en dicho intervalo:
def uniforme(a,b):
if a>b:
a,b=b,a
return a+(b-a)*random()
xx,yy=uniforme(a,b),uniforme(c,d)
9RE TVYIFE GSR
t1,t2=thorizontal(yy)
VIGYEHVS
print bool(dentro_tronco(xx,yy))
medio+line([G(t1),G(t2)],linestyle=':')+points([G(t1),G(t2),(xx,yy)])
True
%time
N=10^4
dentro=[]
for _ in xrange(N):
xx,yy=uniforme(a,b),uniforme(c,d)
if dentro_tronco(xx,yy):
dentro.append((xx,yy))
medio+points(dentro,pointsize=1)
CPU time: 17.91 s, Wall time: 17.96 s
2*(len(dentro)/N).n()*(b-a)*(d-c)
5.18094483197716
YR TYRXS EP E^EV IR IP
Descargar