Выведите 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

постоянный ток , 12 байт

?dZ?-Ar^/A%p

Это математический ответ. Вот как это работает:

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

В бою:

$ {echo 987654321; эхо 1; } | dc ndigit.dc
9
$ {echo 987654321; эхо 2; } | dc ndigit.dc
8
$ {echo 987654321; эхо 8; } | dc ndigit.dc
2
$ {echo 987654321; эхо 9; } | dc ndigit.dc
1
$ 

1
Я думаю, что ты победитель. Это третий самый короткий код, но самый короткий 2 используется base conversion -> arrays.
kukac67

5

GolfScript (10 байт)

~(\10base=

Это предполагает, что ввод в виде строки (например, через стандартный ввод). Если в стеке два целых числа, то начальная буква ~должна быть удалена, сохраняя 1 символ.

Если базовое преобразование считается нарушением правила встроенных функций, у меня есть альтернатива из 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-значными цифрами из первого числа, получая
=желаемое элемент массива

Программа в основном перевод решения Питера Тейлора.


Я бы сказал, что помещение десятичных цифр в массив - это скорее строковая операция, чем математическая.
Цифровая травма

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 символа

Достаточно «математический ответ».

(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

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

Вам не нужно определять его как fn:def f(i,n): ... return d
smci

Вам не нужно здравомыслие - проверьте if n>k: return -1дело.
smci

... и вам, конечно, не нужно делать первый проход, чтобы просто посчитать k (количество цифр в i), чтобы сравнить его с n.
smci

2

С, 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, который я выбрал просто потому, что он короче, чем использование журнала. Если это проблема, это легко исправить, я могу добавить ее, когда вернусь домой.
ВОО

Там мы идем, добавил чисто математическую версию.
ВОО

2
Математика - ни разу!
Поцблиц

2

до н.э. (управляемый bash), 41 29

Я думаю, что это первый ответ, который делает это математически, а не со строками:

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

Использование length()может показаться немного сложным, но страница руководства bc говорит о количестве цифр, а не о длине строки:

  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
Ok. Я буду отменять тогда. Надеюсь, ты не выиграешь! : P
kukac67

1

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

Это может быть значительно в гольфе. Начните с этих советов
Цифровая травма

Для начала, (int) броски и связанные с ними парены не нужны
Digital Trauma

1
Я не мог устоять. Я играл в гольф до 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]&

У меня нет Mathematica под рукой для тестирования, я сомневаюсь, что это будет Как я подозревал (и как любезно подтверждено 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

Ungolfed:

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
(М * Math.pow (10, I (1) .toInt-1-Math.log10 (м) toInt)). ToInt% 10}

Спасибо, что заметили ошибку в предыдущей формуле. Этот короче.


Мне это нравится! :) Проголосовал
kukac67

Протестировал решение: k (Array ("1234", "7")), которое дает 9. Разве это не работает для n> #digits (x)?
lambruscoAcido

Это связано с тем, что 10 ^ -1 не является точным в этих обозначениях, поэтому возникает ошибка округления, когда вы берете 10% pow (10, -1), которые должны были дать ноль, но вместо этого дали 0.0999. Исправил мой ответ, чтобы учесть этот побочный эффект.
Микаэль Майер

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

Код 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   без 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 и вычитаем 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 символ, изменив его на echo$n%10.
Амаль Мурали

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

Но это правда, что если второе число больше, чем количество цифр, вы выводите 9, а не ноль
Микаэль Майер

Я вижу, он выводит последнюю цифру, если число больше, чем количество цифр. Если вы введете 1234 и 5-ю цифру, вы получите 4, так как 1234 i уже меньше 10 ^ 5.
dkasipovic

0

~ - ~! - 94 93

Немного изменяет правила - это функция, которая принимает n в качестве входных данных и предполагает, что число, в котором находится цифра n, хранится в '''''- и ~ - ~! не поддерживает поплавки.

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

'''''=~~~~,~~,~~,~~,~~,~~:''''''=''''&~:приведет ''''''к ~~(2) ('' '' '= 128).


Хм ... Еще один эзотерический язык?
VisioN

@VisioN на самом деле это не эзотерика, просто единственный тип данных - это число, и он не может взаимодействовать с os / internet. 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-битного беззнакового целого
  2. когда мы нажимаем на левую часть целого числа, int ($ 1 / d) возвращает ненулевое значение
  3. продолжить n ($ 2) цифр после этого

Ungolfed:

{
    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

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

С, 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

Smalltalk, 44

Хотя dc непобедим, вот решение Smalltalk:

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

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