Ряд натуральных чисел

22

Определение

Существует бесконечный ряд объединенных натуральных чисел (положительные целые числа, начиная с 1):

1234567891011121314151617181920212223...

Вызов

  • Напишите программу на любом языке, который принимает номер позиции в качестве ввода и выводит цифры из этой позиции в строке, определенной выше.
  • Номер позиции - произвольный размер положительного целого числа. То есть первая позиция равна 1, получая выходную цифру «1»
  • Входные данные либо в десятичном виде (например, 13498573249827349823740000191), либо в электронной записи (например, 1.2e789), соответствующие положительному целому числу.
  • Программа должна завершиться за разумное время (10 секунд на современном ПК / Mac), учитывая очень большой индекс в качестве входа (например, 1e123456 - то есть 1 с 123456 нулями). Таким образом, простой итерационный цикл не приемлем.
  • Программа должна завершиться с ошибкой в ​​1 с, если дан неверный ввод. Например. 1,23e (недействительно) или 1,23e1 (равно 12,3 - не целое число)
  • Можно использовать публичную библиотеку BigNum для анализа / хранения чисел и выполнения простых математических операций с ними (+ - * / exp). Байт-штраф не применяется.
  • Самый короткий код выигрывает.

TL; DR

  • Ввод: целое число
  • Вывод: цифра в этой позиции в бесконечном ряду 123456789101112131415...

Некоторые приемочные тесты

в обозначении «Вход: выход». Все они должны пройти.

  • 1: 1
  • 999: 9
  • 10000000: 7
  • 1e7: 7 (аналогично строке выше)
  • 13498573249827349823740000191: 6
  • 1.1e10001: 5
  • 1e23456: 5
  • 1.23456e123456: 4
  • 1e1000000: 0
  • 1.23e: ошибка (неверный синтаксис)
  • 0: ошибка (за пределами)
  • 1.23e1: ошибка (не целое число)

Бонус!

Выведите номер позиции цифры внутри номера и сам номер выхода. Например:

  • 13498573249827349823740000191: 6 24 504062383738461516105596714
    • Это цифра '6' в позиции 24 номера '50406238373846151610559 6 714'
  • 1e1000000: 0 61111 1000006111141666819445...933335777790000
    • Цифра «0» в позиции 61111 длинного номера 999995, который я не собираюсь здесь включать.

Если вы выполнили бонусное задание, умножьте размер кода на 0,75

кредит

Это задание было дано на одном из собраний devclub.eu в 2012 году без требования большого количества. Следовательно, большинство представленных ответов были тривиальными петлями.

Повеселись!

metalim
источник
Я действительно не понимаю, в чем проблема. Должны ли мы взять ввод и вывести число в этой позиции?
The_Basset_Hound
2
@vihan Использование некоторой публичной библиотеки bignum допустимо. Без штрафа. Конечно, включение решения в библиотеку и использование библиотеки в одной строке - это вопрос обмана. Здравый смысл применяется здесь.
Металим
1
Просто хотел продемонстрировать удивительно сжатое решение F # с тактовой частотой 44 байта. Конечно, он может обрабатывать индексы только до 2 ^ 31-1 (и все еще пытается вычислить это значение, пока я пишу это). Я не публикую это, хотя, потому что это действительно нарушает правила, но я бы сказал, что это довольно хорошо для F #!
Jwosty
7
Требования к обработке входных данных, например, 1.23456e123456произвольно наказывают языки, которые не могут обрабатывать такие значения естественным образом, и требуют, чтобы они выполняли обработку строк, которая является касательной к задаче.
xnor

Ответы:

12

CJam , 78 байт

r_A,s-" e . .e"S/\a#[SSS"'./~'e/~i1$,-'e\]s"0]=~~_i:Q\Q=Qg&/
s,:L{;QAL(:L#9L*(*)9/-_1<}g(L)md_)p\AL#+_ps=

Программа имеет длину 104 байта и имеет право на бонус.

Новая строка чисто косметическая. Первая строка анализирует вход, вторая генерирует выход.

Попробуйте онлайн!

идея

Для любого натурального числа k существует 9 × 10 k-1 натуральных чисел с ровно k цифрами (не считая начальных нулей). Таким образом, если мы объединяем их все, мы получаем целое число 9 × n × 10 k-1 .

Теперь, объединяя все целые числа из n или менее цифр, получим целое число

формула

цифры.

Для заданного входного значения q мы пытаемся определить наибольшее значение n , чтобы указанное выше выражение было меньше, чем q . Мы устанавливаем n: = ⌈log 10 q⌉-1 , затем n: = ⌈log 10 q⌉-2 и т. Д., Пока требуемое выражение не станет меньше q , вычитаем полученное выражение из q (получая r ) и сохраняем последнее значение п в л .

Теперь r задает индекс в конкатенации всех натуральных чисел из l + 1 цифр, что означает, что желаемым выходным значением является r% (l + 1) цифра r / (l + 1) -го целого числа l + 1 цифры.

Код (входной разбор)

r_          e# Read from STDIN and duplicate.
A,s-        e# Remove all digits.
" e . .e"S/ e# Push ["" "e" "." ".e"].
\a#         e# Compute the index of the non-digit part in this array.

[SSS"'./~'e/~i1$,-'e\]s"0]

            e# Each element corresponds to a form of input parsing:
            e#   0 (only digits): noop
            e#   1 (digits and one 'e'): noop
            e#   2 (digits and one '.'): noop
            e#   3 (digits, one '.' then one 'e'):
            e#     './~    Split at dots and dump the chunks on the stack.
            e#     'e/~    Split the and chunks at e's and dump.
            e#     i       Cast the last chunk (exponent) to integer.
            e#     1$      Copy the chunk between '.' and 'e' (fractional part).
            e#     ,-      Subtract its length from the exponent.
            e#     'e\     Place an 'e' between fractional part and exponent.
            e#     ]s      Collect everything in a string.
            e#   -1 (none of the above): push 0

~           e# For s string, this evaluates. For 0, it pushes -1.
~           e# For s string, this evaluates. For -1, it pushes 0.
            e# Causes a runtime exception for some sorts of invalid input.
_i:Q        e# Push a copy, cast to Long and save in Q.
\Q=         e# Check if Q is numerically equal to the original.
Qg          e# Compute the sign of Q.
&           e# Logical AND. Pushes 1 for valid input, 0 otherwise.
/           e# Divide by Q the resulting Boolean.
            e# Causes an arithmetic exception for invalid input.

Код (генерация вывода)

s,:L     e# Compute the number of digits of Q and save in L.
{        e# Do:
  ;      e#   Discard the integer on the stack.
  Q      e#   Push Q.
  AL(:L# e#   Push 10^(L=-1).
  9L*(   e#   Push 9L-1.
  *)     e#   Multiply and increment.
  9/     e#   Divide by 9.
  -      e#   Subtract from Q.
  _1<    e#   Check if the difference is non-positive.
}g       e# If so, repeat the loop.
(        e# Subtract 1 to account for 1-based indexing.
L)md     e# Push quotient and residue of the division by L+1.
_)p      e# Copy, increment (for 1-based indexing) and print.
\AL#+    e# Add 10^L to the quotient.
_p       e# Print a copy.
s        e# Convert to string.
2$=      e# Retrieve the character that corresponds to the residue.
Деннис
источник
5

CJam, 75 * 0,75 = 56,25

Это довольно быстро, одна итерация на цифру числа, которое содержит желаемую позицию. Я уверен, что в него можно играть гораздо чаще, оно довольно грубое.

q~_i_@<{0/}&:V9{VT>}{T:U;_X*T+:T;A*X):X;}w;U-(_X(:X/\X%10X(#@+s_2$\=S+@)S+@

Дайте позицию в качестве входа, выход:

<digit> <position> <full number>

Попробуйте онлайн .

Андреа Биондо
источник
@Dennis Работа со всеми входами сейчас :)
Андреа Биондо
Это все еще не вызывает ошибку (как и должно быть) для 1.23e1. Это ошибка, однако, 1.23456e123456поскольку вход не может быть представлен двойным. Кроме того, последние тестовые случаи занимают 3 минуты.
Деннис
2
@Dennis Теперь выдает ошибку. Что касается большого теста ... Черт. Возможно, мне придется переписать все это.
Андреа Биондо