Saca los enésimos dígitos de un entero


13

Sin usar cadenas (excepto cuando sea necesario, como con entrada o salida), calcule el enésimo dígito, desde la izquierda , de un entero (en la base 10).

La entrada se dará en este formato:

726433 5

La salida debe ser:

3

como ese es el quinto dígito de "726433".

La entrada no contendrá ceros a la izquierda, por ejemplo, "00223".

Casos de prueba / ejemplos adicionales:

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

Este es el código de golf; menor cantidad de caracteres victorias, pero cualquier construido en funciones tales como "nthDigit (x, n)" son no aceptable .

Aquí hay algunos pseudocódigos para comenzar:

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 puede ver, soy nuevo en el código de golf, y aunque creo que es un poco injusto hacer una pregunta antes de responderla, realmente me gustaría ver qué tipo de respuestas genera. :)

Editar : esperaba respuestas matemáticas, por lo que realmente no puedo aceptar respuestas que dependen de la conversión de cadenas en matrices o de poder acceder a los números como una lista de dígitos.

Tenemos un ganador

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


¿Puede ser esto solo una función o debe necesitar manejar E / S? Si no necesita manejar E / S, ¿puede ser simplemente una lambda en lugar de una función?
slebetman

Su edición no deja claro qué es exactamente lo que no le gusta. En particular, con "poder acceder a los números como una lista de dígitos", ¿es el uso de matrices en cualquier forma que no le guste, o simplemente la existencia de rutinas de conversión de base incorporadas?
Peter Taylor

@PeterTaylor Las matrices de dígitos no están bien, ya que uno puede tomar fácilmente el enésimo elemento de la matriz. No estoy seguro de cómo funciona exactamente la conversión de base, pero parece fácil.
kukac67

¿Por qué es un problema crear una lista de dígitos? Eso es altamente matemático: representa el número como un polinomio.
2rs2ts

@ 2rs2ts Si puede crear una lista de dígitos matemáticamente, es decir, sin analizar una cadena en una matriz, entonces podría ser aceptable.
kukac67

Respuestas:


2

dc , 12 bytes

?dZ?-Ar^/A%p

Esta es una respuesta matemática. Así es como funciona:

  • ? leer el número de entrada y presionar para apilar
  • d duplicar la parte superior de la pila
  • Z Extrae el valor de la pila, calcula y empuja el número de dígitos
  • ? leer el índice de dígitos y presionar para apilar
  • - restar índice de dígitos del recuento de dígitos
  • A empuja 10 a la pila
  • r intercambiar los 2 valores superiores en la pila
  • ^ exponer 10 ^ (recuento de dígitos - índice de dígitos)
  • / dividir el número por el resultado de la exponenciación
  • A empuja 10 a la pila
  • % calcule el número mod 10 para obtener el último dígito y presione hasta la parte superior de la pila
  • p pop e imprime la parte superior de la pila

En acción:

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

1
Creo que eres el ganador. Este es el tercer código más corto, pero el 2 más corto utilizado base conversion -> arrays.
kukac67

5

GolfScript (10 bytes)

~(\10base=

Esto supone que la entrada es como una cadena (por ejemplo, a través de stdin). Si es como dos enteros en la pila, la inicial ~debe eliminarse, ahorrando 1 carácter.

Si se considera que la conversión de base no cumple con la regla de funciones incorporadas, tengo una alternativa de 16 caracteres:

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

Su primer programa con la conversión base genera el primer dígito solo si ingresa "0" y el segundo si ingresa "1". golfscript.apphb.com/?c=MjcwNiAxCgpcMTBiYXNlPQ%3D%3D
kukac67

@ kukac67, arreglado.
Peter Taylor

4

CJam - 7

l~(\Ab=

CJam es un nuevo lenguaje que estoy desarrollando, similar a GolfScript: http://sf.net/p/cjam . Aquí está la explicación:

llee una línea desde la entrada,
~evalúa la cadena (obteniendo así los dos números)
(disminuye el segundo número
\intercambia los números
Aes una variable preinicializada a 10
brealiza una conversión base, haciendo una matriz con los dígitos de base 10 del primer número
=obtiene el deseado elemento de la matriz

El programa es básicamente una traducción de la solución de Peter Taylor.


Yo diría que poner dígitos de base 10 en una matriz es más una operación de cadena que matemática.
Trauma digital


3

J - 15 24 char

Una respuesta suficientemente "matemática".

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

Los mismos resultados que a continuación, pero está dotado de la cualidad mística de ser matemático.


La versión corta, que usa expansión de base 10.

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

Anteponemos un 0 para ajustar la indexación basada en 1.

Uso:

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

2
Las cadenas no están 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

No necesita definirlo como un fn:def f(i,n): ... return d
smci

No es necesario que revise el if n>k: return -1caso.
smci

... y ciertamente no necesita hacer un primer paso solo para contar k (el número de dígitos en i), para poder compararlo con n.
smci

2

C, 50

Esto usa matrices.

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

Solo ignora todas las advertencias.

Y sí, en C, las cadenas son realmente solo matrices, por lo que esto es algo barato.


Más matemática:

C, 83

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

¿No está usando funciones de cadena / matriz?
VX

El primero lo hace, como dice;) El segundo obviamente no, aparte del strlen, que elegí simplemente porque es más corto que usar log. Si ese es un problema, es una solución fácil, puedo agregarlo cuando llegue a casa.
SBI

Ahí vamos, agregó la versión puramente matemática.
SBI

2
Matemáticas, ¡ni una sola vez!
Potzblitz

2

a. C. (impulsado por bash), 41 29

Creo que esta es la primera respuesta para hacer esto matemáticamente y no con cadenas:

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

El uso de length()quizás parece un poco fibroso, pero la página de manual de bc habla sobre el número de dígitos y no la longitud de la cadena:

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

Salida:

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

1
@ kukac67 Agradezco el voto de aceptación! Pero creo que es habitual que las preguntas de código de golf se dejen abiertas más de 2 horas para alentar más respuestas. Quizás una semana más o menos. No me ofenderé si no aceptas esta respuesta :)
Digital Trauma

1
Okay. Dejaré de aceptar entonces. ¡Espero que no ganes! : P
kukac67

1

Mathematica - 24 23

Este es algo obvio :)

IntegerDigits[#][[#2]]&

Ejemplo:

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

Salida:

3

Puede acortarlo codificando dos enteros, p. Ej.

IntegerDigits[n][[m]]

pero luego primero tienes que escribir n = 726433; m = 5;. La llamada a la función se sintió más similar a un programa.


1
Puedes soltar el número 1.
DavidC

Ahora esto es trampa ..: D
kukac67

1

C 145

El programa encuentra la distancia desde el final del número entero y lo divide hasta que se alcanza el índice, luego usa el módulo 10 para obtener el ú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);
}

Esto se puede jugar de manera significativa. Comience con estos consejos
Trauma digital el

Para empezar, los lanzamientos (int) y los parens asociados son innecesarios
Digital Trauma

1
No pude resistirme. Jugamos al golf que se reduce a 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);}.
Trauma digital el

1

Wolfram Alpha - entre 40 y 43

Por supuesto, puedo defender totalmente que usar IntegerDigitses un truco que no está incluido

cualquier función integrada como "nthDigit (x, n)"

Pero debido a que mi respuesta anterior aún parecía hacer trampa un poco, aquí hay una alternativa. Desafortunadamente es un poco más largo, pero no vi cómo acortarlo más de lo que lo hice.

Contando de la misma manera que antes (con el signo y sin pasar ningún argumento),

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

Tiene 43 caracteres. Al negar el exponente y barajar los términos, puedo perder un operador aritmético ( 10^(...)xse interpretará como multiplicación)

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

No tengo a mano Mathematica para probar, dudo que sea lo que sospeché (y fue amablemente verificado por kukac67 ) en Mathematica, esto no es aceptado, pero se ejecuta en WolframAlpha .

Tengo dudas sobre el uso de RealDigits, porque me limité a usar IntegerDigitspara esta respuesta y son bastante similares. Sin embargo, si me permito incluirla (después de todo, no devuelve los números enteros directamente, lo que muchos de ellos no lo son), puedo recortar fuera otros dos personajes:

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

Lo probé en Mathematica, no genera un valor. El carácter 43 uno ouputs esto:Mod[Trunc[57 2^(3 - Trunc[Log[456]/Log[10]])5^Trunc[Log[456]/Log[10]]], 10]
kukac67

Sí, me lo imaginé. Wolfram Alpha es un poco más indulgente en la interpretación de las entradas. Afortunadamente le di el encabezado correcto;)
CompuChip

Pero veo que funciona en WolframAlpha.
kukac67

{edit} Aunque veo que el enlace está roto ... aparentemente no le gustan los [caracteres incluso cuando están codificados. Lo sacaré a través de un acortador de URL. {edit2} Aparentemente W.Alpha tiene uno: cambió el enlace.
CompuChip

1

Tcl (42 bytes, lambda):

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

(49 bytes, función):

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

(83 bytes, si necesitamos aceptar la entrada del shell):

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

¿Como funciona esto?
kukac67

Explicación agregada. Es la forma más obvia de hacerlo matemáticamente. Cómo lo harías en papel.
slebetman

Creo que estás contando desde el lado equivocado.
Peter Taylor

Hmm .. si. Lo parece. Lo revisaré para contar desde la izquierda.
slebetman

Aceptaré los 31 bytes. Aunque, ¿cómo se puede ejecutar la lambda? ¿Tcl tiene un intérprete que pueda usarlo? ¿O solo como parte de un programa que define los argumentos?
kukac67

1

R (60)

Resolvió el problema usando log10 para calcular el número de dígitos. El caso especial x == 0 cuesta 13 caracteres, suspiro.

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

Sin golf:

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 las entradas positivas. Se divide por 10 a la potencia del dígito buscado desde la derecha, luego toma el 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}

Gracias por notar el error en la fórmula anterior. Este es más corto.


¡Me gusta! :)
Votado a

Probamos la solución: k (Array ("1234", "7")) que da 9. ¿No funciona para n> # dígitos (x)?
lambruscoAcido

Esto se debe a que 10 ^ -1 no es exacto en esta notación, por lo que hay un error de redondeo cuando tomas 10% de polvo (10, -1) que debería haber dado cero pero en su lugar dio 0.0999. Corregí mi respuesta para acomodar este efecto secundario.
Mikaël Mayer

1

Haskell, 142

No estoy seguro de haber entendido la pregunta correctamente, pero esto es lo que creo que quería: leer stdin (cadena), hacer los dos números int (no cadena), hacer algunas cosas algorítmicas y luego generar el resultado (cadena). Lo metí en 142 caracteres, que es demasiado:

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

ejemplo 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, sin condiciones, ninguna de ellas. Toma el primer número en la primera solicitud y el segundo número en la segunda solicitud.

Caso de prueba :

Input: 97654 5
Output: 4

Input: 224658 3
Output: 4

Código sin golf:

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   no 30 caracteres

(sin contar el salto de línea)

Esto es posiblemente una trampa debido al cambio de comando, pero gracias por dejarme jugar :-)

~/$ 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 :

Fue capaz de eliminar 2 caracteres:

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

... luego 6 más:

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

Cómo

Dividimos la entrada del primer argumento al script $ARGV[0]por character ( split//) creando una matriz indexada a cero; agregar uno al segundo argumento $ARGV[1]del script corresponde al elemento en esa posición en la cadena o primer argumento. Luego mantenemos la expresión dentro ()como una lista de un elemento que sayiterará. Para la versión corta más corta, solo utilizamos shiftel primer argumento y utilizamos la parte restante de @ARGV para el índice; una vez shifteditado, solo queda el segundo argumento, por lo quepop() lo restamos 1.

¿Se supone que esto es un ejercicio de matemáticas? Me acabo de dar cuenta de que estoy indexando una cadena de lectura de entrada, así que ... ¿supongo que pierdo? Marcarme si tengo sentido en un campo de golf paralelo e intentaré nuevamente, más matemáticamente, en una respuesta separada.

salud,


Sí, lo siento, sin usar cuerdas . Bienvenido a PPCG de todos modos!
Trauma digital

OK lo siento por eso ... hasta ahora mis enfoques matemáticos no son muy dignos de golf :-)
G. Cito

0

PHP, 58

Usar solo matemáticas

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


1
¿No se encuentra esto desde la derecha?
cjfaure

2
Puede guardar 1 carácter cambiándolo a echo$n%10.
Amal Murali

@Trimsty no, en realidad se repite hasta que el número ingresado ya no sea mayor que 10 ^ x, siendo x el número de dígito. Entonces, por ejemplo, si ingresa 3457 como un número y 2 como un dígito, le quitará el último dígito hasta que el número sea menor que 100 (10 ^ 2). Eso significa que eliminará 5 y 7, porque entonces queda 34 y no es mayor que 100. Luego, solo genera el último dígito (4).
dkasipovic

Pero es cierto que si el segundo número es más grande que el número de dígitos, genera 9 y no cero
Mikaël Mayer

Ya veo, genera el último dígito si el número es mayor que el número de dígitos. Si ingresa 1234 y 5to dígito, obtendrá 4, ya que 1234 ya es menor que 10 ^ 5.
dkasipovic

0

~ - ~! - 94 93

Dobla un poco las reglas: es una función que toma n como entrada y supone que el número para encontrar el dígito n se almacena en '''''- y ~ - ~! No admite flotadores.

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

'''''=~~~~,~~,~~,~~,~~,~~:''''''=''''&~:resultará en ''''''ser ~~(2) ('' '' '= 128).


Hm ... ¿Otro lenguaje esotérico más?
VisioN

@VisioN no es realmente esotérico, solo que el único tipo de datos nativo es un número y no puede interactuar con el sistema operativo / internet. esolangs.org/wiki/No_Comment
cjfaure

1
Bueno, para mí cada sintaxis que un ser humano no puede leer fácilmente es esotérica. Y sí, Perl también es esotérico según esta teoría:)
VisioN

@VisioN Se vuelve fácil de leer después de un tiempo. : P
cjfaure

0

Python 2.7 (89 bytes)

Transforme el número entero en un "polinomio" usando una lista de dígitos. Sé que dices que no puedes aceptar eso, pero no veo por qué no, ya que usa el concepto matemático de los números que se representan como polinomios de sus bases. Solo fallará cuando el entero pasado sea 0, pero usted dijo que no había ceros rellenados;)

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]

Ejecutar como test.py:

$ python test.py 726489 5
8

Supongo que quería una entrada de shell y que no podía hacer uso del hecho de que la entrada sería cadenas. Saltar la entrada del shell es de solo 43 bytes, con:

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

Aunque uso algunas iteraciones innecesarias, guardo algunos bytes al no agregar una disminución adicional n.


0

BrainFuck extendido : 49

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

Uso:

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

Ectually no estoy usando ninguna característica especial de EBF excepto el operador de multiplicación (por ejemplo. 10+ => ++++++++++ ). Aparte de eso, es principalmente puro BrainFuck

Cómo 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 (sin espacios en blanco innecesarios)

(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. recortar dígitos por división, comenzando con el máximo posible para int sin signo de 32 bits
  2. cuando tocamos el lado izquierdo del entero, int ($ 1 / d) devuelve un valor distinto de cero
  3. continuar n ($ 2) dígitos más allá de eso

Sin golf:

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

0

Scala (83)

No utiliza ninguna característica especial de Scala. Más bien la solución estándar.

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

Sin golf:

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 por usar matrices.

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]);}

No permití las matrices en una edición (antes de que publicaras esto) ... Pero me gusta cómo hiciste esto. :)
kukac67

OK, no estaba mirando bien. He agregado una solución para evitar matrices.
VX

0

Julia 37

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

Debido al operador incorporado ^. La aritmética de precisión arbitraria permite cualquier tamaño int.

Muestra

julia> d(1231198713987192871,10)
3

0

perl (un poco más mathy / no muy golfista) - 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);

Ejecútalo 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

Aunque dc es inmejorable, aquí hay una solución Smalltalk:

argumentos, n número; d digit-nr para extraer:

[:n :d|(n//(10**((n log:10)ceiling-d)))\\10]
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.