Saída dos enésimos dígitos de um número inteiro


13

Sem usar strings (exceto quando necessário, como com entrada ou saída) calcule o enésimo dígito, a partir da esquerda , de um número inteiro (na base 10).

A entrada será fornecida neste formato:

726433 5

A saída deve ser:

3

como esse é o quinto dígito de "726433".

A entrada não conterá zeros à esquerda, por exemplo "00223".

Casos de teste / outros exemplos:

9 1  ->  9
0 1  ->  0
444494 5  ->  9
800 2  ->  0

Isso é código de golfe; menor quantidade de caracteres vence, mas qualquer função incorporada, como "nthDigit (x, n)", não é aceitável .

Aqui estão alguns pseudo-códigos para você começar:

x = number
n = index of the digit
digits = floor[log10[x]] + 1
dropRight = floor[x / 10^(digits - n)]
dropLeft = (dropRight / 10 - floor[dropRight / 10]) * 10
nthDigit = dropLeft

Como você pode ver, sou novo no código do golfe e, embora eu ache um pouco injusto fazer uma pergunta antes mesmo de responder uma, gostaria muito de ver que tipo de resposta isso gera. :)

Edit : Eu estava esperando por respostas matemáticas, por isso não posso realmente aceitar respostas que dependem da conversão de strings em matrizes ou de poder acessar números como uma lista de dígitos.

Temos um vencedor

Escrito em "dc", 12 bytes. Por DigitalTrauma .


Isso pode ser apenas uma função ou precisa lidar com E / S? Se ele não precisar lidar com E / S, pode ser simplesmente um lambda em vez de uma função?
Slebetman

Sua edição deixa claro o que exatamente você não gosta. Em particular, com "poder acessar números como uma lista de dígitos", é o uso de matrizes de qualquer forma que você não goste, ou apenas a existência de rotinas de conversão de base integradas?
Peter Taylor

@PeterTaylor Matrizes de dígitos não estão OK, pois é possível simplesmente pegar o enésimo item na matriz. Não tenho certeza de como a conversão de base funciona exatamente, mas parece fácil.
precisa saber é o seguinte

Por que é um problema criar uma lista de dígitos? Isso é altamente matemático - representa o número como um polinômio.
2rs2ts

@ 2rs2ts Se puder criar uma lista de dígitos matematicamente, ou seja, sem analisar uma cadeia de caracteres em uma matriz, pode ser aceitável.
kukac67

Respostas:


2

dc , 12 bytes

?dZ?-Ar^/A%p

Esta é uma resposta matemática. Veja como funciona:

  • ? leia o número de entrada e pressione para empilhar
  • d topo duplicado da pilha
  • Z Retorna o valor da pilha, calcula e envia o número de dígitos
  • ? leia o índice de dígitos e pressione para empilhar
  • - subtrair índice de dígitos da contagem de dígitos
  • A empurre 10 para a pilha
  • r trocar os 2 principais valores na pilha
  • ^ exponenciada 10 ^ (contagem de dígitos - índice de dígitos)
  • / dividir número pelo resultado da exponenciação
  • A empurre 10 para a pilha
  • % calcule o número mod 10 para obter o último dígito e empurre para o topo da pilha
  • p pop e imprima a parte superior da pilha

Em ação:

$ {eco 987654321; eco 1; } dc ndigit.dc
9
$ {eco 987654321; eco 2; } dc ndigit.dc
8
$ {eco 987654321; eco 8; } dc ndigit.dc
2
$ {eco 987654321; eco 9; } dc ndigit.dc
1
$ 

1
Eu acho que você é o vencedor. Este é o terceiro código mais curto, mas o 2 mais curto usado base conversion -> arrays.
kukac67

5

GolfScript (10 bytes)

~(\10base=

Isso pressupõe que a entrada seja uma string (por exemplo, via stdin). Se houver dois números inteiros na pilha, a inicial ~deve ser removida, economizando 1 caractere.

Se a conversão de base for considerada incorreta com a regra de funções internas, eu tenho uma alternativa de 16 caracteres:

~~)\{}{10/}/=10%

Seu primeiro programa com a conversão base gera o primeiro dígito somente se você digitar "0" e o segundo se você digitar "1". golfscript.apphb.com/?c=MjcwNiAxCgpcMTBiYXNlPQ%3D%3D
kukac67

@ kukac67, corrigido.
Peter Taylor

4

CJam - 7

l~(\Ab=

CJam é uma nova linguagem que estou desenvolvendo, semelhante ao GolfScript - http://sf.net/p/cjam . Aqui está a explicação:

llê uma linha da entrada
~avalia a string (obtendo assim os dois números)
(diminui o segundo número
\troca os números
Aé uma variável pré-inicializada para 10
bfaz uma conversão de base, fazendo um array com os dígitos da base 10 do primeiro número
=obter o desejado elemento da matriz

O programa é basicamente uma tradução da solução de Peter Taylor.


Eu diria que colocar 10 dígitos da base em uma matriz é mais uma operação de string do que matemática.
Digital Trauma


3

J - 15 24 caracteres

Uma resposta "matemática suficiente".

(10|[<.@*10^]-10>.@^.[)/

Mesmos resultados que abaixo, mas é dotado da qualidade mística de ser matemático.


A versão curta, usando expansão de base 10.

({0,10&#.inv)~/

Anexamos um 0 para ajustar a indexação baseada em 1.

Uso:

   ({0,10&#.inv)~/ 1234567 3
3
   ({0,10&#.inv)~/ 444494 5
9

2
Strings não são permitidas.
0xcaff

2

Python 127

def f(i,n):
 b=10;j=i/b;k=1;d=i-j*b
 while j>0:
  k+=1;j/=b
 if n>k:
  return -1
 while k>n:
  k-=1;j/=b;i/=b;d=i-j*b
 return d

Você não precisa de defini-lo como uma nota de rodapé:def f(i,n): ... return d
SMCI

Você não precisa verificar a sanidade do if n>k: return -1caso.
SMCI

... e você certamente não precisa fazer uma primeira passagem apenas para contar k (o número de dígitos em i), para sanidade - compará-lo com n.
SMCI

2

C, 50

Isso usa matrizes.

main(int c,char**a){putchar(a[1][atoi(a[2])-1]);}

Apenas ignore todos os avisos.

E sim, em C, strings são realmente apenas matrizes, então isso é meio barato.


Mais matemático:

C, 83

main(int c,char**a){printf("%d",(atoi(a[1])/pow(10,strlen(a[1])-atoi(a[2])))%10);}

não está usando funções string / array?
VX

O primeiro, como diz;) O segundo obviamente não, exceto o strlen, que eu escolhi simplesmente porque é mais curto do que usar o log. Se for um problema, é uma solução fácil, posso adicioná-lo quando chegar em casa.
SBI

Lá vamos nós, acrescentou a versão puramente matemática.
SBI

2
Matemática - nem uma vez!
precisa saber é o seguinte

2

bc (impulsionado por bash), 41 29

Eu acho que esta é a primeira resposta para fazer isso matematicamente e não com strings:

bc<<<"$1/A^(length($1)-$2)%A"

O uso de length()talvez pareça um pouco complicado, mas a página de manual do bc fala sobre o número de dígitos e não o comprimento da string:

  length ( expression )
          The value of the length function is the  number  of  significant
          digits in the expression.

Resultado:

$ ./ndigits.bc.sh 726433 5
3
$ ./ndigits.bc.sh 9 1
9
$ ./ndigits.bc.sh 0 1
0 0
$ ./ndigits.bc.sh 444494 5
9
$ ./ndigits.bc.sh 800 2
0 0
$ 

1
@ kukac67 Agradeço o voto de aceitação! Mas acho que é habitual que as perguntas sobre código de golfe sejam deixadas em aberto por mais de duas horas para incentivar mais respostas. Talvez uma semana mais ou menos. Eu não vou ficar ofendido se você de-aceitar essa resposta :)
Trauma Digital

1
Está bem. Eu vou des-aceitar então. Espero que você não ganhe! : P
kukac67

1

Mathematica - 24 23

Este é meio óbvio :)

IntegerDigits[#][[#2]]&

Exemplo:

IntegerDigits[#][[#2]]& [726433, 5]

Resultado:

3

Você pode reduzi-lo codificando dois números inteiros, por exemplo

IntegerDigits[n][[m]]

mas então você primeiro tem que escrever n = 726433; m = 5;. A chamada de função parecia mais semelhante a um programa.


1
Você pode soltar o número 1.
9134

Agora isso é trapaça ..: D
kukac67

1

C 145

O programa encontra a distância do final do número inteiro e se divide até o índice ser alcançado e, em seguida, usa o módulo 10 para obter o último dígito.

int main()
{
int i,a,b,d,n;
scanf("%d %d",&i,&a);
d=(int)(log(i)/log(10))+1;
n=d-a;
while(n--){i=(int)(i/10);}
b=i%10;
printf("%d",b);
}

Isso pode ser jogado significativamente. Comece com estas dicas
Digital Trauma

Para começar, os (int) elencos e parens associados são desnecessários
Digital Trauma

1
Eu não pude resistir. I golfed-lo até 87 caracteres: i,a;main(){scanf("%d%d",&i,&a);for(a=log(i)/log(10)+1-a;a--;)i/=10;printf("%d",i%10);}.
Digital Trauma

1

Wolfram Alpha - entre 40 e 43

Claro, posso defender totalmente que usar IntegerDigitsé um truque que não se enquadra

quaisquer funções incorporadas, como "nthDigit (x, n)"

Mas como minha resposta anterior ainda parecia trapacear um pouco, aqui está uma alternativa. Infelizmente, é um pouco mais longo, mas não vi como reduzi-lo mais do que vi.

Contando da mesma maneira que antes (com o e comercial, sem passar em nenhum argumento),

Mod[Trunc[#/10^(Trunc[Log10[#]]-#2+1)],10]&

possui 43 caracteres. Ao negar o expoente e embaralhar os termos, posso perder um operador aritmético ( 10^(...)xserá interpretado como multiplicação)

Mod[Trunc[10^(#2-Trunc[Log10[#]]-1)#],10]&

Não tenho o Mathematica à mão para testar, duvido que seja Como eu suspeitava (e como foi gentilmente verificado por kukac67 ) no Mathematica, isso não é aceito, mas é executado no WolframAlpha .

Estou em dúvida sobre o uso de RealDigits, porque me restringi de usar IntegerDigitspara esta resposta e elas são bastante semelhantes. No entanto, se eu me permito incluí-lo (afinal, ele não retorna os inteiros diretamente, assim como muitos deles não são), eu posso cortar fora mais dois personagens:

Mod[Trunc[10^(#2-RealDigits[#]-1)#],10]&

Eu tentei no Mathematica, ele não gera um valor. O caráter 43 um ouputs isto:Mod[Trunc[57 2^(3 - Trunc[Log[456]/Log[10]])5^Trunc[Log[456]/Log[10]]], 10]
kukac67

Sim, eu percebi isso. O Wolfram Alpha é um pouco mais tolerante na interpretação de entradas. Felizmente, dei-lhe o cabeçalho correto;) #
016

Mas vejo que funciona no WolframAlpha.
precisa saber é o seguinte

{edit} Embora eu veja que o link está quebrado ... aparentemente não gosta de [caracteres, mesmo quando estão codificados. Vou passar por um encurtador de URL. {edit2} Aparentemente, o W.Alpha mudou um link.
CompuChip

1

Tcl (42 bytes, lambda):

{{x y} {expr $x/10**int(log10($x)+1-$y)%10}}

(49 bytes, função):

proc f {x y} {expr $x/10**int(log10($x)+1-$y)%10}

(83 bytes, se precisarmos aceitar entrada do shell):

puts [expr [lindex $argv 0]/10**int(log10([lindex $argv 0])+1-[lindex $argv 1])%10]

Como é que isso funciona?
kukac67

Adicionado explicação. É apenas a maneira mais óbvia de fazer isso matematicamente. Como você faria isso no papel.
slebetman

Eu acho que você está contando do lado errado.
Peter Taylor

Hmm ... sim. Parece que sim. Vou revisá-lo para contar da esquerda.
slebetman

Eu aceito os 31 bytes. Embora como o lambda possa ser executado? Tcl tem um intérprete que possa usá-lo? Ou apenas como parte de um programa que define os argumentos?
precisa saber é o seguinte

1

R (60)

Resolvido o problema usando o log10 para calcular o número de dígitos. O caso especial x == 0 custa 13 caracteres, suspiro.

f=function(x,n)if(x)x%/%10^(trunc(log10(x))-n+1)%%10 else 0

Ungolfed:

f=function(x,n)
  if(x) 
    x %/% 10^(trunc(log10(x)) - n + 1) %% 10
  else
    0

Uso

> f(898,2)
[1] 9

1

Scala ( 133 99 bytes):

Funciona para todas as entradas positivas. Divide por 10 a potência do dígito procurado da direita e, em seguida, leva o módulo 10.

def k (i: Array [String]) = {val m = i (0) .toInt
(m * Math.pow (10, i (1) .toInt-1-Math.log10 (m) toInt)). toInt% 10}

Obrigado por perceber o bug na fórmula anterior. Este é mais curto.


Eu gosto disso! :) Up-
vote

Testou a solução: k (Matriz ("1234", "7")), que fornece 9. Não funciona para n> #digits (x)?
precisa saber é o seguinte

É porque 10 ^ -1 não é exato nesta notação; portanto, há um erro de arredondamento quando você recebe 10% de pow (10, -1), que deveria ter dado zero, mas deu 0,0999. Corrigida minha resposta para acomodar esse efeito colateral.
Mikaël Mayer

1

Haskell, 142

Não sei se entendi a pergunta corretamente, mas é o que acho que você queria: leia stdin (string), faça os dois números int (não string), faça algumas coisas algorítmicas e depois produza o resultado (string). Coloquei 142 caracteres, o que é demais:

import System.Environment
a%b|a>9=div a 10%(b+1)|1<2=b
x#n=x`div`10^(x%1-n)`mod`10
u[a,b]=read a#read b
main=fmap(u.words)getContents>>=print

exemplo de uso:

> echo 96594 4 | getIndex
9

1

JavaScript - 84

p=prompt,x=+p(),m=Math;r=~~(x/m.pow(10,~~(m.log(x)/m.LN10)+1-+p()));p(r-~~(r/10)*10)

Puramente matemático, sem strings, nenhum deles. Pega o primeiro número no primeiro prompt e o segundo número no segundo prompt.

Caso de teste :

Input: 97654 5
Output: 4

Input: 224658 3
Output: 4

Código Ungolfed:

p = prompt,
x = +p(), // or parseInt(prompt())
m = Math;

r = m.floor( x / m.pow(10, m.floor(m.log(x) / m.LN10) + 1 - +p()) )
//                                               ^-- log(10) ^-- this is `n`

p(r - ~~(r / 10) * 10) // show output

1

perl, 38, 36   há 30 caracteres

(sem contar o avanço de linha)

Isso sem dúvida é trapaça devido à opção de comando, mas obrigado por me deixar jogar :-)

~/$ cat ndigits.pl
say((split//,$ARGV[0])[$ARGV[1]-1]);
~/$ tr -cd "[:print:]" < ndigits.pl |wc -m 
36
~/$ perl -M5.010 ndigits.pl 726433 5 
3

editar :

Conseguiu remover 2 caracteres:

 say for(split//,$ARGV[0])[$ARGV[1]-1];
 say((split//,$ARGV[0])[$ARGV[1]-1]);

... mais 6:

 say((split//,shift)[pop()-1]);

Quão

Dividimos a entrada do primeiro argumento no script $ARGV[0]por character ( split//) criando uma matriz indexada zero; adicionar um ao segundo argumento $ARGV[1]no script corresponde ao elemento nessa posição na cadeia ou no primeiro argumento. Em seguida, mantemos a expressão dentro ()como uma lista de um elemento que sayiterará. Para a versão curta mais curta, apenas shiftno primeiro argumento e usamos a parte restante do @ARGV para usar no índice - uma vez shifted, apenas o segundo argumento permanece, e nós pop()subtraímos 1.

Isso deveria ser um exercício de matemática? Acabei de perceber que estou indexando uma string lida na entrada, então ... acho que perco ?? Marque-me se eu fizer sentido em um campo de golfe paralelo e tentarei novamente - mais matematicamente - em uma resposta separada.

Felicidades,


Sim, desculpe, sem usar strings . Bem-vindo ao PPCG de qualquer maneira!
Digital Trauma

OK, desculpe por ... até agora, minhas abordagens matemáticas não valem muito a pena :-)
G. Cito

0

PHP, 58

Usando apenas matemática

<?$n=$argv[1];while($n>pow(10,$argv[2]))$n/=10;echo $n%10;


1
Isso não é da direita?
cjfaure

2
Você pode salvar 1 caractere alterando-o para echo$n%10.
Amal Murali

@ Trimsty não, ele realmente faz um loop até que o número digitado não seja maior que 10 ^ x, x sendo o número do dígito. Portanto, por exemplo, se você digitar 3457 como um número e 2 como um dígito, o último dígito será retirado até que o número fique menor que 100 (10 ^ 2). Isso significa que ele tira 5 e 7, porque então resta 34 e não é maior que 100. Em seguida, apenas gera o último dígito (4).
Dkasipovic 9/04

Mas é verdade que, se o segundo número é maior do que o número de dígitos, você saída 9 e não é zero
Mikaël Mayer

Entendo, ele gera o último dígito se o número for maior que o número de dígitos. Se você digitar 1234 e 5º dígito, obterá 4, pois 1234 já é menor que 10 ^ 5.
Dkasipovic

0

~ - ~! - 94 93

Dobra um pouco as regras - é uma função que recebe n como entrada e assume que o número para encontrar o dígito n é armazenado em '''''- e ~ - ~! não suporta carros alegóricos.

'=~~~~~,~~:''=|*==~[']<''&*-~>,'|:'''=|*==%[%]~+*/~~~~/~~|:''''=|'''''/''&<<'''&'''''>-*-~>|:

'''''=~~~~,~~,~~,~~,~~,~~:''''''=''''&~:resultarão em ''''''ser ~~(2) ( '' '''= 128).


Hum ... Mais uma linguagem esotérica?
VisioN

@VisioN não é realmente esotérico, apenas que o único tipo de dados nativo é um número e não pode interagir com o sistema operacional / internet. esolangs.org/wiki/No_Comment
cjfaure

1
Bem, para mim toda sintaxe que não pode ser facilmente lida por um ser humano é esotérica. E sim, Perl também é esotérico de acordo com essa teoria:)
Visão

@VisioN Fica fácil de ler depois de um tempo. : P
cjfaure

0

Python 2.7 (89 bytes)

Transformei o número inteiro em um "polinômio" usando uma lista de dígitos. Eu sei que você diz que não pode aceitar isso, mas não vejo por que não, pois usa o conceito matemático de números sendo representados como polinômios de suas bases. Só falhará quando o número inteiro for passado 0, mas você disse que não há zeros acolchoados;)

import sys;v=sys.argv;p,x,n=[],int(v[1]),int(v[2])
while x:p=[x%10]+p;x//=10
print p[n-1]

Executar como test.py:

$ python test.py 726489 5
8

Suponho que você quisesse entrada de shell e que eu não poderia fazer uso do fato de que a entrada seria string. Ignorando a entrada do shell, são apenas 43 bytes, com:

p=[]
while x:p=[x%10]+p;x//=10
print p[n-1]

Embora eu use alguma iteração desnecessária, economizo alguns bytes não adicionando um decremento adicional n.


0

BrainFuck estendido : 49

+[>>,32-]<<-[<<-],49-[->>>[>>]+[<<]<]>>>[>>]<33+.

Uso:

% bf ebf.bf < nth-digit.ebf > nth-digit.bf
% echo "112234567 7" | bf nth-digit.bf 
5

Não estou usando nenhum recurso especial do EBF, exceto o operador de multiplicação (por exemplo, 10+ => ++++++++++ ). Fora isso, é principalmente puro BrainFuck

Como funciona:

+                ; Make a 1 in the first cell
[>>,32-]         ; while cell is not zero: read byte 2 to the right and reduce by 32 (space)
<<-[<<-]         ; move back to the first cell by reducing every cell with 1
,49-             ; read index, reduce by 49 so that ascii 1 becomes 0
[->>>[>>]+[<<]<] ; use that to fill a trail of breadcrumbs to the desired number
>>>[>>]          ; follow the breadcrumbs
<33+.            ; go to value part, increase by 33 (32 + 1 which we substracted) and print

Esquema (R6RS): 100 (sem espaço em branco desnecessário)

(let*((x(read))(n(read))(e(expt 10(-(floor(+(/(log x)(log 10))1))n))))
  (exact(div(mod x(* e 10))e)))

0

awk - 53

{for(d=10^9;!int($1/d)||--$2;d/=10);$0=int($1/d)%10}1
  1. aparar dígitos por divisão, começando com max possível para int sem sinal de 32 bits
  2. quando atingimos o lado esquerdo do número inteiro, int ($ 1 / d) retorna diferente de zero
  3. continue n ($ 2) dígitos além desse

Ungolfed:

{
    for(d = 1000000000; int($1 / d) != 0 || --$2; d /= 10);
    print int($1 / d) % 10;
}

0

Scala (83)

Não usa nenhum recurso especial do Scala. Antes, a solução padrão.

def f(x:Int,n:Int)=if(x==0)0 else x/(math.pow(10,math.log10(x).toInt-n+1)).toInt%10

Ungolfed:

def f(x:Int,n:Int) = 
  if(x==0)
    0
  else
    x / (math.pow(10, math.log10(x).toInt - n + 1)).toInt % 10 

0

C, 94

main(x,y,z,n){scanf("%d%d",&x,&y);for(z=x,n=1-y;z/=10;n++);for(;n--;x/=10);printf("%d",x%10);}

C, 91, inválido devido ao uso de matrizes.

main(x,y,z){int w[99];scanf("%d%d",&x,&y);for(z=0;x;x/=10)w[z++]=x%10;printf("%d",w[z-y]);}

Não permiti matrizes em uma edição (antes de você postar isso) ... Mas eu gosto de como você fez isso. :)
kukac67

OK, eu não estava olhando corretamente. Eu adicionei uma solução evitando matrizes.
VX

0

Julia 37

d(x,y)=div(x,10^int(log10(x)-y+1))%10

Devido ao operador interno ^. A aritmética de precisão arbitrária permite qualquer tamanho int.

Amostra

julia> d(1231198713987192871,10)
3

0

perl (um pouco mais mathy / não muito golfy) - 99 caracteres

 ~/$ cat ndigits2.pl
  ($n,$i)=@ARGV;
  $r=floor($n/10**(floor(log($n)/log(10)+1)-$i));
  print int(.5+($r/10-floor($r/10))*10);

Execute-o como:

 perl -M5.010 -MPOSIX=floor ndigits.pl 726433 1

0

Perl6 - 85 caracteres

my ($n,$i)=@*ARGS;
my$r=$n/10**(log10($n).round-$i);
say (($r/10-floor($r/10))*10).Int;

0

Smalltalk, 44

Embora dc seja imbatível, aqui está uma solução Smalltalk:

argumentos, número n; d dígito-nr para extrair:

[:n :d|(n//(10**((n log:10)ceiling-d)))\\10]
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.