Areplay:gamma
60/64
Breplay:alfa
62/64
tests superados
gana B por tests superados (62 frente a 60, con las mismas tareas resueltas) (suma de 2 ejecuciones)
2/3
Tareas resueltas
todos los tests en todas las ejecuciones
2/3
4/6
Intentos resueltos
ejecuciones con todos los tests en verde
4/6
60/64(peor)
Tests superados
suma de 2 ejecuciones
(mejor)62/64
7,4 s(mejor)tests: 2,5 s
Tiempo del modelo
menos es mejor · suma de 2 ejecuciones
(peor)20,2 stests: 2,5 s
3.480(mejor)entrada 2.628 · salida 852
Tokens
menos es mejor
(peor)4.208entrada 2.802 · salida 1.406
0,0006 USD(mejor)
Coste estimado
precios ficticios de demostración
(peor)0,0034 USD
Tests superados por tarea
Tabla por tarea
| Tarea | Tests | Tiempo del modelo | Tokens entrada / salida | Coste | ||||
|---|---|---|---|---|---|---|---|---|
| A | B | A | B | A | B | A | B | |
| Convertir un texto en slugfácil | 16/16 | 16/16 | 1,8 s | 5,7 s | 776 / 192 | 824 / 376 | 0,0002 USD | 0,0009 USD |
| Fusionar intervalosmedia | 12/16 | 16/16 | 2,4 s | 6,7 s | 872 / 284 | 936 / 482 | 0,0002 USD | 0,0011 USD |
| Convertir una duración a segundosdifícil | 32/32 | 30/32 | 3,2 s | 7,8 s | 980 / 376 | 1.042 / 548 | 0,0002 USD | 0,0013 USD |
Código y salida de los tests
Convertir un texto en slugslugifyA 16/16 B 16/16
# Convertir un texto en slug
Escribe una función de Python con esta firma exacta:
```python
def slugify(text: str, separator: str = "-") -> str:
```
Debe convertir cualquier texto en un *slug* apto para una URL siguiendo estas reglas:
1. El resultado va en minúsculas.
2. Las letras con tilde, diéresis u otros diacríticos se convierten en su letra base
(`á` → `a`, `ñ` → `n`, `ü` → `u`, `ç` → `c`).
3. Solo se conservan letras ASCII (`a`-`z`) y dígitos (`0`-`9`).
4. Cualquier secuencia de uno o más caracteres no conservados (espacios, signos de
puntuación, barras, guiones, puntos…) se sustituye por **un único** `separator`.
5. El resultado nunca empieza ni termina con el separador.
6. Si no queda ningún carácter conservado, devuelve la cadena vacía `""`.
Ejemplos:
- `slugify("Canción de Añoranza")` → `"cancion-de-anoranza"`
- `slugify("Python 3.12 en 2026")` → `"python-3-12-en-2026"`
- `slugify("Árbol Genealógico", separator="_")` → `"arbol_genealogico"`
A · replay:gamma
Ejecución 1 · 8/8 tests · resuelta · 0,9 s
import re
import unicodedata
def slugify(text: str, separator: str = "-") -> str:
plain = "".join(
char for char in unicodedata.normalize("NFD", text) if not unicodedata.combining(char)
)
return separator.join(re.findall(r"[a-z0-9]+", plain.lower()))
Salida de pytest
........ [100%] 8 passed in 0.06s
Ejecución 2 · 8/8 tests · resuelta · 0,9 s
import re
import unicodedata
def slugify(text: str, separator: str = "-") -> str:
plain = "".join(
char for char in unicodedata.normalize("NFD", text) if not unicodedata.combining(char)
)
return separator.join(re.findall(r"[a-z0-9]+", plain.lower()))
Salida de pytest
........ [100%] 8 passed in 0.06s
B · replay:alfa
Ejecución 1 · 8/8 tests · resuelta · 2,8 s
import re
import unicodedata
def slugify(text: str, separator: str = "-") -> str:
normalized = unicodedata.normalize("NFKD", text)
ascii_text = normalized.encode("ascii", "ignore").decode("ascii").lower()
parts = re.split(r"[^a-z0-9]+", ascii_text)
return separator.join(part for part in parts if part)
Salida de pytest
........ [100%] 8 passed in 0.06s
Ejecución 2 · 8/8 tests · resuelta · 2,8 s
import re
import unicodedata
def slugify(text: str, separator: str = "-") -> str:
normalized = unicodedata.normalize("NFKD", text)
ascii_text = normalized.encode("ascii", "ignore").decode("ascii").lower()
parts = re.split(r"[^a-z0-9]+", ascii_text)
return separator.join(part for part in parts if part)
Salida de pytest
........ [100%] 8 passed in 0.06s
Fusionar intervalosmerge_intervalsA 12/16 B 16/16
# Fusionar intervalos
Escribe una función de Python con esta firma exacta:
```python
def merge_intervals(intervals: list[tuple[int, int]]) -> list[tuple[int, int]]:
```
Recibe una lista de intervalos **cerrados** `(inicio, fin)` de números enteros y devuelve
una lista nueva con los intervalos fusionados:
1. El resultado está ordenado por `inicio` y ningún par de intervalos del resultado se
solapa ni se toca.
2. Dos intervalos que se solapan o que **comparten un extremo** se fusionan:
`(1, 3)` y `(3, 5)` → `(1, 5)`.
3. Dos intervalos consecutivos que no comparten ningún punto **no** se fusionan:
`(1, 2)` y `(3, 4)` siguen separados.
4. La entrada puede venir desordenada y puede contener intervalos de un solo punto,
como `(5, 5)`.
5. La lista de entrada no se modifica.
6. Si algún intervalo tiene `inicio > fin`, lanza `ValueError`.
7. Una lista vacía devuelve `[]`.
8. Cada intervalo del resultado es una tupla `(inicio, fin)`.
Ejemplo:
```python
merge_intervals([(8, 10), (1, 3), (2, 6), (15, 18)])
# [(1, 6), (8, 10), (15, 18)]
```
A · replay:gamma
Ejecución 1 · 6/8 tests · 2 fallan · 1,2 s
def merge_intervals(intervals: list[tuple[int, int]]) -> list[tuple[int, int]]:
merged: list[tuple[int, int]] = []
for start, end in sorted(intervals):
if start > end:
raise ValueError(f"Intervalo no válido: {(start, end)}")
if merged and start < merged[-1][1]:
merged[-1] = (merged[-1][0], max(merged[-1][1], end))
else:
merged.append((start, end))
return merged
Salida de pytest
...F.F.. [100%]
================================== FAILURES ===================================
______________ test_intervalos_que_comparten_extremo_se_fusionan ______________
test_task.py:19: in test_intervalos_que_comparten_extremo_se_fusionan
assert merge_intervals([(3, 5), (1, 3), (5, 7)]) == [(1, 7)]
E assert [(1, 3), (3, 5), (5, 7)] == [(1, 7)]
E
E At index 0 diff: (1, 3) != (1, 7)
E Left contains 2 more items, first extra item: (3, 5)
E Use -v to get more diff
______________________ test_intervalos_de_un_solo_punto _______________________
test_task.py:27: in test_intervalos_de_un_solo_punto
assert merge_intervals([(5, 5), (1, 2), (2, 2), (7, 7)]) == [(1, 2), (5, 5), (7, 7)]
E assert [(1, 2), (2, ...5, 5), (7, 7)] == [(1, 2), (5, 5), (7, 7)]
E
E At index 1 diff: (2, 2) != (5, 5)
E Left contains one more item: (7, 7)
E Use -v to get more diff
=========================== short test summary info ===========================
FAILED test_task.py::test_intervalos_que_comparten_extremo_se_fusionan - asse...
FAILED test_task.py::test_intervalos_de_un_solo_punto - assert [(1, 2), (2, ....
2 failed, 6 passed in 0.16sEjecución 2 · 6/8 tests · 2 fallan · 1,2 s
def merge_intervals(intervals: list[tuple[int, int]]) -> list[tuple[int, int]]:
merged: list[tuple[int, int]] = []
for start, end in sorted(intervals):
if start > end:
raise ValueError(f"Intervalo no válido: {(start, end)}")
if merged and start < merged[-1][1]:
merged[-1] = (merged[-1][0], max(merged[-1][1], end))
else:
merged.append((start, end))
return merged
Salida de pytest
...F.F.. [100%]
================================== FAILURES ===================================
______________ test_intervalos_que_comparten_extremo_se_fusionan ______________
test_task.py:19: in test_intervalos_que_comparten_extremo_se_fusionan
assert merge_intervals([(3, 5), (1, 3), (5, 7)]) == [(1, 7)]
E assert [(1, 3), (3, 5), (5, 7)] == [(1, 7)]
E
E At index 0 diff: (1, 3) != (1, 7)
E Left contains 2 more items, first extra item: (3, 5)
E Use -v to get more diff
______________________ test_intervalos_de_un_solo_punto _______________________
test_task.py:27: in test_intervalos_de_un_solo_punto
assert merge_intervals([(5, 5), (1, 2), (2, 2), (7, 7)]) == [(1, 2), (5, 5), (7, 7)]
E assert [(1, 2), (2, ...5, 5), (7, 7)] == [(1, 2), (5, 5), (7, 7)]
E
E At index 1 diff: (2, 2) != (5, 5)
E Left contains one more item: (7, 7)
E Use -v to get more diff
=========================== short test summary info ===========================
FAILED test_task.py::test_intervalos_que_comparten_extremo_se_fusionan - asse...
FAILED test_task.py::test_intervalos_de_un_solo_punto - assert [(1, 2), (2, ....
2 failed, 6 passed in 0.15sB · replay:alfa
Ejecución 1 · 8/8 tests · resuelta · 3,4 s
def merge_intervals(intervals: list[tuple[int, int]]) -> list[tuple[int, int]]:
for start, end in intervals:
if start > end:
raise ValueError(f"Intervalo inválido: ({start}, {end})")
merged: list[tuple[int, int]] = []
for start, end in sorted(intervals):
if merged and start <= merged[-1][1]:
last_start, last_end = merged[-1]
merged[-1] = (last_start, max(last_end, end))
else:
merged.append((start, end))
return merged
Salida de pytest
........ [100%] 8 passed in 0.06s
Ejecución 2 · 8/8 tests · resuelta · 3,4 s
def merge_intervals(intervals: list[tuple[int, int]]) -> list[tuple[int, int]]:
for start, end in intervals:
if start > end:
raise ValueError(f"Intervalo inválido: ({start}, {end})")
merged: list[tuple[int, int]] = []
for start, end in sorted(intervals):
if merged and start <= merged[-1][1]:
last_start, last_end = merged[-1]
merged[-1] = (last_start, max(last_end, end))
else:
merged.append((start, end))
return merged
Salida de pytest
........ [100%] 8 passed in 0.05s
Convertir una duración a segundosparse_durationA 32/32 B 30/32
# Convertir una duración a segundos
Escribe una función de Python con esta firma exacta:
```python
def parse_duration(text: str) -> int:
```
Recibe una duración escrita por una persona, como `"1h 30m 15s"`, y devuelve el total en
segundos (`5415` en ese ejemplo).
Formato válido:
1. La duración está formada por uno o más **componentes** `<entero><unidad>`, sin espacio
entre el número y la unidad.
2. Las unidades son `d` (días), `h` (horas), `m` (minutos) y `s` (segundos), en
minúsculas o mayúsculas.
3. Los componentes pueden ir juntos (`"1h30m"`) o separados por espacios, y se admiten
espacios al principio y al final.
4. Cada unidad aparece **como mucho una vez** y siempre en orden descendente:
`d`, luego `h`, luego `m`, luego `s`. Se pueden omitir unidades (`"2d 5s"` es válido).
5. El número es un entero sin signo; `"0s"` es válido y vale `0`.
Cualquier otra cosa debe lanzar `ValueError`, por ejemplo: cadena vacía o solo espacios,
un número sin unidad (`"10"`), una unidad desconocida (`"5x"`), una unidad repetida
(`"1h 2h"`), unidades fuera de orden (`"30m 1h"`), signos (`"-5m"`), decimales (`"1.5h"`)
o texto sobrante (`"1h y 5m"`).
A · replay:gamma
Ejecución 1 · 16/16 tests · resuelta · 1,6 s
import re
_PATTERN = re.compile(
r"\s*(?:(\d+)d)?(?:\s*(\d+)h)?(?:\s*(\d+)m)?(?:\s*(\d+)s)?\s*", re.IGNORECASE
)
def parse_duration(text: str) -> int:
match = _PATTERN.fullmatch(text)
if match is None or all(group is None for group in match.groups()):
raise ValueError(f"Duración no válida: {text!r}")
days, hours, minutes, seconds = (int(group or 0) for group in match.groups())
return ((days * 24 + hours) * 60 + minutes) * 60 + seconds
Salida de pytest
................ [100%] 16 passed in 0.06s
Ejecución 2 · 16/16 tests · resuelta · 1,6 s
import re
_PATTERN = re.compile(
r"\s*(?:(\d+)d)?(?:\s*(\d+)h)?(?:\s*(\d+)m)?(?:\s*(\d+)s)?\s*", re.IGNORECASE
)
def parse_duration(text: str) -> int:
match = _PATTERN.fullmatch(text)
if match is None or all(group is None for group in match.groups()):
raise ValueError(f"Duración no válida: {text!r}")
days, hours, minutes, seconds = (int(group or 0) for group in match.groups())
return ((days * 24 + hours) * 60 + minutes) * 60 + seconds
Salida de pytest
................ [100%] 16 passed in 0.06s
B · replay:alfa
Ejecución 1 · 15/16 tests · 1 falla · 3,9 s
import re
_SECONDS = {"d": 86_400, "h": 3_600, "m": 60, "s": 1}
_FORMAT = re.compile(r"(?:\s*\d+[dhms])+\s*", re.IGNORECASE)
_COMPONENT = re.compile(r"(\d+)([dhms])", re.IGNORECASE)
def parse_duration(text: str) -> int:
if not _FORMAT.fullmatch(text):
raise ValueError(f"Duración no válida: {text!r}")
total = 0
seen: set[str] = set()
for number, unit in _COMPONENT.findall(text):
unit = unit.lower()
if unit in seen:
raise ValueError(f"Unidad repetida: {unit!r}")
seen.add(unit)
total += int(number) * _SECONDS[unit]
return total
Salida de pytest
...............F [100%]
================================== FAILURES ===================================
_______________ test_unidades_fuera_de_orden_lanzan_valueerror ________________
test_task.py:41: in test_unidades_fuera_de_orden_lanzan_valueerror
with pytest.raises(ValueError):
^^^^^^^^^^^^^^^^^^^^^^^^^
E Failed: DID NOT RAISE ValueError
=========================== short test summary info ===========================
FAILED test_task.py::test_unidades_fuera_de_orden_lanzan_valueerror - Failed:...
1 failed, 15 passed in 0.15sEjecución 2 · 15/16 tests · 1 falla · 3,9 s
import re
_SECONDS = {"d": 86_400, "h": 3_600, "m": 60, "s": 1}
_FORMAT = re.compile(r"(?:\s*\d+[dhms])+\s*", re.IGNORECASE)
_COMPONENT = re.compile(r"(\d+)([dhms])", re.IGNORECASE)
def parse_duration(text: str) -> int:
if not _FORMAT.fullmatch(text):
raise ValueError(f"Duración no válida: {text!r}")
total = 0
seen: set[str] = set()
for number, unit in _COMPONENT.findall(text):
unit = unit.lower()
if unit in seen:
raise ValueError(f"Unidad repetida: {unit!r}")
seen.add(unit)
total += int(number) * _SECONDS[unit]
return total
Salida de pytest
...............F [100%]
================================== FAILURES ===================================
_______________ test_unidades_fuera_de_orden_lanzan_valueerror ________________
test_task.py:41: in test_unidades_fuera_de_orden_lanzan_valueerror
with pytest.raises(ValueError):
^^^^^^^^^^^^^^^^^^^^^^^^^
E Failed: DID NOT RAISE ValueError
=========================== short test summary info ===========================
FAILED test_task.py::test_unidades_fuera_de_orden_lanzan_valueerror - Failed:...
1 failed, 15 passed in 0.15s