Emette l'ennesima cifra di un numero intero


13

Senza usare stringhe (tranne quando necessario, come ad esempio con input o output) calcola l'ennesima cifra, da sinistra , di un numero intero (in base 10).

L'input verrà fornito in questo formato:

726433 5

L'output dovrebbe essere:

3

poiché questa è la quinta cifra di "726433".

L'input non conterrà zeri iniziali, ad es. "00223".

Casi di prova / altri esempi:

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

Questo è il codice golf; vince il minor numero di caratteri, ma qualsiasi funzione integrata come "nthDigit (x, n)" non è accettabile .

Ecco alcuni pseudo-codice per iniziare:

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

Come puoi vedere sono nuovo nel campo del golf, e anche se penso che sia un po 'ingiusto porre una domanda prima ancora di averne risposto, mi piacerebbe davvero vedere che tipo di risposte genera. :)

Modifica : speravo in risposte matematiche, quindi non posso davvero accettare risposte che si basano sulla conversione di stringhe in array o sulla possibilità di accedere ai numeri come un elenco di cifre.

Abbiamo un vincitore

Scritto in "dc", 12 byte. Di DigitalTrauma .


Può essere solo una funzione o deve essere necessario gestire l'I / O? Se non è necessario gestire l'I / O, può essere semplicemente una lambda anziché una funzione?
slebetman,

La tua modifica non ti chiarisce esattamente cosa non ti piace. In particolare, con "essere in grado di accedere ai numeri come un elenco di cifre", è l'uso di array in qualsiasi forma che non ti piace o semplicemente l'esistenza di routine di conversione di base integrate?
Peter Taylor,

@PeterTaylor Le matrici di cifre non sono OK, in quanto si può facilmente prendere l'ennesimo elemento dell'array. Non sono sicuro di come funzioni esattamente la conversione di base, ma sembra facile.
kukac67,

Perché è un problema costruire un elenco di cifre? Questo è altamente matematico: rappresenta il numero come un polinomio.
ore 2

@ 2rs2ts Se è possibile creare un elenco di cifre matematicamente, ovvero senza analizzare una stringa in un array, potrebbe essere accettabile.
kukac67,

Risposte:


2

dc , 12 byte

?dZ?-Ar^/A%p

Questa è una risposta matematica. Ecco come funziona:

  • ? leggere il numero di input e premere per impilare
  • d cima duplicata dello stack
  • Z Elimina il valore dallo stack, calcola e invia il numero di cifre
  • ? leggere l'indice delle cifre e spingere per impilare
  • - sottrai l'indice delle cifre dal conteggio delle cifre
  • A spingere 10 nello stack
  • r scambia i primi 2 valori in pila
  • ^ esponente 10 ^ (conteggio cifre - indice cifre)
  • / dividere il numero per risultato di esponenziazione
  • A spingere 10 nello stack
  • % calcola il numero mod 10 per ottenere l'ultima cifra e spingi in cima allo stack
  • p pop e stampa la parte superiore dello stack

In azione:

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

1
Penso che tu sia il vincitore. Questo è il terzo codice più breve, ma il 2 più corto utilizzato base conversion -> arrays.
kukac67,

5

GolfScript (10 byte)

~(\10base=

Ciò presuppone che l'input sia una stringa (ad es. Tramite stdin). Se è come due numeri interi nello stack, l'iniziale ~dovrebbe essere rimosso, salvando 1 carattere.

Se la conversione di base viene considerata come fallo della regola delle funzioni integrate, ho un'alternativa di 16 caratteri:

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

Il primo programma con la conversione di base genera la prima cifra solo se si inserisce "0" e la seconda se si immette "1". golfscript.apphb.com/?c=MjcwNiAxCgpcMTBiYXNlPQ%3D%3D
kukac67

@ kukac67, risolto.
Peter Taylor,

4

CJam - 7

l~(\Ab=

CJam è un nuovo linguaggio che sto sviluppando, simile a GolfScript - http://sf.net/p/cjam . Ecco la spiegazione:

llegge una riga dall'input
~valuta la stringa (ottenendo così i due numeri)
(decrementa il secondo numero
\scambia i numeri
Aè una variabile preinizializzata a 10
bfa una conversione di base, facendo un array con le cifre di base 10 del primo numero
=ottiene il desiderato elemento dell'array

Il programma è sostanzialmente una traduzione della soluzione di Peter Taylor.


Direi che inserire 10 cifre di base in un array è più un'operazione di stringa che matematica.
Trauma digitale


3

J - 15 24 caratteri

Una risposta sufficientemente "matematica".

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

Stessi risultati di seguito, ma è dotato della mistica qualità di essere matematico.


La versione breve, usando l'espansione base-10.

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

Anticipiamo uno 0 per regolare l'indicizzazione in base 1.

Uso:

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

2
Le stringhe non sono consentite.
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

Non è necessario definirlo come fn:def f(i,n): ... return d
smci

Non è necessario controllare la sanità mentale del if n>k: return -1caso.
smci,

... e certamente non è necessario effettuare un primo passaggio solo per contare k (il numero di cifre in i), al fine di confrontarlo con n.
smci,

2

C, 50

Questo utilizza array.

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

Ignora tutti gli avvisi.

E sì, in C, le stringhe sono in realtà solo array, quindi è un po 'economico.


Più matematico:

C, 83

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

non sta usando le funzioni stringa / matrice?
VX

Il primo lo fa, come si dice;) Il secondo ovviamente no, a parte lo strlen, che ho scelto semplicemente perché è più corto dell'uso del log. Se questo è un problema, è una soluzione semplice, posso aggiungerlo quando torno a casa.
SBI

Eccoci, ha aggiunto la versione puramente matematica.
SBI

2
Matematica - nemmeno una volta!
Potzblitz,

2

bc (guidato da bash), 41 29

Penso che questa sia la prima risposta a farlo matematicamente e non con le stringhe:

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

L'uso di length()forse sembra un po 'filante, ma la pagina man di bc parla del numero di cifre e non della lunghezza della stringa:

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

Produzione:

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

1
@ kukac67 Apprezzo il voto di accettazione! Ma penso che sia consuetudine lasciare aperte le domande di code-golf più di 2 ore per incoraggiare più risposte. Forse una settimana o giù di lì. Non mi offenderò se non accetterai questa risposta :)
Digital Trauma

1
ok. Deselezionerò quindi. Spero che tu non vinca! : P
kukac67,

1

Mathematica - 24 23

Questo è abbastanza ovvio :)

IntegerDigits[#][[#2]]&

Esempio:

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

Produzione:

3

Puoi accorciarlo codificando due numeri interi, ad es

IntegerDigits[n][[m]]

ma poi devi prima scrivere n = 726433; m = 5;. La chiamata di funzione sembrava più simile a un programma.


1
Puoi rilasciare il numero 1.
DavidC

Ora questo è barare ..: D
kukac67

1

C 145

Il programma trova la distanza dalla fine del numero intero e si divide fino al raggiungimento dell'indice, quindi utilizza il modulo 10 per ottenere l'ultima cifra.

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

Questo può essere giocato a golf in modo significativo. Inizia con questi suggerimenti
Digital Trauma,

Per cominciare, i cast (int) e le parentesi associate non sono necessari
Digital Trauma

1
Non ho resistito. Ho giocato a golf in giù a 87 caratteri: i,a;main(){scanf("%d%d",&i,&a);for(a=log(i)/log(10)+1-a;a--;)i/=10;printf("%d",i%10);}.
Trauma digitale

1

Wolfram Alpha - tra 40 e 43

Certo, posso difendere totalmente che l'uso IntegerDigitsè un trucco che non rientra

qualsiasi funzione integrata come "nthDigit (x, n)"

Ma poiché la mia risposta precedente aveva ancora voglia di barare, ecco un'alternativa. Sfortunatamente è un po 'più lungo, ma non ho visto come accorciarlo più di me.

Contando in un modo simile a prima (con la e commerciale, senza passare in alcun argomento),

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

ha 43 caratteri. Negando l'esponente e mescolando i termini, posso perdere un operatore aritmetico ( 10^(...)xverrà interpretato come moltiplicazione)

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

Non ho Mathematica a portata di mano per testare, dubito che sarà come sospettavo (e come è stato gentilmente verificato da kukac67 ) in Mathematica questo non è accettato, ma funziona in WolframAlpha .

Sono in dubbio sull'uso di RealDigits, perché mi sono limitato a utilizzare IntegerDigitsper questa risposta e sono abbastanza simili. Tuttavia, se mi permetto di includerlo (dopo tutto, non restituisce i numeri interi direttamente, proprio come molti di loro ci sono), io posso tagliare fuori altri due personaggi:

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

L'ho provato in Mathematica, non genera un valore. Il personaggio di 43 uno lo Mod[Trunc[57 2^(3 - Trunc[Log[456]/Log[10]])5^Trunc[Log[456]/Log[10]]], 10]
rivela

Sì, ho pensato tanto. Wolfram Alpha è un po 'più indulgente nell'interpretazione dell'input. Per fortuna gli ho dato l'intestazione corretta;)
CompuChip

Ma vedo che funziona su WolframAlpha.
kukac67,

{edit} Anche se vedo che il collegamento è interrotto ... a quanto pare non piacciono i [personaggi anche quando sono codificati. Lo tirerò attraverso un accorciatore di URL. {edit2} Apparentemente W.Alpha ne ha uno: ha cambiato il collegamento.
CompuChip

1

Tcl (42 byte, lambda):

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

(49 byte, funzione):

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

(83 byte, se dobbiamo accettare l'input dalla shell):

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

How does this work?
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

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.


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

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

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,


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;


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).


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.


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)))

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

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 

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

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

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

0

Perl6 - 85 chars

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

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]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.