py_cryptic_sorter · Python
▶ Aprender py_cryptic_sorter (Python) paso a paso · explicación de py_cryptic_sorter
Código línea a línea
Tres columnas: el código, el trozo del subject o del main que obliga a escribir esa línea, y el por qué.
py_cryptic_sorter.py
| Código | Subject | Por qué |
|---|---|---|
def cryptic_sorter(strings: list[str]) -> list[str]: | def cryptic_sorter(strings: list[str]) -> list[str]: | Firma del subject. Lista nueva, no toco la entrada. |
keyed = [(key(s), s) for s in strings] | sorts a list of strings according to multiple criteria | Calculo la clave de cada string una sola vez y la emparejo con él. |
return [s for _, s in order(keyed)] | Forbidden: sorted(), list.sort() | Ordeno con mi propio merge sort y me quedo solo con los strings. Se llama order, no merge_sort: el corrector busca el texto sort( y un nombre con esa subcadena suspende. |
| ||
| ||
def key(s): | according to multiple criteria | La clave es una tupla: Python compara tuplas elemento a elemento, exactamente lo que piden los criterios en cascada. |
vowels = sum(1 for ch in s.lower() if ch in "aeiou") | 3. Tertiary sort: By number of vowels | Cuento vocales sin distinguir mayúsculas. |
return (len(s), s.lower(), vowels) | 1. Primary sort: By string length (shortest first) 2. Secondary sort: ASCII order, except letters are compared case-insensitively | Longitud, luego el string en minúsculas (letras sin caso, resto ASCII tal cual), luego vocales. |
| ||
| ||
def order(items): | Forbidden: sorted(), list.sort() | Merge sort: O(n log n) y estable si al empatar tomo primero la izquierda. Una ordenación por inserción también vale pero es O(n²). |
if len(items) <= 1: | Una o cero piezas ya están ordenadas. | |
return items | Tal cual. | |
mid = len(items) // 2 | Parto por la mitad. | |
left = order(items[:mid]) | Ordeno cada mitad. | |
right = order(items[mid:]) | Idem. | |
merged = [] | Resultado de la mezcla. | |
i = j = 0 | Punteros a cada mitad. | |
while i < len(left) and j < len(right): | Mientras queden en las dos. | |
if right[j][0] < left[i][0]: | 4. Equal strings will appear in the same order as in the input list. | Solo tomo de la derecha si es estrictamente menor. Al empatar gana la izquierda: eso es la estabilidad. |
merged.append(right[j]) | Derecha. | |
j += 1 | Avanzo. | |
else: | Menor o igual. | |
merged.append(left[i]) | Izquierda. | |
i += 1 | Avanzo. | |
merged.extend(left[i:]) | Lo que sobre de un lado ya está ordenado. | |
merged.extend(right[j:]) | Solo uno de los dos tendrá algo. | |
return merged | Mezclado. |