La respuesta fácil:
Si sus números tienen un mínimo de cero y un valor máximo de N, puede verlos como dígitos de un número base N + 1 y luego convertirlo a decimal.
public static int Pack (IEnumerable números, int max)
{
int retval = 0;
foreach (int número en números)
{
retval + = número;
retval * = max + 1;
}
retorno retval;
}
- Si alguien pudiera factorizar rápidamente los números primos, ¿cuáles serían las consecuencias?
- Necesito saber cómo describir el cálculo del PageRank de punto fijo. ¿Alguien sabe algo al respecto?
- ¿Cuál es el mejor libro para aprender algoritmos?
- Cómo escribir algoritmo para asignaturas requeridas
- ¿Cuál es la manera de mejorar en la resolución de preguntas recurrentes y complicadas de estructura de datos / algoritmo?
Para recuperar los números, conviértalo de nuevo a un número en base max + 1, y luego lea los dígitos.
public static IEnumerable Unpack (int número, int max)
{
while (número> 0)
{
número de retorno de rendimiento% (max + 1);
número / = max + 1;
}
}
Si sus números no tienen un valor máximo, entonces esto se vuelve mucho más complicado, pero aún se puede hacer. Consideremos solo dos números, A y B, que son cualquier cosa no negativa.
La idea es codificar A y B de la siguiente manera:
si
0 1 2 3 4
+ ———
0 | 0 2 5 9 14
1 | 1 4 8 13
A 2 | 3 7 12
3 | 6 11
4 | 10
Observe que las salidas están dispuestas en “capas” diagonales, por lo que no tenemos que lidiar con filas finitas. El “número de capa” es simplemente la suma de A y B. El primer valor en esta “capa” es el enésimo número triangular:
[matemáticas] inicio = \ frac {capa (capa + 1)} {2} [/ matemáticas]
A partir de aquí, podemos agregar B para obtener la respuesta final.
Paquete estático público int (int a, int b)
{
int suma = a + b;
int inicio = suma * (suma + 1) / 2;
retorno inicio + b;
}
Ahora hagamos tres números. Aquí, necesitamos un gráfico tridimensional, con “capas” bidimensionales. La idea es la misma, pero con una función diferente para obtener el número de inicio de la capa:
Paquete int estático público (int a, int b, int c)
{
int suma = a + b + c;
int inicio = suma * (suma + 1) * (suma + 2) / 6;
inicio de retorno + paquete (b, c);
}
Podemos trabajar la idea general en una función recursiva para N números;
public static int Pack (lista IEnumerable )
{
int cuenta = list.Count ();
si (cuenta == 0)
{
devuelve 0;
}
más
{
int sum = list.Sum ();
int inicio = 1;
para (int i = 0; i <cuenta; i ++)
{
inicio * = suma + i;
inicio / = i + 1;
}
return start + Pack (Cola (lista));
}
}
Sin embargo, deshacer esto es un oso. Para dos números, necesitamos recuperar en qué capa estamos encontrando la “raíz triangular” del número.
public static IEnumerable Unpack2 (int número)
{
// encuentra la “raíz triangular” del número.
int sum = (int) ((Math.Sqrt (1 + 8 * número) – 1) / 2);
int inicio = suma * (suma + 1) / 2;
int b = número – inicio;
int a = sum-b;
rendimiento de rendimiento a;
rendimiento de rendimiento b;
}
Hacer esto para el caso general es mucho más difícil, ya que requiere que encontremos el inverso de los números triangulares generalizados. Esto se deja como un ejercicio para el alumno.
public static IEnumerable Unpack (int number, int count)
{
si (cuenta == 0)
{
ruptura de rendimiento;
}
más
{
int sum = FindLayer (número, recuento); // ¡Buena suerte!
int inicio = 1;
para (int i = 0; i <cuenta; i ++)
{
inicio * = suma + i;
inicio / = i + 1;
}
int last = number = start;
foreach (int i en Unpack (número – último, cuenta – 1))
{
rendimiento de rendimiento i;
}
rendimiento de retorno último;
}
}