Generación de números de n dígitos secuenciados por suma de dígitos individuales (sin recursión)

StackOverflow https://stackoverflow.com/questions/1715304

Pregunta

Busco para generar todos los posibles valores de número de n dígitos, en el siguiente orden, donde la secuencia está determinada por la suma de los dígitos individuales.

Por ejemplo, con n = 3:

111     sum = 3
112     sum = 4
121
211
122     sum = 5
212
221
113
131
311
114     sum = 6
141
411
:::
999     sum = 27

El orden en el grupo suma no es importante.

Cualquier ayuda, idea sería apreciada

¿Fue útil?

Solución

Puede siempre convertir un problema recurrente en un proceso iterativo si mantiene su propia pila de datos importantes - que es si la razón para evitar la repetición es que el idioma no lo soporta

Sin embargo, si el idioma hace lo apoyan, a continuación, soluciones recursivas son mucho más elegante.

La única otra razón que se me ocurre para evitar la repetición es limitada profundidad de la pila. En ese caso una conversión iterativo de una solución recursiva mitigará el problema al no requerir tanto espacio de pila.

Sin embargo, es necesario comprender que la profundidad de la pila para el procesamiento de n números sólo crece en relación con log 10 n. En otras palabras, sólo se obtiene una estructura de pila extra por dígitos (sólo 10 marcos de pila de manejar toda la gama de enteros de 32 bits).

Aparte: en el momento en que llegue a ese punto, estás algoritmo va a tomar tanto tiempo para correr, marcos de pila será el menor de sus problemas: -)

Esto es una solución Python recursiva:

def recur (numdigits,sum,pref="",prefsum=0):
    if numdigits == 0:
        if prefsum == sum:
            print "%s, sum=%d"%(pref,prefsum)
    else:
        for i in range (1,10):
            recur (numdigits-1,sum,"%s%d"%(pref,i),prefsum+i)

def do (n):
    for i in range (1,n*9+1):
        recur (n,i)

do (2)
do (3)

que da salida (para 2 y 3):

11, sum=2          111, sum=3
12, sum=3          112, sum=4
21, sum=3          121, sum=4
13, sum=4          211, sum=4
22, sum=4          113, sum=5
31, sum=4          122, sum=5
14, sum=5          131, sum=5
23, sum=5          212, sum=5
32, sum=5          221, sum=5
41, sum=5          311, sum=5
15, sum=6          114, sum=6
 :    :             :     :
89, sum=17         989, sum=26
98, sum=17         998, sum=26
99, sum=18         999, sum=27

Tenga en cuenta que la solución todavía se podría optimizar un poco - lo dejé en su forma inicial para mostrar cómo puede ser elegante recursividad. Una solución pura iterativo sigue, pero yo prefiero el recursiva.

Ejecutar el programa siguiente y use sort y awk bajo UNIX para obtener el orden deseado. Por ejemplo:

go | sort | awk '{print $2}'

Tenga en cuenta que este utiliza herramientas externas para realizar la ordenación, pero que podría fácilmente especie dentro del código C (permitiendo la memoria).

#include <stdio.h>

int main (void) {
    int i, sum, carry, size;
    int *pDigit;

    // Choose your desired size.

    size = 2;

    // Allocate and initialise digits.

    if ((pDigit = malloc (size * sizeof (int))) == NULL) {
        fprintf (stderr, "No memory\n");
        return 1;
    )

    for (i = 0; i < size; i++)
        pDigit[i] = 1;

    // Loop until overflow.

    carry = 0;
    while (carry != 1) {
        // Work out sum, then output it with number.
        // Line is sssssssssssssssssss ddddd
        //   where sss...sss is the fixed-width sum, zero padded on left (for sort)
        //   and ddd...ddd is the actual number.

        sum = 0;
        for (i = 0; i < size; i++)
            sum += pDigit[i];

        printf ("%020d ", sum);
        for (i = 0; i < size; i++)
            printf ("%d", pDigit[i]);
        printf ("\n");

        // Advance to next number.

        carry = 1;
        for (i = 0; i < size; i++) {
            pDigit[size-i-1] = pDigit[size-i-1] + carry;
            if (pDigit[size-i-1] == 10)
                pDigit[size-i-1] = 1;
            else
                carry = 0;
        }
    }

    return 0;
}

Otros consejos

¿Se puede utilizar std :: next_permutation ?

  

El next_permutation función ()   los intentos de transformar el rango dado   de elementos [start, end) en la siguiente   lexicográfico mayor de permutación   de elementos. Si tiene éxito,   devuelve true, en caso contrario, devuelve   falsa.

     

Si una estricta función ordenadora débil   se proporciona objeto cmp, se utiliza en   lugar de la

Vea esto: anterior para responder

Si no importa qué patrón se utiliza siempre que hay un patrón (no es del todo clara de su cargo si usted tiene un patrón específico en mente), entonces para n = 3, se inicia con 111 y el incremento hasta que se llegar a 999.

Por cierto, el término para lo que está pidiendo no es exactamente "permutaciones".

Puede intentar reducir el problema a dos cubos:

Dos divisiones de cubo son simples: Comenzar con todos menos uno en el cubo A y uno en el cubo B, a continuación, poner uno de A a B hasta A contiene una sola

.

tres divisiones de cubo están a continuación, sólo: empezar con todos dos menos en cubo de A y uno en B y C. Reducir A por uno y recoger todas las dos divisiones de cubo de tres en B y C, se repiten hasta que A contiene sólo una.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top