Виведіть n-й цифри цілого числа


13

Не використовуючи рядки (за винятком випадків, коли це необхідно, наприклад, із введенням або виведенням), обчисліть n-ю цифру зліва з цілого числа (в базі 10).

Введення буде надано у такому форматі:

726433 5

Вихід повинен бути:

3

як це п'ята цифра "726433".

Введення не буде містити провідні нулі, наприклад, "00223".

Тестові приклади / подальші приклади:

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

Це код гольфу; виграє найменша кількість символів, але будь-які вбудовані функції, такі як "nthDigit (x, n)" ", неприйнятні .

Ось кілька псевдокодів для початку роботи:

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

Як ви бачите, я новачок у коді гольфу, і хоча я думаю, що це трохи несправедливо, що я задаю питання, перш ніж я навіть відповів на нього, я дуже хотів би побачити, які відповіді це породжує. :)

Редагувати : Я сподівався на математичні відповіді, тому я не можу реально приймати відповіді, які покладаються на перетворення рядків у масиви чи можливість доступу до чисел у списку цифр.

У нас є переможець

Написано "dc", 12 байт. За допомогою DigitalTrauma .


Це може бути лише функцією або вона повинна працювати для вводу / виводу? Якщо йому не потрібно обробляти введення-виведення, чи може це просто лямбда замість функції?
slebetman

Ваша редакція залишає незрозумілим, що саме вам не подобається. Зокрема, з "можливістю доступу до чисел як списку цифр", чи це використання масивів у будь-якій формі, яка вам не подобається, чи просто наявність вбудованої базової програми перетворення?
Пітер Тейлор

@PeterTaylor Масиви цифр не в порядку, оскільки можна легко просто схопити n-й елемент у масиві. Я не впевнений, як саме працює конверсія бази, але це здається легко.
kukac67

Чому проблема складання списку цифр? Це дуже математично - воно представляє число як многочлен.
2rs2ts

@ 2rs2ts Якщо ви можете створити список цифр математично, тобто без розбору рядка в масив, то це може бути прийнятним.
kukac67

Відповіді:


2

DC , 12 байт

?dZ?-Ar^/A%p

Це математична відповідь. Ось як це працює:

  • ? прочитати вхідний номер і натиснути на стек
  • d дублікат верхньої частини стека
  • Z Спливає значення зі стека, обчислює та висуває кількість цифр
  • ? прочитати індекс і натиснути на стек
  • - відняти цифрний індекс від числа цифр
  • A натисніть 10 до стека
  • r поміняйте топ-2 значень у стеці
  • ^ показник 10 ^ (число цифр - цифрний індекс)
  • / ділити число за результатом експоненції
  • A натисніть 10 до стека
  • % обчисліть число мод 10, щоб отримати останню цифру, і натисніть на верхню частину стека
  • p вискочити та надрукувати верхню частину стека

Дія:

$ {відлуння 987654321; відлуння 1; } | dc ndigit.dc
9
$ {відлуння 987654321; відлуння 2; } | dc ndigit.dc
8
$ {відлуння 987654321; відлуння 8; } | dc ndigit.dc
2
$ {відлуння 987654321; відлуння 9; } | dc ndigit.dc
1
$ 

1
Я думаю, ти переможець. Це третій найкоротший код, але найкоротший 2 використаний base conversion -> arrays.
kukac67

5

GolfScript (10 байт)

~(\10base=

Це передбачає, що введення є як рядок (наприклад, через stdin). Якщо це два цілі числа у стеці, початкове ~слід видалити, зберігаючи 1 char.

Якщо базове перетворення вважається невдалим правилом вбудованих функцій, у мене є альтернатива 16 знаків:

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

Ваша перша програма з базовим перетворенням виводить першу цифру, лише якщо ви введете "0", а другу, якщо ви введете "1". golfscript.apphb.com/?c=MjcwNiAxCgpcMTBiYXNlPQ%3D%3D
kukac67

@ kukac67, виправлено.
Пітер Тейлор

4

CJam - 7

l~(\Ab=

CJam - це нова мова, яку я розробляю, схожа на GolfScript - http://sf.net/p/cjam . Ось пояснення:

lчитає рядок із вхідного сигналу,
~оцінює рядок (отримуючи таким чином два числа)
(декременти, друге число
\заміняє числа
A- це змінна, попередньо ініціалізована на 10
bробить базове перетворення, що робить масив з базовими 10 цифрами першого числа
=отримує потрібне елемент масиву

Програма - це в основному переклад рішення Пітера Тейлора.


Я б заперечував, що введення масиву 10 цифр у масив - це більше рядкова операція, ніж математична.
Цифрова травма

4

Haskell 60 байт і читабельний

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

жодних струн не задіяно!

*Main> nth 1234567 4
4


Нічого, ти боровся за кожен байт. 1 <2 "замість" справжній "- милий.
Мартін Драйтцбург


3

J - 15 24 char

Досить «математична відповідь».

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

Ті ж результати, що і нижче, але наділені містичною якістю математики.


Коротка версія, що використовує розширення base-10.

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

Ми додаємо 0, щоб скоригуватися для індексації на основі 1.

Використання:

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

2
Строки заборонені.
0xcaff

2

Пітон 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

Не потрібно визначати це як fn:def f(i,n): ... return d
smci

Вам не потрібно перевіряти if n>k: return -1справу.
smci

... і вам, звичайно, не потрібно робити перший прохід просто для підрахунку k (кількість цифр в i), щоб обгрунтувати його - порівняти його з n.
smci

2

C, 50

Для цього використовуються масиви.

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

Просто ігноруйте всі попередження.

І так, у C рядки справді є просто масивами, тому це щось дешево.


Більше математичних:

С, 83

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

чи не використовує це рядок / функції масиву?
VX

Перший робить, як це каже;) Другий, очевидно, не робить, крім strlen, який я вибрав просто тому, що він коротший, ніж використання журналу. Якщо це проблема, це легко вирішити, я можу додати її, коли повернусь додому.
SBI

Там ми йдемо, додавши чисто математичну версію.
SBI

2
Математика - не один раз!
Potzblitz

2

bc (керований bash), 41 29

Я думаю, що це перша відповідь зробити це математично, а не рядками:

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

Використання, length()можливо, здається дещо складним, але сторінка bc man говорить про кількість цифр, а не про довжину рядка:

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

Вихід:

$ ./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 Я вдячний за прийняття! Але я вважаю, що для кодових питань із гольфу зазвичай залишається відкритим більше 2 годин, щоб заохочувати більше відповідей. Можливо, тиждень або близько того. Я не ображаюся, якщо ви приймете цю відповідь :)
Digital Trauma

1
добре. Я згодом прийму. Сподіваюся, ви не виграєте! : P
kukac67

1

Математика - 24 23

Цей вид очевидний :)

IntegerDigits[#][[#2]]&

Приклад:

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

Вихід:

3

Ви можете скоротити її за допомогою жорсткого кодування двох цілих чисел, наприклад

IntegerDigits[n][[m]]

але тоді спочатку треба писати n = 726433; m = 5;. Виклик функції виглядав більш схожим на програму.


1
Можна скинути число 1.
DavidC

Тепер це обман ..: D
kukac67

1

C 145

Програма знаходить відстань від кінця цілого числа і ділиться до досягнення індексу, тоді використовує модуль 10 для отримання останньої цифри.

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

Це може бути значно гольф. Почніть з цих порад
Digital Trauma

Для початку (int) касти та пов’язані з ними паролі непотрібні
Digital Trauma

1
Я не втримався. Я golfed його до 87 символів: i,a;main(){scanf("%d%d",&i,&a);for(a=log(i)/log(10)+1-a;a--;)i/=10;printf("%d",i%10);}.
Цифрова травма

1

Вольфрам Альфа - від 40 до 43 років

Звичайно, я можу повністю захищати, що використання IntegerDigits- це хитрість, яка не підпадає

будь-які вбудовані функції, такі як "nthDigit (x, n)"

Але оскільки моя попередня відповідь все ж відчувала, як трохи обманюю, ось альтернатива. На жаль, це зовсім трохи довше, але я не бачив, як його скоротити більше, ніж я.

Підрахунок аналогічно, як і раніше (з амперсандом, не передаючи жодних аргументів),

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

має 43 символи. Заперечуючи показник і перемішуючи умови навколо, я можу втратити одного арифметичного оператора ( 10^(...)xбуде трактуватися як множення)

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

У мене немає математики під рукою для тестування, я сумніваюся, що це буде Як я підозрював (і як це люб’язно перевірив kukac67 ) у Mathematica це не прийнято, але воно працює у WolframAlpha .

Я сумніваюся у використанні RealDigits, тому що я обмежив себе у використанні IntegerDigitsдля цієї відповіді, і вони досить схожі. Однак, якщо я дозволю собі включити його ( в кінці кінців, він не повертає цілі числа безпосередньо, так як багато з них є), я можу скоротити від ще два символи:

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

Я спробував це в Mathematica, воно не виводить значення. 43 персонажа витісняють це:Mod[Trunc[57 2^(3 - Trunc[Log[456]/Log[10]])5^Trunc[Log[456]/Log[10]]], 10]
kukac67

Так, я зрозумів стільки ж. Вольфрам Альфа трохи поблажливіший у тлумаченні введення. На щастя, я дав йому правильний заголовок;)
CompuChip

Але я бачу, що це працює на WolframAlpha.
kukac67

{edit} Хоча я бачу, що посилання розірвано ... мабуть, не подобаються [символи, навіть коли вони закодовані. Я проведу це через коротший URL-адрес. {edit2} Мабуть, W.Alpha має один - змінив посилання.
CompuChip

1

Tcl (42 байт, лямбда):

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

(49 байт, функція):

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

(83 байти, якщо нам потрібно прийняти введення з оболонки):

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

Як це працює?
kukac67

Додано пояснення. Це просто найочевидніший спосіб зробити це математично. Як би це зробити на папері.
slebetman

Я думаю, ти рахуєш з неправильного кінця.
Пітер Тейлор

Хм .. так. Виглядає так. Я перегляну його, щоб порахувати форму зліва.
slebetman

Я прийму 31 байт. Хоча як можна запускати лямбда? Чи є Tcl перекладач, який може ним користуватися? Або лише як частина програми, яка визначає аргументи?
kukac67

1

R (60)

Вирішено проблему за допомогою log10 для обчислення кількості цифр. Окремий випадок x == 0 коштує 13 символів, зітхання.

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

Безголівки:

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

Використання

> f(898,2)
[1] 9

1

Scala ( 133 99 байт):

Працює для всіх позитивних входів. Ділиться на 10 на потужність цифри, яку шукали праворуч, потім приймає її за модулем 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}

Дякуємо, що помітили помилку в попередній формулі. Цей коротший.


Мені це подобається! :) Оголошено
kukac67

Тестоване рішення: k (масив ("1234", "7")), який дає 9. Чи не працює він для n> #digits (x)?
lambruscoAcido

Це тому, що 10 ^ -1 не є точним у цій нотації, тому виникає помилка округлення, коли ви берете 10% pow (10, -1), який повинен був дати нуль, але дав 0,0999 замість цього. Виправили свою відповідь, щоб відповідати цьому побічному ефекту.
Mikaël Mayer

1

Хаскелл, 142

Я не впевнений, що правильно зрозумів це питання, але я думаю, що ви цього хотіли: прочитайте stdin (рядок), зробіть два числа int (не рядок), зробіть деякі алгоритмічні речі, а потім виведіть результат (рядок). Я забила це на 142 символи, що дуже багато:

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

Приклад використання:

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

Чисто математичний, без рядків, жодна з них. Бере перший номер у першому підказці, а другий - у другому.

Тестовий випадок :

Input: 97654 5
Output: 4

Input: 224658 3
Output: 4

Код без вогню:

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

перл, 38, 36   ні 30 символів

(без урахування подачі рядків)

Це, мабуть, обман через командний перемикач, але дякую, що дозволили мені грати :-)

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

редагувати :

Вдалося видалити 2 символи:

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

... потім ще 6:

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

Як

Ми розділили вхід першого аргументу до сценарію $ARGV[0]по символу ( split//), створивши масив з індексом нуля; додавання одного до другого аргументу $ARGV[1]до сценарію, то відповідає елементу в цій позиції в рядку або першому аргументі. Потім ми тримаємо вираз всередині, ()як єдиний список елементів, який sayбуде повторюватися. Для коротшої короткої версії ми просто shiftв першому аргументі, а решту частину @ARGV використовуємо для використання в індексі - після shiftредагування залишається лише другий аргумент, тому ми pop()його і віднімаємо 1.

Це має бути математичною вправою? Я щойно зрозумів, що я індексує рядок, прочитану з вхідних даних, так що ... я думаю, я програю ?? Позначте мене, якщо я маю сенс на паралельному полі для гольфу, і я спробую ще раз - більш математично - в окремій відповіді.

ура,


Так, вибачте, без використання рядків . Ласкаво просимо до PPCG!
Цифрова травма

Добре вибачте, але що ... поки що мої математичні підходи не дуже варті гольфу :-)
G. Cito

0

PHP, 58

Використовуючи лише математику

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


1
Це не знаходить справа?
cjfaure

2
Ви можете зберегти 1 char, змінивши його на echo$n%10.
Амаль Муралі

@Тримст ні, воно фактично циклічне, поки введене число не перевищує 10 ^ х, x є цифрою цифри. Так, наприклад, якщо ви введете 3457 як число, а 2 - як цифра, це забиратиме останню цифру, поки число не стане менше 100 (10 ^ 2). Це означає, що це забирає 5 і 7, тому що тоді залишається 34 і не більше 100. Тоді він просто виводить останню цифру (4).
dkasipovic

Але це правда, що якщо друге число більше, ніж кількість цифр, ви виводите 9, а не нуль
Mikaël Mayer

Я бачу, він видає останню цифру, якщо число, якщо більше, ніж кількість цифр. Якщо ви введете 1234 і п'яту цифру, ви отримаєте 4 з 1234 i вже менше 10 ^ 5.
dkasipovic

0

~ - ~! - 94 93

Трохи згинає правила - це функція, яка приймає n як вхід і передбачає, що число, для знаходження цифри n зберігається в '''''- і ~ - ~! не підтримує поплавці.

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

'''''=~~~~,~~,~~,~~,~~,~~:''''''=''''&~:призведе до ''''''бути ~~(2) ( '' '' »= 128).


Гм ... Ще одна езотерична мова?
VisioN

@VisioN це насправді не езотерика, лише те, що єдиним типом даних є номер, і він не може взаємодіяти з ОС / Інтернетом. esolangs.org/wiki/No_Comment
cjfaure

1
Ну, для мене кожен синтаксис, який не може бути легко прочитаний людиною, є езотеричним. І так, Perl також езотеричний за цією теорією:)
VisioN

@VisioN Через деякий час його легко читати. : P
cjfaure

0

Python 2.7 (89 байт)

Я перетворюю ціле число в "многочлен", використовуючи список цифр. Я знаю, ви говорите, що ви не можете цього прийняти, але я не розумію, чому б ні, оскільки він використовує математичну концепцію чисел, представлених як поліноми їх бази. Він вийде з ладу лише тоді, коли передане ціле число є 0, але ви сказали, що немає прокладених нулів;)

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]

Виконувати як test.py:

$ python test.py 726489 5
8

Я припускаю, що ви хотіли ввести оболонку і що я не міг використати той факт, що вхід буде рядками. Пропускаючи введення оболонки, це всього 43 байти, з:

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

Хоча я використовую деякі непотрібні ітерації, я зберігаю деякі байти, не додаючи додатковий декремент n.


0

Розширений BrainFuck : 49

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

Використання:

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

Я фактично не використовую жодних особливих функцій EBF, за винятком оператора множення (наприклад, 10+ => ++++++++++). Крім цього, це в основному чистий BrainFuck

Як це працює:

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

Схема (R6RS): 100 (без зайвого пробілу)

(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. обрізання цифр діленням, починаючи з максимуму, можливого для 32-бітного неподписаного int
  2. коли ми потрапимо на ліву частину цілого числа, int ($ 1 / д) повертається не нульовим
  3. продовжуйте n ($ 2) цифр, що минули це

Безголівки:

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

0

Скала (83)

Не використовує жодних спеціальних функцій Scala. Швидше стандартне рішення.

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

Безголівки:

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

0

С, 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, недійсний через використання масивів.

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

Я заборонив масиви в редагуванні (перед тим, як ви це опублікували) ... Але мені подобається, як ви це зробили. :)
kukac67

Гаразд, я не виглядав належним чином. Я додав рішення, уникаючи масивів.
VX

0

Юлія 37

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

Завдяки вбудованому ^ оператору. Довільна арифметика точності дозволяє використовувати будь-який розмір int.

Зразок

julia> d(1231198713987192871,10)
3

0

perl (трохи більше матовий / не дуже гофрований) - 99 символів

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

Виконайте це як:

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

0

Perl6 - 85 символів

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

0

Малий розмову, 44

Хоча постійний струм є неперевершеним, ось рішення Smalltalk:

аргументи, n число; d цифра-nr для вилучення:

[:n :d|(n//(10**((n log:10)ceiling-d)))\\10]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.