Linha de números naturais

22

Definição

Há uma linha infinita de números naturais concatenados (números inteiros positivos, começando com 1):

1234567891011121314151617181920212223...

Desafio

  • Escreva um programa em qualquer idioma, que aceite o número da posição como uma entrada e emita um dígito dessa posição na linha definida acima.
  • O número da posição é um número inteiro positivo de tamanho arbitrário. Essa é a primeira posição é 1, produzindo o dígito de saída '1'
  • A entrada é decimal (por exemplo: 13498573249827349823740000191) ou a notação eletrônica (por exemplo: 1.2e789) corresponde ao número inteiro positivo.
  • O programa precisa terminar em um tempo razoável (10 segundos no PC / Mac moderno), dado um índice muito grande como entrada (por exemplo, 1e123456 - ou seja, 1 com 123456 zeros). Portanto, um loop de iteração simples não é aceitável.
  • O programa deve terminar com um erro em 1 s, se receber alguma entrada inválida. Por exemplo. 1.23e (inválido) ou 1.23e1 (igual a 12.3 - não um número inteiro)
  • Não há problema em usar a biblioteca pública do BigNum para analisar / armazenar números e executar operações matemáticas simples neles (+ - * / exp). Nenhuma penalidade de byte aplicada.
  • O menor código vence.

TL; DR

  • Entrada: número inteiro bignum
  • Saída: dígito nessa posição em linha infinita 123456789101112131415...

Alguns casos de teste de aceitação

na notação "Input: Output". Todos eles devem passar.

  • 1: 1
  • 999: 9
  • 10000000: 7
  • 1e7: 7 (igual à linha acima)
  • 13498573249827349823740000191: 6
  • 1.1e10001: 5
  • 1e23456: 5
  • 1.23456e123456: 4
  • 1e1000000: 0
  • 1.23e: erro (sintaxe inválida)
  • 0: erro (fora dos limites)
  • 1.23e1: erro (não um número inteiro)

Bônus!

Digite o número da posição do dígito dentro do número e o próprio número de saída. Por exemplo:

  • 13498573249827349823740000191: 6 24 504062383738461516105596714
    • Esse é o dígito '6' na posição 24 do número '50406238373846151610559 6 714'
  • 1e1000000: 0 61111 1000006111141666819445...933335777790000
    • O dígito '0' na posição 61111 do número longo de 999995 dígitos que não vou incluir aqui.

Se você cumprir a tarefa de bônus, multiplique o tamanho do seu código por 0,75

Crédito

Essa tarefa foi realizada em uma das reuniões do devclub.eu no ano de 2012, sem a necessidade de um grande número. Portanto, a maioria das respostas enviadas foram loops triviais.

Diverta-se!

metalim
fonte
Eu realmente não entendo qual é o desafio. Devemos pegar a entrada e enviar o número nessa posição?
The_Basset_Hound
1
Esta é a sequência OEIS 33307 .
Tyilo
2
@vihan O uso de alguma biblioteca pública bignum é aceitável. Sem penalidade. É claro que incluir a solução na biblioteca e usar a biblioteca em uma linha é considerar trapaça. O senso comum se aplica aqui.
metalim 5/08/2015
1
Só queria mostrar uma solução F # surpreendentemente concisa , com clock de 44 bytes. Concedido, ele só pode manipular índices de até 2 ^ 31-1 (e ainda está tentando calcular esse valor enquanto escrevo isso). Eu não estou postando isso, porque ele realmente quebra as regras, mas eu diria que é muito bom para F #!
Jwosty
7
Os requisitos para lidar com entradas como 1.23456e123456punem arbitrariamente linguagens que não podem processar esses valores de forma nativa e exigem que eles façam o processamento de strings que é tangencial ao desafio.
Xnor

Respostas:

12

CJam , 78 bytes

r_A,s-" e . .e"S/\a#[SSS"'./~'e/~i1$,-'e\]s"0]=~~_i:Q\Q=Qg&/
s,:L{;QAL(:L#9L*(*)9/-_1<}g(L)md_)p\AL#+_ps=

O programa tem 104 bytes e se qualifica para o bônus.

A nova linha é puramente cosmética. A primeira linha analisa a entrada, a segunda gera a saída.

Experimente online!

Idéia

Para qualquer número inteiro positivo k , existem números inteiros positivos de 9 × 10 k-1 com exatamente k dígitos (sem contar os zeros à esquerda). Assim, se concatenamos todos eles, obtemos um número inteiro de 9 × n × 10 k-1 .

Agora, concatenar todos os números inteiros de n ou menos dígitos produz um número inteiro de

Fórmula

dígitos.

Para uma determinada entrada q , tentamos determinar o n mais alto, de modo que a expressão acima seja menor que q . Definimos n: = log 10 q⌉-1 , depois n: = log 10 q⌉-2 , etc. até que a expressão desejada se torne menor que q , subtraia a expressão resultante de q (produzindo r ) e salve a última valor de n em l .

r agora especifica o índice na concatenação de todos os números inteiros positivos de l + 1 dígitos, o que significa que o resultado desejado é o r% (l + 1) th dígito do r / (l + 1) th número inteiro de l + 1 dígitos.

Código (análise de entrada)

r_          e# Read from STDIN and duplicate.
A,s-        e# Remove all digits.
" e . .e"S/ e# Push ["" "e" "." ".e"].
\a#         e# Compute the index of the non-digit part in this array.

[SSS"'./~'e/~i1$,-'e\]s"0]

            e# Each element corresponds to a form of input parsing:
            e#   0 (only digits): noop
            e#   1 (digits and one 'e'): noop
            e#   2 (digits and one '.'): noop
            e#   3 (digits, one '.' then one 'e'):
            e#     './~    Split at dots and dump the chunks on the stack.
            e#     'e/~    Split the and chunks at e's and dump.
            e#     i       Cast the last chunk (exponent) to integer.
            e#     1$      Copy the chunk between '.' and 'e' (fractional part).
            e#     ,-      Subtract its length from the exponent.
            e#     'e\     Place an 'e' between fractional part and exponent.
            e#     ]s      Collect everything in a string.
            e#   -1 (none of the above): push 0

~           e# For s string, this evaluates. For 0, it pushes -1.
~           e# For s string, this evaluates. For -1, it pushes 0.
            e# Causes a runtime exception for some sorts of invalid input.
_i:Q        e# Push a copy, cast to Long and save in Q.
\Q=         e# Check if Q is numerically equal to the original.
Qg          e# Compute the sign of Q.
&           e# Logical AND. Pushes 1 for valid input, 0 otherwise.
/           e# Divide by Q the resulting Boolean.
            e# Causes an arithmetic exception for invalid input.

Código (geração de saída)

s,:L     e# Compute the number of digits of Q and save in L.
{        e# Do:
  ;      e#   Discard the integer on the stack.
  Q      e#   Push Q.
  AL(:L# e#   Push 10^(L=-1).
  9L*(   e#   Push 9L-1.
  *)     e#   Multiply and increment.
  9/     e#   Divide by 9.
  -      e#   Subtract from Q.
  _1<    e#   Check if the difference is non-positive.
}g       e# If so, repeat the loop.
(        e# Subtract 1 to account for 1-based indexing.
L)md     e# Push quotient and residue of the division by L+1.
_)p      e# Copy, increment (for 1-based indexing) and print.
\AL#+    e# Add 10^L to the quotient.
_p       e# Print a copy.
s        e# Convert to string.
2$=      e# Retrieve the character that corresponds to the residue.
Dennis
fonte
5

CJam, 75 * 0,75 = 56,25

Isso é bastante rápido, uma iteração por dígito do número que contém a posição desejada. Tenho certeza de que pode jogar muito mais, é bastante bruto.

q~_i_@<{0/}&:V9{VT>}{T:U;_X*T+:T;A*X):X;}w;U-(_X(:X/\X%10X(#@+s_2$\=S+@)S+@

Dê a posição como entrada, a saída é:

<digit> <position> <full number>

Experimente online .

Andrea Biondo
fonte
@ Dennis Trabalho com todas as entradas agora :)
Andrea Biondo
Isso ainda não gera um erro (como deveria) para 1.23e1. No entanto, ele erro, 1.23456e123456pois a entrada não pode ser representada por um duplo. Além disso, os últimos casos de teste levam 3 minutos.
Dennis
2
@Dennis Agora gera o erro. Quanto ao grande caso de teste ... Droga. Talvez eu tenha que reescrever a coisa toda.
Andrea Biondo