Convirtiendo Números a un "No es un sistema de valor posicional"

11

Vamos a crear un sistema de números donde el dígito más grande en el enésimo valor posicional (contando de derecha a izquierda) de una longitud de número m siempre es igual a m - n + 1. Para dar un ejemplo, el número más grande de 5 dígitos expresable en este sistema está escrito 12345. Además del número de dígitos disponibles para ser usados ​​en un lugar particular que está restringido, todos los demás incrementos son estándar. Es decir, cuando un dígito debe superar su límite de dígitos, agregamos uno al siguiente dígito.

Así es como se representaría el conteo en este sistema:

1; 10; 11; 12; 100; 101; 102; 103; 110; 111; 112; 113; 120; 121; 122; 123; 1000; 1001 ...

Su tarea es escribir una función que tome un número base 10 estándar y lo convierta a mi sistema de numeración.

El código más corto es preferible. Bonne Chance!

** Si necesita dígitos después del 9 (debería), puede optar por usar letras, o puede devolver un número de 2 dígitos como elemento de una lista.

Casos de prueba

10 -> 111
20 -> 1003
30 -> 1023
50 -> 1123
100 -> 10035
23116 -> 1234567
21977356 -> 123456789A

El último caso puede ser increíblemente lento para ejecutarse dependiendo de cómo lo implementó. No necesita ejecutarlo si tarda demasiado o usa demasiada memoria. Sin embargo, tenga en cuenta que existen formas de ejecutarlo rápidamente y con poca memoria.

Ando Bando
fuente
Dado su último comentario, ¿está bien si siempre devolvemos una lista con los dígitos?
Greg Martin
Sí, esa es una forma razonable de dar salida, siempre y cuando los números sean correctos
Ando Bando
1
Estoy obteniendo en 100 -> 10035lugar de 100 -> 10033, ¿puedes verificar?
Greg Martin el
@GregMartin 10035 parece correcto. Hice mis cálculos con lápiz y no con programa y, por lo tanto, cometí un error de cálculo. Supongo que tenemos computadoras para un reasom
Ando Bando

Respuestas:

4

Mathematica, 64 bytes

Part[Join@@Array[Tuples@Join[{{1}},Array[Range,#-1,3]-1]&,#],#]&

Función sin nombre que toma un argumento entero positivo y devuelve una lista de enteros.

Join[{{1}},Array[Range,#-1,3]-1]devuelve la lista anidada { {1}, {0,1,2}, {0,1,2,3}, ..., {0,1,...,#} }. Luego Tuplesdevuelve el conjunto (ordenado) de todas las tuplas en cuyo primer elemento se encuentra {1}, en cuyo segundo elemento se encuentra {0,1,2}, y así sucesivamente; Estos son los #números de dígitos en este sistema de numeración. Join@@Array[...,#]devuelve una matriz de todos los números en este sistema de numeración con, como máximo #, dígitos, y Part[...,#]extrae el #número.

¡Esto es irremediablemente lento! Funciona bien para la entrada de hasta 9. Para una entrada más grande, pruébela reemplazando el final ,#],#]&con ,Ceiling[0.9Log[#]]],#]&; Esto pone un límite más realista en la cantidad de dígitos necesarios para llegar lo suficientemente lejos en el sistema de numeración como para encontrar el que queremos.

Greg Martin
fuente
3

Mathematica, 93 bytes

Nest[#/.{x___,y_}:>{x,y+1}//.x:{y___,z_:0,w_,v___}/;w>Tr[1^x]-Tr[1^{v}]:>{y,z+1,0,v}&,{0},#]&

Función pura con primer argumento #. Si se proporciona un entero no negativo, generará la lista correcta de dígitos (¡incluso se maneja 0correctamente!).

Explicación

Nest[f,expr,n]da el resultado de aplicar fa expr ntiempos. En este caso, expres la lista {0}y nes el entero de entrada #. La función fes complicada:

# (* Starting with the input # *)
 /. (* Apply the following rule *)
   {x___,y_} (* If you see a list of the form {x___,y} *)
            :> (* replace it with *)
              {x,y+1} (* this *)
                     //. (* Now apply the following rule repeatedly until nothing changes *)
                        x:{y___,z_:0,w_,v___} (* If you see a list x starting with a sequence y of 0 or more elements, 
                                                 followed by an optional element z (default value of 0),
                                                 followed by an element w,
                                                 followed by a sequence v of 0 or more elements *)
                                             /; (* such that *)
                                               w>Tr[1^x]-Tr[1^{v}] (* w is greater than the length of x minus the length of {v} *)
                                                                  :> (* replace it with *)
                                                                    {y,z+1,0,v}& (* this *)
ngenisis
fuente
Buen uso de y___,z_:0para aumentar la longitud de la lista!
Greg Martin
2
@GregMartin JungHwan Min lo usó en un problema similar ayer.
ngenisis
3

Perl 6 , 38 bytes

{map({|[X] 1,|map ^*,3..$_},1..*)[$_]}

Toma un entero positivo y genera una lista de enteros que representan los dígitos.

Explicación:

{                                    }  # a lambda

 map({                    },1..*)       # for each number length from 0 to infinity,
                                        # offset by 1 to avoid a +1 in next step...

           1,|map ^*,3..$_              # generate the digit ranges, e.g.:
                                        #     length 0  ->  (1)  # bogus, but irrelevant
                                        #     length 1  ->  (1)
                                        #     length 2  ->  (1, 0..2)
                                        #     length 3  ->  (1, 0..2, 0..3)
                                        #     length 4  ->  (1, 0..2, 0..3, 0..4)

       [X]                              # take the cartesian product

      |                                 # slip the results into the outer sequence

                                 [$_]   # Index the sequence generated this way
smls
fuente
2

Pyth - 14 bytes

Simplemente devuelve el nthvalor que se ajusta al "patrón de valor de posición menor".

e.f.A.eghkbjZT

Test Suite .

Maltysen
fuente
2
¿Funciona esto en la entrada 2018967, donde el último dígito es igual a 10?
Greg Martin
1

Haskell, 65 bytes

i(x:r)|x>length r=0:i r|1<2=1+x:r
i[]=[1]
reverse.(iterate i[]!!)

iaumenta los números en el sistema numérico con los dígitos en orden inverso. iteratecrea la lista infinita de todos estos números comenzando con cero, que se representa con []. Entonces todo lo que queda por hacer es tomar ( !!) el número solicitado y reverseeso.

La última línea es una función, no una definición de función, por lo que no puede aparecer como está en un archivo de código fuente. En su lugar, solo coloque las otras líneas en el código fuente y use la última línea en el intérprete (o vincule la función a un nombre precediendo f=a la última línea).

Ejemplo de uso:

*Main> reverse.(iterate i[]!!) $ 100
[1,0,0,3,5]

(Se podrían guardar 8 bytes si [5,3,0,0,1]fuera una representación permitida del resultado).

Christian Sievers
fuente
1

Haskell, 49 bytes

x=[1]:[n++[d]|n<-x,d<-[0..length n+1]]
(x!!).pred

La primera línea es una definición auxiliar, y la segunda se evalúa como una función. Toma un entero y devuelve una lista de enteros. Pruébalo en línea!

Explicación

Lo defino xcomo la lista infinita de representaciones mencionadas en el texto del desafío; la función principal simplemente disminuye su argumento e indexa en x. La primera línea funciona así:

x=                     -- The list of lists x contains
 [1]:                  -- the list [1], followed by
 [n++[d]|              -- integer d appended to list n, where
  n<-x,                -- n is drawn from x, and
  d<-[0..length n+1]]  -- the new "digit" d is drawn from this range.

Verá que xse define en términos de sí mismo, pero Haskell es vago, por lo que esto no es un problema.

Zgarb
fuente