Afficher les nièmes chiffres d'un entier

13

Sans utiliser de chaînes (sauf lorsque cela est nécessaire, comme avec une entrée ou une sortie), calculez le nième chiffre, partir de la gauche , d'un entier (en base 10).

L'entrée sera donnée dans ce format:

726433 5

La sortie doit être:

3

car c'est le cinquième chiffre de "726433".

L'entrée sera ne contiendra pas de zéros non significatifs, par exemple "00223".

Cas de test / autres exemples:

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

C'est le golf de code; moins de caractères gagnent, mais toutes les fonctions intégrées telles que "nthDigit (x, n)" sont ne pas acceptées .

Voici un pseudo-code pour vous aider à démarrer:

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

Comme vous pouvez le voir, je suis nouveau dans le golf de code, et même si je pense qu'il est un peu injuste que je pose une question avant même d'y avoir répondu, j'aimerais vraiment voir quel type de réponses cela génère. :)

Edit : J'espérais des réponses mathématiques, donc je ne peux pas vraiment accepter les réponses qui reposent sur la conversion de chaînes en tableaux ou sur la possibilité d'accéder à des nombres sous forme de liste de chiffres.

Nous avons un gagnant

Écrit en "dc", 12 octets. Par DigitalTrauma .

kukac67
la source
Cela peut-il être juste une fonction ou doit-il avoir besoin de gérer les E / S? S'il n'a pas besoin de gérer les E / S, peut-il simplement s'agir d'un lambda au lieu d'une fonction?
slebetman
Votre modification ne permet pas de savoir exactement ce que vous n'aimez pas. En particulier, avec "pouvoir accéder aux nombres comme une liste de chiffres", est-ce l'utilisation de tableaux sous une forme que vous n'aimez pas, ou simplement l'existence de routines de conversion de base intégrées?
Peter Taylor
@PeterTaylor Les tableaux de chiffres ne sont pas corrects, car on peut facilement saisir le nième élément du tableau. Je ne sais pas exactement comment fonctionne la conversion de base, mais cela semble facile.
kukac67
Pourquoi est-ce un problème de créer une liste de chiffres? C'est très mathématique - cela représente le nombre comme un polynôme.
2rs2ts
@ 2rs2ts Si vous pouvez créer une liste de chiffres mathématiquement, c'est-à-dire sans analyser une chaîne dans un tableau, cela pourrait être acceptable.
kukac67

Réponses:

2

dc , 12 octets

?dZ?-Ar^/A%p

Ceci est une réponse mathématique. Voici comment ça fonctionne:

  • ? lire le numéro d'entrée et pousser pour empiler
  • d dupliquer le haut de la pile
  • Z Fait sortir la valeur de la pile, calcule et pousse le nombre de chiffres
  • ? lire l'index des chiffres et pousser pour empiler
  • - soustraire l'index des chiffres du nombre de chiffres
  • A poussez 10 vers la pile
  • r permuter les 2 premières valeurs sur la pile
  • ^ exponentiate 10 ^ (nombre de chiffres - index des chiffres)
  • / diviser le nombre par le résultat de l'exponentiation
  • A poussez 10 vers la pile
  • % calculer le nombre mod 10 pour obtenir le dernier chiffre et pousser en haut de la pile
  • p sauter et imprimer le haut de la pile

En action:

$ {echo 987654321; écho 1; } | dc ndigit.dc
9
$ {echo 987654321; écho 2; } | dc ndigit.dc
8
$ {echo 987654321; écho 8; } | dc ndigit.dc
2
$ {echo 987654321; écho 9; } | dc ndigit.dc
1
$ 
Traumatisme numérique
la source
1
Je pense que tu es le gagnant. C'est le troisième code le plus court, mais le 2 le plus court utilisé base conversion -> arrays.
kukac67
5

GolfScript (10 octets)

~(\10base=

Cela suppose que l'entrée est une chaîne (par exemple via stdin). S'il s'agit de deux entiers sur la pile, l'initiale ~doit être supprimée, économisant 1 caractère.

Si la conversion de base est considérée comme contraire à la règle des fonctions intégrées, j'ai une alternative à 16 caractères:

~~)\{}{10/}/=10%
Peter Taylor
la source
Votre premier programme avec la conversion de base ne produit le premier chiffre que si vous entrez "0" et le second si vous entrez "1". golfscript.apphb.com/?c=MjcwNiAxCgpcMTBiYXNlPQ%3D%3D
kukac67
@ kukac67, fixe.
Peter Taylor
4

CJam - 7

l~(\Ab=

CJam est un nouveau langage que je développe, similaire à GolfScript - http://sf.net/p/cjam . Voici l'explication:

llit une ligne de l'entrée
~évalue la chaîne (obtenant ainsi les deux nombres)
(décrémente le deuxième nombre
\permute les nombres
Aest une variable préinitialisée à 10
beffectue une conversion de base, faisant un tableau avec les chiffres de base 10 du premier nombre
=obtient le désiré élément du tableau

Le programme est essentiellement une traduction de la solution de Peter Taylor.

aditsu quitte parce que SE est MAL
la source
Je dirais que mettre des chiffres de base 10 dans un tableau est plus une opération de chaîne que mathématique.
Digital Trauma
4

Haskell 60 octets et lisible

nth x n
        | x < (10^n) = mod x 10
        | True = nth (div x 10) n

aucune chaîne impliquée!

*Main> nth 1234567 4
4
Martin Drautzburg
la source
Cela peut être joué à 36
Cristian Lupascu
Wow vous vous êtes battu pour chaque octet. 1 <2 "au lieu de" vrai "- mignon.
Martin Drautzburg
C'est ce que nous faisons ici ...
Cristian Lupascu
3

J - 15 24 caractères

Une réponse suffisamment "mathématique".

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

Mêmes résultats que ci-dessous, mais est doté de la qualité mystique d'être mathématique.


La version courte, utilisant l'expansion base-10.

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

Nous ajoutons un 0 pour ajuster l'indexation basée sur 1.

Usage:

   ({0,10&#.inv)~/ 1234567 3
3
   ({0,10&#.inv)~/ 444494 5
9
algorithmshark
la source
2
Les chaînes ne sont pas autorisées.
0xcaff le
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
Willem
la source
Vous n'avez pas besoin de le définir comme un fn:def f(i,n): ... return d
smci
Vous n'avez pas besoin de vérifier la raison if n>k: return -1.
smci
... et vous n'avez certainement pas besoin de faire un premier passage juste pour compter k (le nombre de chiffres dans i), afin de le comparer à n.
smci
2

C, 50

Cela utilise des tableaux.

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

Ignorez simplement tous les avertissements.

Et oui, en C, les chaînes ne sont vraiment que des tableaux, donc c'est en quelque sorte bon marché.


Plus mathématique:

C, 83

main(int c,char**a){printf("%d",(atoi(a[1])/pow(10,strlen(a[1])-atoi(a[2])))%10);}
SBI
la source
n'est-ce pas en utilisant des fonctions chaîne / tableau?
VX
Le premier le fait, comme il est dit;) Le second ne le fait évidemment pas, à part le strlen, que j'ai choisi simplement parce qu'il est plus court que d'utiliser log. Si c'est un problème, c'est une solution facile, je peux l'ajouter quand je rentre à la maison.
SBI
Voilà, a ajouté la version purement mathématique.
SBI
2
Math - pas même une fois!
Potzblitz
2

bc (entraîné par bash), 41 29

Je pense que c'est la première réponse pour le faire mathématiquement et non avec des chaînes:

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

L'utilisation de length()peut - être semble un peu filandreuse, mais la page de manuel bc parle du nombre de chiffres et non de la longueur de la chaîne:

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

Production:

$ ./ndigits.bc.sh 726433 5
3
$ ./ndigits.bc.sh 9 1
9
$ ./ndigits.bc.sh 0 1
0
$ ./ndigits.bc.sh 444494 5
9
$ ./ndigits.bc.sh 800 2
0
$ 
Traumatisme numérique
la source
1
@ kukac67 J'apprécie le vote d'acceptation! Mais je pense qu'il est habituel de laisser les questions de code-golf ouvertes plus de 2 heures pour encourager plus de réponses. Peut-être une semaine environ. Je ne serai pas offensé si vous refusez cette réponse :)
Digital Trauma
1
D'accord. Je refuserai alors. J'espère que vous ne gagnez pas! : P
kukac67
1

Mathematica - 24 23

Celui-ci est assez évident :)

IntegerDigits[#][[#2]]&

Exemple:

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

Production:

3

Vous pouvez le raccourcir en codant en dur deux entiers, par exemple

IntegerDigits[n][[m]]

mais il faut d'abord écrire n = 726433; m = 5;. L'appel de fonction ressemblait plus à un programme.

CompuChip
la source
1
Vous pouvez laisser tomber le nombre 1.
DavidC
Maintenant, c'est de la triche ..: D
kukac67
1

C 145

Le programme trouve la distance de la fin de l'entier et divise jusqu'à ce que l'indice soit atteint, puis utilise le module 10 pour obtenir le dernier chiffre.

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);
}
bacchusbeale
la source
Cela peut être joué de manière significative. Commencez avec ces conseils
Digital Trauma
Pour commencer, les moulages (int) et les parenthèses associées ne sont pas nécessaires
Digital Trauma
1
Je n'ai pas pu résister. Je vers le bas à joué au golf 87 caractères: 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 et 43

Bien sûr, je peux totalement défendre que l'utilisation IntegerDigitsest une astuce qui ne relève pas

toutes les fonctions intégrées telles que "nthDigit (x, n)"

Mais parce que ma réponse précédente avait toujours envie de tricher un peu, voici une alternative. Malheureusement, c'est un peu plus long, mais je n'ai pas vu comment le raccourcir plus que moi.

Compter de la même manière que précédemment (avec l'esperluette, sans passer d'arguments),

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

a 43 caractères. En niant l'exposant et en mélangeant les termes autour, je peux perdre un opérateur arithmétique ( 10^(...)xsera interprété comme une multiplication)

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

Je n'ai pas Mathematica à portée de main pour tester, je doute que ce sera comme je le soupçonnais (et comme l'a aimablement vérifié par kukac67 ) en Mathematica cela n'est pas accepté, mais il fonctionne dans WolframAlpha .

Je doute de l'utilisation de RealDigits, car je me suis limité à utiliser IntegerDigitspour cette réponse et ils sont assez similaires. Cependant, si je me permets de l' inclure (après tout, il ne retourne pas les entiers directement, à quel point nombre d'entre eux il y a), je peux réduire de deux autres personnages:

Mod[Trunc[10^(#2-RealDigits[#]-1)#],10]&
CompuChip
la source
Je l'ai essayé dans Mathematica, il ne produit pas de valeur. Le 43 caractère on outes ceci:Mod[Trunc[57 2^(3 - Trunc[Log[456]/Log[10]])5^Trunc[Log[456]/Log[10]]], 10]
kukac67
Ouais, je pensais autant. Wolfram Alpha est un peu plus indulgent dans l'interprétation des entrées. Heureusement, je lui ai donné la bonne tête;)
CompuChip
Mais je vois que cela fonctionne sur WolframAlpha.
kukac67
{edit} Bien que je vois que le lien est rompu ... n'aime apparemment pas les [caractères même lorsqu'ils sont encodés. Je vais le passer à travers un raccourcisseur d'URL. {edit2} Apparemment W.Alpha en a un - a changé le lien.
CompuChip
1

Tcl (42 octets, lambda):

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

(49 octets, fonction):

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

(83 octets, si nous devons accepter l'entrée du shell):

puts [expr [lindex $argv 0]/10**int(log10([lindex $argv 0])+1-[lindex $argv 1])%10]
Slebetman
la source
Comment cela marche-t-il?
kukac67
Added explanation. It's just the most obvious way to do it mathematically. How you'd do it on paper.
slebetman
I think you're counting from the wrong end.
Peter Taylor
Hmm.. yeah. Looks like it. I'll revise it to count form the left.
slebetman
I'll accept the 31 bytes. Though how can the lambda be run? Does Tcl have an interpreter which can use it? Or only as part of a program which defines the arguments?
kukac67
1

R (60)

Solved the problem using log10 to calculate the number of digits. The special case x==0 costs 13 character, sigh.

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

Usage

> f(898,2)
[1] 9
lambruscoAcido
la source
1

Scala (133 99 bytes):

Works for all positive inputs. Divides by 10 to the power of the digit looked for from the right, then takes it modulo 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}

Thank you for noticing the bug in the previous formula. This one is shorter.

Mikaël Mayer
la source
I like it! :) Up-voted
kukac67
Tested the solution: k(Array("1234", "7")) which gives 9. Does it not work for n > #digits(x) ?
lambruscoAcido
It's because 10^-1 is not exact in this notation, so there is a rounding error when you take 10%pow(10,-1) which should have given zero but gave 0.0999 instead. Corrected my answer to accomodate this side-effect.
Mikaël Mayer
1

Haskell, 142

I'm not sure I understood the question correctly, but this is what I think you wanted: read stdin (string), make the two numbers int (not string), do some algorithmic things, and then output the result (string). I crammed it into 142 chars, which is way too much:

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

example usage:

> echo 96594 4 | getIndex
9
Flonk
la source
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)

Purely mathematical, no strings, none of them. Takes the first number in the first prompt and the second number in the second prompt.

Test Case:

Input: 97654 5
Output: 4

Input: 224658 3
Output: 4

Ungolfed Code:

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
Gaurang Tandon
la source
1

perl, 38, 36   no 30 characters

(not counting the linefeed)

This is arguably cheating due to the command switch, but thanks for letting me play :-)

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

edit:

Was able to remove 2 characters:

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

... then 6 more:

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

How

We split the input of the first argument to the script $ARGV[0] by character (split//) creating an zero indexed array; adding one to the second argument $ARGV[1] to the script then corresponds to the element at that position in the string or first argument. We then hold the expression inside () as a one element list which say will iterate through. For the shorter short version we just shift in the first argument and use the remaining part of @ARGV to use for the index - once shifted only the second argument remains so we pop() it and subtract 1.

Is this supposed to be a math exercise? I just realized I'm indexing a string read from input, so ... I guess I lose?? Mark me up if I make sense in parallel golf course and I will try again - more mathematically - in a separate answer.

cheers,

G. Cito
la source
Yup, sorry, Without using strings. Welcome to PPCG anyway!
Digital Trauma
OK sorry 'bout that ... so far my mathematical approaches are not very golf-worthy :-)
G. Cito
0

PHP, 58

Using math only

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

dkasipovic
la source
1
Doesn't this find from the right?
cjfaure
2
You can save 1 char by changing it to echo$n%10.
Amal Murali
@Trimsty no, it actually loops until entered number is no longer bigger than 10^x, x being the digit number. So, for example, if you enter 3457 as a number and 2 as a digit, it will take away the last digit until the number becomes smaller than 100 (10^2). That means it will take away 5 and 7, because then 34 remains and it is not bigger than 100. Then it just outputs the last digit (4).
dkasipovic
But it is true that if the second number is bigger than the number of digits, you output 9 and not zero
Mikaël Mayer
I see, it outputs last digit if the number if bigger than the number of digits. If you enter 1234 and 5th digit, you will get 4 since 1234 i already less than 10^5.
dkasipovic
0

~-~! - 94 93

Bends the rules a bit - it's a function that takes n as input and assumes the number to find digit n of is stored in ''''' - and ~-~! doesn't support floats.

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

'''''=~~~~,~~,~~,~~,~~,~~:''''''=''''&~: will result in '''''' being ~~ (2) (''''' = 128).

cjfaure
la source
Hm... Yet another esoteric language?
VisioN
@VisioN it isn't really esoteric, just that the only native data type is a number and it can't interact with the os/internet. esolangs.org/wiki/No_Comment
cjfaure
1
Well, to me every syntax that can't be easily read by a human being is esoteric. And yes, Perl is also esoteric according to this theory :)
VisioN
@VisioN It gets easy to read after a while. :P
cjfaure
0

Python 2.7 (89 bytes)

I transform the integer into a "polynomial" by using a list of digits. I know you say you can't accept that, but I don't see why not since it uses the mathematical concept of numbers being represented as polynomials of their bases. It will only fail when the integer passed in is 0, but you said no padded zeroes ;)

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]

Run as test.py:

$ python test.py 726489 5
8

I assume you wanted shell input and that I couldn't make use of the fact that the input would be strings. Skipping shell input it's just 43 bytes, with:

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

Although I use some unnecessary iteration, I save some bytes by not adding an additional decrement on n.

2rs2ts
la source
0

Extended BrainFuck: 49

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

Usage:

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

I'm not ectually using any special features of EBF except the multiplication operator (eg. 10+ => ++++++++++). Other than that it's mostly pure BrainFuck

How it works:

+                ; 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

Scheme (R6RS): 100 (without unnecessary whitespace)

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

awk - 53

{for(d=10^9;!int($1/d)||--$2;d/=10);$0=int($1/d)%10}1
  1. trim digits by division, starting with max possible for 32 bit unsigned int
  2. when we hit the left side of the integer, int($1 / d) returns non-zero
  3. continue n ($2) digits past that

Ungolfed:

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

Scala (83)

Does not use any Scala special features. Rather the standard solution.

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 
lambruscoAcido
la source
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, invalid because of using arrays.

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]);}
V-X
la source
I disallowed arrays in a edit (before you posted this)... But I like how you did this. :)
kukac67
OK, I wasn't looking properly. I've added a solution avoiding arrays.
V-X
0

Julia 37

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

Owing to the builtin ^ operator. Arbitrary precision arithmetic allows for any size int.

Sample

julia> d(1231198713987192871,10)
3
waTeim
la source
0

perl (slightly more mathy/not very golfy) - 99 chars

 ~/$ 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);

Run it as:

 perl -M5.010 -MPOSIX=floor ndigits.pl 726433 1
G. Cito
la source
0

Perl6 - 85 chars

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

Smalltalk, 44

Although dc is unbeatable, here is a Smalltalk solution:

arguments, n number; d digit-nr to extract:

[:n :d|(n//(10**((n log:10)ceiling-d)))\\10]
blabla999
la source