Aller au contenu

E04 - Intersection⚓︎

Le problème

Intersection

Proposition 1⚓︎

🐍 Script Python
def calcul(nombre_heure1, nombre_heure2, duree_commune) -> int :


    # cas de figure 0 : 
    if nombre_heure1[0] >= nombre_heure2[1] :
        return 0
    if nombre_heure2[0] >= nombre_heure1[1] :
        return 0

    # Premier cas de figure 1 :

    if nombre_heure1[0] > nombre_heure2[0] :

        #1a

        if nombre_heure1[1] > nombre_heure2[1]:
            duree_commune = nombre_heure1[0] - nombre_heure2[1]
            return duree_commune

        #1b 

        duree_commune = nombre_heure1[1] - nombre_heure2[1]
        return duree_commune

    # Deuxième cas de figure 2 :

    if nombre_heure1[0] < nombre_heure2[0] :

        #2a    

        if nombre_heure1[1] < nombre_heure2[1]:
            duree_commune = nombre_heure2[0] - nombre_heure1[1]
            return duree_commune
        #2b

        duree_commune = nombre_heure2[0] - nombre_heure2[1]
        return duree_commune

    # Troisème cas de figure 3 :

    if nombre_heure1[0] == nombre_heure2[0]:

        #3a

        if nombre_heure1[1] > nombre_heure2[1]: 
            duree_commune = nombre_heure1[0] - nombre_heure2[1]
            return duree_commune

        #3b

        duree_commune = nombre_heure1[0] - nombre_heure1[1]
        return duree_commune


nombre_heure1 = list(map(int, input().split()))
nombre_heure2 = list(map(int, input().split()))
duree_commune = 0 

print(abs(calcul(nombre_heure1, nombre_heure2, duree_commune)))

# abs() va renvoyer la valeur absolue
  • Mauvais passage de paramètres.

  • Il y a trop de cas de figures... On peut largement simplifier.

  • On attend des noms de variable bien plus explicites que calcul !

  • On attend un doctest...

  • abs aurait du être utilisé dans la fonction, pas ensuite.

Proposition 2⚓︎

🐍 Script Python
def inter(pa,pb):
    if pa[0] >= pb[0] and pa[0] < pb[1]:
        if pa[1]>pb[1]:
            return pb[1]-pa[0]
        else:
            return pa[1]-pa[0]
    elif pb[0]>= pa[0] and pb[0]<pa[1]:
        if pb[1]>pa[1]:
            return pa[1]-pb[0]
        else:
            return pb[1]-pb[0]
    else:
        return 0

pera = list(map(int,input(). strip(). split()))[:2]
perb = list(map(int,input(). strip(). split()))[:2]
per = inter(pera,perb)
print(per)

import doctest
doctest.testmod()
  • Noms de variables très mal choisis...
  • PEP-8 à mieux respecter !
  • On attend un doctest pour chaque problème.

Proposition 3⚓︎

🐍 Script Python
def intervalle(x_min: int, x_max: int, y_min: int, y_max: int) -> int:
    """
    Renvoie la durée en commun entre les deux périodes.

    >>> intervalle(-47686716, -38491014, -48528973, -42411585)
    5275131

    >>> intervalle(-47698252, -45630884, -45440315, -37180150)
    0

    """

    # se touche pas

    if x_max <= y_min or y_max <= x_min:
        return 0

    # englobe tout

    elif y_min >= x_min and y_max <= x_max:
        return abs(y_max - y_min)

    elif x_min >= y_min and x_max <= y_max:
        return abs(x_max - x_min)

    # intervalle

    elif y_min < x_min < y_max:
        return abs(y_max - x_min)

    elif y_min < x_max < y_max:
        return abs(x_max - y_min)

# Test

import doctest
doctest.testmod()

# Entrée

x_min, x_max = input().split()
x_min = int(x_min)
x_max = int(x_max)

y_min, y_max = input().split()
y_min = int(y_min)
y_max = int(y_max)

# Sortie

print(intervalle(x_min, x_max, y_min, y_max))
  • Le nom intervalle est mal choisi.

  • x et y sont mal choisis, cela fait penser à des coordonnées cartésiennes en 2D ; ce n'est pas le cas ici.

  • Tu pouvais encore factoriser le code.

Proposition 4⚓︎

🐍 Script Python
def intersection(periode_a, periode_b):
    """
    Calcule et Renvoie le nombre d'heure en commun
    """
    if periode_a[0] == periode_a[1] or periode_b[0] == periode_b[1] \
            or periode_a[1] == periode_b[0] or periode_b[1] == periode_a[0]:
        return 1
    if periode_a[0] < periode_b[0] and periode_a[1] > periode_b[1]:
        return (periode_b[1] - periode_b[0])
    if periode_a[0] > periode_b[0] and periode_a[1] < periode_b[1]:
        return (periode_a[1] - periode_a[0])
    if periode_a[1] < periode_b[0] or periode_b[1] < periode_a[0]:
        return 0
    if periode_a[1] > periode_b[0] and periode_a[1] < periode_b[1]:
        return (periode_a[1]-periode_b[0])
    if periode_b[1] > periode_a[0] and periode_b[1] < periode_a[1]:
        return (periode_b[1]-periode_a[0])

#Entrée
periode_a = list(map(int, input().split()))
periode_b = list(map(int, input().split()))
if periode_a[1] > 0:
    periode_a[1] -= 1
if periode_b[1] > 0:
    periode_b[1] -= 1

#Sortie
print(intersection(periode_a, periode_b))
  • Il y a trop de cas, tu pouvais factoriser.

  • Pourquoi ce décalage de - 1 juste après la lecture de l'entrée ???

  • Les [0] et [1] sont peu lisibles ; il vaut mieux extraire et utiliser un nom explicite.

Proposition 5⚓︎

🐍 Script Python
def intersection():
    """Renvoie la durée en commun entre les deux périodes

    >>> -47686716 -38491014
    >>> -48528973 -42411585
    5275131

    """

    if (période_2[1] < période_1[0]) or (période_1[1] < période_2[0]) :

        return 0

    elif période_1[0] < période_2[0] and période_1[1] < période_2[1] :

        return abs(période_2[0] - période_1[1])

    elif période_1[0] < période_2[0] and période_1[1] > période_2[1] :

        return abs(période_2[0] - période_2[1])

    elif période_1[0] > période_2[0] and période_1[1] < période_2[1] :

        return abs(période_1[0] - période_1[1])

    elif période_1[0] > période_2[0] and période_1[1] > période_2[1]:

        return abs(période_1[0] - période_2[1])



période_1 = list(map(int, input().split()))
période_2 = list(map(int, input().split()))
print(intersection())
  • Revoir le principe du doctest.

  • Il y a trop de cas.

  • Travailler avec les indices 0 et 1 est pénible, il vaut mieux extraire dans debut_1, ... , fin_2 ; par exemple.

  • Il faut passer les paramètres à la fonction.

Corrigé du professeur⚓︎

🐍 Script Python
"""
author: Franck CHAMBON
problem: https://prologin.org/train/2004/semifinal/carte_au_tresor
"""

def intersection(debut_1: int, fin_1: int, debut_2: int, fin_2: int) -> int:
    """Renvoie la durée de l'intersection de
    [debut_1 ; fin_1] avec [debut_2 ; fin_2]

    >>> intersection(-47686716, -38491014, -48528973, -42411585)
    5275131

    >>> intersection(-47698252, -45630884, -45440315, -37180150)
    0

    """
    debut = max(debut_1, debut_2)
    fin = min(fin_1, fin_2)
    if debut < fin:
        return fin - debut
    else:
        return 0

# Tests
import doctest
doctest.testmod()

# Entrée
debut_1, fin_1 = map(int, input().split())
debut_2, fin_2 = map(int, input().split())

# Sortie
print(intersection(debut_1, fin_1, debut_2, fin_2))

Code minimal

On peut encore réduire (ce serait mal) le code de la fonction avec

🐍 Script Python
def intersection(debut_1, fin_1, debut_2, fin_2):
    debut = max(debut_1, debut_2)
    fin = min(fin_1, fin_2)
    return max(0, fin - debut)

One-liner

Et en une seule ligne, mais ce serait très peu lisible. INTERDIT !!!

🐍 Script Python
def intersection(debut_1, fin_1, debut_2, fin_2):
    return max(0, min(fin_1, fin_2) - max(debut_1, debut_2))