█████████ ████ ███░░░░░███ ░░███ ███ ░░░ ██████ ███████ ██████ ██████ ░███ ███░░███ ███░░███ ███░░███ ███░░███ ░███ ░███ ░███░███ ░███ ░███████ ░███ ░███ ░░███ ███░███ ░███░███ ░███ ░███░░░ ░███ ░███ ░░█████████ ░░██████ ░░████████░░██████ ░░██████ ░░░░░░░░░ ░░░░░░ ░░░░░░░░ ░░░░░░ ░░░░░░

Envío 911

Problema 0xe1 - Cuadrado mágico

  • Autor: abatesins
  • Fecha: 2020-09-29 08:20:41 UTC (Hace alrededor de 4 años)
Caso # Resultado Tiempo Memoria
#1
Correcto
0.025 s 3 KBi
#2
Correcto
0.027 s 3 KBi
#3
Correcto
0.028 s 3 KBi
#4
Correcto
0.028 s 3 KBi
#5
Correcto
0.025 s 3 KBi
#6
Correcto
0.026 s 3 KBi
#7
Correcto
0.024 s 3 KBi
#8
Correcto
0.028 s 3 KBi
#9
Correcto
0.026 s 3 KBi
#10
Correcto
0.023 s 3 KBi
#11
Correcto
0.025 s 4 KBi
#12
Correcto
0.026 s 3 KBi
#13
Correcto
0.027 s 5 KBi
#14
Correcto
0.026 s 3 KBi
#15
Correcto
0.03 s 3 KBi
#16
Correcto
0.035 s 3 KBi
#17
Correcto
0.032 s 3 KBi
#18
Correcto
0.034 s 3 KBi
#19
Correcto
0.033 s 3 KBi
#20
Correcto
0.039 s 3 KBi
Puntos totales: 100 / 100

Código

# Ya que Andrés pasó por mi código explicando
# la solución en el último stream, aquí está 
# una versión más comentada del mismo algoritmo

# 1. Leyendo la entrada:
mat_size = int(input())
# 1.1. Para leer la matriz hay que
# (1) leer cada línea de la matriz y
# (2) para cada caracter en una línea, 
# convertir este a entero. Aquí aprovechamos 
# dos formas de iterar sobre listas: el 
# list-comprehension y la función map (como 
# mencionaba Andrés, esta línea tiene 
# complejidad N**2)  
mat = [list(map(int, input().split())) for _ 
in range(mat_size)]

# 2. Estrategia: pasar una vez por cada 
# elemento de la matriz y establecer a qué 
# fila pertenece, a qué columna pertenece y 
# si pertenece a alguna de las 2 diagonales.
# Todas esas consultas pueden hacerse con los 
# índices de la matriz.

# 2.1. Los resultados de cada consulta van a 
# acumularse, uno por cada fila, columna y 
# diagonal. Una forma simple de modelar estos 
# valores es con un arreglo donde los 
# primeros 'mat_size' elementos (llamado N en 
# la definición del problema) corresponden a 
# la suma de las filas, los siguientes 
# 'mat_size' elementos, corresponden a la 
# suma de las columnas y los últimos dos, a 
# la de las 2 diagonales.
accums = [0] * (mat_size * 2 + 2)

# 2.2. Recorrer la matriz usando un doble 
# bucle normal
for i, row in enumerate(mat):
  for j, elem in enumerate(row):
    # Acumula valor de la fila
    accums[i] += elem
    # Acumula valor de la columna
    accums[mat_size + j] += elem
    # Revisa si pertenece a la diagonal que
    # va de izquiera-derecha, arriba-abajo
    if i == j:
      accums[-1] += elem
    # Revisa si pertenece a la diagonal que
    # va de izquierda-derecha, abajo-arriba.
    # Es un error poner este IF como una
    # cláusula ELSE del primer IF porque,
    # cuando N es impar, el elemento del
    # medio en la matriz cuenta para las dos 
    # diagonales
    if mat_size - 1 - j == i:
      accums[-2] += elem

# 3. Verificar que todos los acumuladores 
# tienen el mismo valor.
# 3.1. Valor de referencia
x0 = accums[0]
# 3.2. De nuevo usando map para hacer la 
# línea más compacta. El primer argumento del 
# 'map' es una versión funcional de un IF (de 
# ahí sale la expresión 'lambda' y retorna un 
# booleano). La función 'all' pasa de nuevo 
# por todos los valores booleanos y retorna 
# True si todos los elementos en la lista son 
# True (y False si al menos uno de ellos no 
# lo es). La complejidad es lineal respecto 
# al tamaño de 'accums', es decir O(2N+2+N) = 
# O(3N+2) = O(N)
is_magic = all(map(lambda x: x == x0, accums))

# 4. Salida: Forma comprimida para imprimir 
# 'Yes' o 'No'. Tampoco suelo escribir así 
# (es más a manera de ejercicio). De hecho, 
# esto hace el código más lento que el IF 
# normal.
print(['No', 'Yes'][int(is_magic)])