Convertendo números em um "sistema não de valor de mercado"

11

Vamos criar um sistema de números em que o maior dígito no enésimo valor colocado (contando da direita para a esquerda) de um comprimento de número m é sempre igual a m - n + 1. Para dar um exemplo, o maior número de 5 dígitos expressável neste sistema está escrito 12345. Além do número de dígitos disponíveis para uso em um local específico estar restrito, todo o restante incremento é padrão. Ou seja, quando um dígito ultrapassa seu limite, adicionamos um ao próximo dígito.

Aqui está como a contagem seria representada neste sistema:

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

Sua tarefa é escrever uma função que pega um número base 10 padrão e o converte no meu sistema de numeração.

Código mais curto é preferível. Bonne Chance!

** Se você precisar de dígitos após 9 (você deve), poderá optar por usar letras ou retornar um número de 2 dígitos como elemento de uma lista.

Casos de teste

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

O último caso pode ser incrivelmente lento para executar, dependendo de como você implementou. Você não precisa executá-lo se demorar muito ou usar muita memória. No entanto, observe que existem maneiras de executá-lo rapidamente e usando pouca memória.

Ando Bando
fonte
Dado seu último comentário, tudo bem se sempre retornamos uma lista com os dígitos?
Greg Martin
Sim, isso é uma forma razoável para dar saída, contanto que os números estão corretos
Ando Bando
1
Estou ficando 100 -> 10035mais do que 100 -> 10033você pode verificar?
Greg Martin
@GregMartin 10035 parece certo. Fiz meus cálculos com caneta e não com o programa e, portanto, cometi um erro de computação. Eu acho que nós temos computadores por um motivo
Ando Bando

Respostas:

4

Mathematica, 64 bytes

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

Função sem nome, usando um argumento inteiro positivo e retornando uma lista de números inteiros.

Join[{{1}},Array[Range,#-1,3]-1]retorna a lista aninhada { {1}, {0,1,2}, {0,1,2,3}, ..., {0,1,...,#} }. Em seguida, Tuplesretorna o conjunto (classificado) de todas as tuplas cujo primeiro elemento está {1}, cujo segundo elemento está {0,1,2}, e assim por diante; esses são os #números de dígitos neste sistema de numeração. Join@@Array[...,#]retorna uma matriz de todos os números neste sistema de numeração com no máximo #dígitos e Part[...,#]extrai o #th tal número.

Isso é irremediavelmente lento! Ele funciona bem para a entrada de até 9. Para entradas maiores, teste-a substituindo a extremidade ,#],#]&por ,Ceiling[0.9Log[#]]],#]&; isso coloca um limite mais realista no número de dígitos necessários para ir longe o suficiente no sistema de numeração para encontrar o que queremos.

Greg Martin
fonte
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},#]&

Função pura com o primeiro argumento #. Se um número inteiro não negativo for fornecido, ele exibirá a lista correta de dígitos (até lida 0corretamente!).

Explicação

Nest[f,expr,n]fornece o resultado da aplicação fde expr ntempos. Nesse caso, expré a lista {0}e né o número inteiro de entrada #. A função fé 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
fonte
Bom uso de y___,z_:0para aumentar o comprimento da lista!
Greg Martin
2
@GregMartin JungHwan Min o usou em um problema semelhante ontem.
Ngenisis
3

Perl 6 , 38 bytes

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

Pega um número inteiro positivo e gera uma lista de números inteiros que representam os dígitos.

Explicação:

{                                    }  # 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
fonte
2

Pitão - 14 bytes

Simplesmente retorna o nthvalor que se encaixa no "padrão de valor menor que o local".

e.f.A.eghkbjZT

Conjunto de Teste .

Maltysen
fonte
2
Isso funciona na entrada 2018967, onde o último dígito é 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 os números no sistema numérico com os dígitos na ordem inversa. iteratecria a lista infinita de todos esses números começando com zero, o qual é representado por []. Tudo o que resta fazer é pegar ( !!) o número exigido e reverseele.

A última linha é uma função, não uma definição de função, portanto, não pode aparecer como está em um arquivo de código-fonte. Em vez disso, coloque apenas as outras linhas no código-fonte e use a última linha no intérprete (ou vincule a função a um nome, acrescentando f=a última linha).

Exemplo de uso:

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

(8 bytes podem ser salvos se houver [5,3,0,0,1]uma representação permitida do resultado.)

Peneiradores cristãos
fonte
1

Haskell, 49 bytes

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

A primeira linha é uma definição auxiliar e a segunda é avaliada como uma função. Ele pega um número inteiro e retorna uma lista de números inteiros. Experimente online!

Explicação

Eu defino xcomo a lista infinita de representações mencionadas no texto do desafio; a função principal apenas diminui seu argumento e indexa em x. A primeira linha funciona assim:

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.

Você vê que isso xé definido em termos de si mesmo, mas Haskell é preguiçoso, então isso não é um problema.

Zgarb
fonte