DS 2 — Correction : modélisation de la circulation¶
MP, année scolaire 2021-2022 — corrigé (informatique commune, Python et SQL).
Sujet
Seule la correction est disponible : l'énoncé n'est pas reproduit ici. Sujet d'après le concours Mines-Ponts 2016, informatique commune (modélisation de la circulation automobile : files de voitures, croisements, espace des configurations, base de données de croisements et de voies).
Partie I¶
Question 1.
Corrigé
On peut faire une liste [v0,...,vn-1] où vi vaut True quand une
voiture est présente à l'indice \(i\) et False sinon.
Question 2.
Corrigé
A = [ True, False, True, True, False,
False, False, False, False, False, True ]
Question 3.
Corrigé
def occupe(L, i):
return L[i]
Question 4.
Corrigé
Chacune des \(n\) cases peut prendre deux valeurs, il y en a donc \(2^n\).
Question 5.
Corrigé
Question mal posée, on peut répondre légitimement avec ==…
def egal(L1, L2):
if len(L1) != len(L2):
return False
for i in range(len(L1)):
if L1[i] != L2[i]:
return False
return True
Question 6.
Corrigé
Complexité linéaire en temps en pire cas, ce qui correspond au fait d'avoir des listes égales.
Question 7.
Corrigé
Le type de retour est un booléen donc de type bool. Note : cette question
est étrange…
Partie II¶
Question 8.
Corrigé
On a vu que avancer(A,False) renvoie
[False,True,False,True, True, False, False, False, False, False, False]
si on appelle sur ce résultat avancer avec True on obtient :
[True, False,True,False,True, True, False, False, False, False, False]
Question 9.
Corrigé
On a plusieurs choix ici, si on considère que la fonction avancer
est définie, on peut l'utiliser directement. Sinon, on peut le faire à la
main.
def avancer_fin(L, m):
La = [ False ] * len(L)
for i in range(m):
La[i] = L[i]
for i in range(m+1, len(L)):
La[i] = L[i-1]
return La
Question 10.
Corrigé
def avancer_debut(L, b, m):
La = [ False ] * len(L)
for i in range(m+1, len(L)):
La[i] = L[i]
for i in range(1, m+1):
La[i] = L[i-1]
La[0] = b
return La
Question 11.
Corrigé
Ici, il faut procéder en reculant à partir de la position m.
def avancer_debut_bloque(L, b, m):
# on cherche la première case libre à gauche de m (strictement)
i = m-1
while i > 0 and L[i]:
i = i-1
return avancer_debut(L, b, i)
Partie III¶
Question 12.
Corrigé
def avancer_files(L1, b1, L2, b2):
p = len(L1)//2
La1 = avancer_file(L1, b1)
if La1[p]:
La2 = avancer_fin(avancer_debut_bloque(L2, b2, p), p)
else:
La2 = avancer_file(L2, b2)
return [La1, La2]
Question 13.
Corrigé
L'appel renvoie
[ [ False, False, True, False, True ], [ False, True, False, True, False ] ]
Partie IV¶
Question 14.
Corrigé
Il suffit que toutes les cases de L1 soient occupées.
Question 15.
Corrigé
On va y passer en deux temps, d'abord toutes les voitures de L1
passent à droite, ensuite les voitures de L2 peuvent descendre et au
passage on rajoute des voitures à gauche de L1.
On a donc 5 étapes pour libérer le croisement puis comme sur la dernière
étape on a commencé à faire descendre les voitures de L2 on a juste
besoin de 4 étapes ensuite, donc 9 étapes en tout.
Question 16.
Corrigé
La configuration 4c n'a pas d'antécédent car il faudrait avoir une
voiture de L1 et une voiture de L2 sur la position centrale.
Partie V¶
Question 17.
Corrigé
def elim_double(L):
Le = []
for x in L:
if Le == [] or x != Le[-1]:
Le.append(x)
return Le
Question 18.
Corrigé
[ 1, 2, 3, 5 ]
Question 19.
Corrigé
Non car elle se contente de supprimer les doublons côte à côte.
Question 20.
Corrigé
rechercherenvoie unbool;successeurrenvoie unelistde couples de configurations[L1,L2];espacea le même type que le retour desuccesseur;butest une configuration, donc une liste[L1,L2]où lesLisont deslistdeboolde même longueur impaire.
Question 21.
Corrigé
La première recherche correspond à une recherche linéaire et la seconde à une recherche dichotomique, donc en temps logarithmique. La seconde est préférable.
Cependant, remarquons que dans la mesure où on effectue un tri à chaque étape en \(O(n \log_2 n)\), la question est peu pertinente…
Question 22.
Corrigé
def versEntier(L):
p = 1
s = 0
for b in reversed(L):
if b:
s = s + p
p = p * 2
return s
Question 23.
Corrigé
Il faut une taille correspondant au nombre de chiffres de \(n\) en binaire, soit \(\lfloor \log_2 n \rfloor + 1\).
La condition est \(n > 0\).
Question 24.
Corrigé
La fonction termine car elle continue tant qu'elle rajoute des configurations et que le nombre de configurations est borné par \(2^{2n-1}\).
Question 25.
Corrigé
On rajoute à chaque fois l'ensemble des successeurs aux précédents. Donc le
test de présence du but ne va en fait porter que sur ces nouveaux
successeurs. Il suffit de compter le nombre d'itérations dans la boucle
while.
def recherche(but, init):
espace = [ init ]
stop = egal(but, init)
if stop:
return 0
nb_etapes = 0
while not stop:
ancien = espace
espace = espace + successeur(espace)
espace.sort()
espace = elim_double(espace)
stop = egal(ancien, espace)
nb_etapes += 1
if but in espace:
return nb_etapes
return -1
Partie VI¶
Question 26.
Corrigé
SELECT id_croisement_fin FROM voie
WHERE id_croisement_debut = c;
Question 27.
Corrigé
SELECT longitude, latitude
FROM croisement JOIN voie ON croisement.id = id_croisement_fin
WHERE id_croisement_debut = c;
Question 28.
Corrigé
Cette requête renvoie les croisements accessibles en suivant deux voies à partir du croisement \(c\).