1votos

Matriz Caracol en C#

por josejuan hace 2 años

Se pueden obtener una función explícita que mapea la enumeración caracol (1, 2, 3, ...) con las coordenadas que ocupan. Así, es posible rellenar el caracol como sea preciso (eg. sólo celdas impares, con cierta forma, etc...) sin calcular el resto del caracol.

Un clasico problema de programacion, en arreglos bidimensionales.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Para rellenar el caracol en una matriz NxN, bastaría, con coste O(N^2) 
Enumerable.Range(0, n).Select(k => coords(k+1, N)); 
 
 
 
 
// Usando las funciones: 
 
// Tomandos los cuadros del más exterior al interior x = 1, 2, 3, ... su perímetro 
Func<int, int, int> perimeter = ( x, n ) => 4 * ( n - 2 * x + 1 ); 
 
// Dada las coordenadas de la diagonal principal (1, 1), (2, 2), ... devuelve el número que contiene 
Func<int, int, int> diagonalPos = ( x, n ) => -4 * x * x + ( 4 * n + 8 ) * x - 4 * n - 3; 
 
// Dado un número, indica en qué cuadro está 
Func<int, int, int> inSquare = ( z, n ) => (int) Math.Floor(n * 0.5 - 0.5 * Math.Sqrt(n * n - z + 1.0) + 1.0); 
 
Func<int, int, Point> coords = ( z, n ) => { 
    var s = inSquare(z, n); 
    var l = perimeter(s, n) / 4; // lado del subcuadro -1 
    var l2 = l + l; 
    var l3 = l2 + l; 
    var d = diagonalPos(s, n); 
    if( z <= d + l ) 
        return new Point(s + z - d, s); 
    if( z <= d + l2 ) 
        return new Point(s + l, s + z - d - l); 
    if( z <= d + l3 ) 
        return new Point(s + d + l3 - z, s + l); 
    return new Point(s, s + d + l2 + l2 - z); 
}; 
1 comentario
0votos

Escrito por CarlosHGamboa hace 2 años

Te aplaudo, una solución muy elegante.

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.