Вычислить A (N) / B (N) с C (N) цифрами

15

Рассмотрим три последовательности чисел A, Bи C:

  • A: Последовательность, основанная на рекуррентных отношениях f(n) = f(n-1)+f(n-2), начиная с f(1) = 3, f(2) = 4. Итак, последовательность начинается так:3 4 7 11 18 29 47 76 ...
  • B: Составные числа , то есть все целые числа, которые не являются простыми числами (или 1):4 6 8 9 10 12 14 15 16 ...
  • CЦифры Пи: 3 1 4 1 5 9 2 6 5 ...

Если задано положительное целое число в N < 50качестве аргумента функции или STDIN, вернуть десятичное значение дроби A(N)/B(N)с C(N)цифрами после десятичной точки. Применяются обычные правила округления (округление в большую сторону, если цифра N + 1 - 5 или выше). Если N-ая цифра piравна нулю, должно быть напечатано целое число. научная нотация / Стандартная форма принимается для номеров выше 1000.

Это код гольфа, поэтому выигрывает самый короткий ответ в байтах.

Несколько примеров:

N = 1: 0.750
N = 2: 0.7
N = 3: 0.8750
N = 4: 1.2
N = 6: 2.416666667
N = 10: 11.056
N = 20: 764.8750

Конечно, применяются стандартные правила игры в гольф.

Функция должна завершиться менее чем за две минуты на любом современном ноутбуке.

Стьюи Гриффин
источник
Когда вы говорите C(n)цифры, мы должны включить конечные 0?
Maltysen
К какому входу применяется ограничение по времени?
Деннис
@ Денис, ты к чему N? Если так, то до N = 49. Или что-то еще?
Стьюи Гриффин
JavaScript имеет ограниченную точность с плавающей запятой 16. В прошлом вы начнете получать неточные результаты. Это нормально?
Downgoat
1
@vihan Мое решение (неопубликованный банкомат) хранит первые 49 цифр числа Пи в строке. И вам не нужно более 9 цифр точности в результате, если вы беспокоитесь об этом.
ETHproductions

Ответы:

9

Pyth, 60 57 58 байтов

.[K`.Rchu,eGsGQjT7e.ftPZQ)Je/u+/*GHhyHy^TQr^T3ZZT\0+xK\.hJ

Испытательный жгут

Это довольно просто - вычислить число Пи, ряд Фибоначчи и композиты, округлить до C (n) цифр, дополнить до C (n) цифр плюс расположение цифр десятичной точки.

А (п): hu,eGsGQjT7

В (п): e.ftPZQ)

С (п): e/u+/*GHhyHy^TQr99ZZT

60 -> 57: Очистить n = 1 особый случай в вычислениях пи.

57 -> 58: Не использовалось достаточно высокое прецизионное значение для pi для всего входного диапазона - увеличено с 99 итераций до 1000 итераций.

Примечание по округлению: при этом используется система округления Python «ближайшая четность», а не OP, заданная система «к бесконечности». Однако разница имеет значение только в том случае, если цифры, следующие сразу за точкой округления 5000..., например, 1,25 округлены до 1 цифры. Я проверил входной диапазон, и этого никогда не происходит, поэтому всегда возвращается правильный результат.

isaacg
источник
2

PowerShell, 420 байт (айыыыыыыы) 378 байт

param($n);[int[]]$p="03141592653589793238462643383279502884197169399375"-Split'';$a=@(0,3,4);for($i=3;$i-lt50;$i++){$a+=$a[$i-1]+$a[$i-2]};$c=[char[]]"00001010111010111010111011111010111110111010111011111011111010111110111";$b=@(0);for($i=4;$i-le70;$i++){if($c[$i]-eq'1'){$b+=$i}};[double]$r=$a[$n]/$b[$n];$q=$p[$n+1];$s="";(0..($q-1))|%{$s+="0"};([math]::Round($r,$q,[MidpointRounding]::AwayFromZero)).ToString("0.$s")

Спасибо isaacg за сохранение 41 байта, за вычисление, как вопрос выполняет округление. Означает, что я не должен был включать ужасные [MidpointRounding]::AwayFromZeroи не нужно явно использовать как [double].

Это было очень весело!

Expanded:

# Take input N
param($n)

# First digits of pi, stored as integer array
[int[]]$p="03141592653589793238462643383279502884197169399375"-Split''

# Fibonacci sequence A(N)
$a=@(0,3,4)
for($i=3;$i-lt50;$i++){
  $a+=$a[$i-1]+$a[$i-2]
}

# Zero-indexed bitmask for if the n-th integer is composite (1) or not (0)
$c=[char[]]"00001010111010111010111011111010111110111010111011111011111010111110111"

# Populate B(N) as an array using the $c mask
$b=@(0)
for($i=4;$i-le70;$i++){
  if($c[$i]-eq'1'){
    $b+=$i
  }
}

# Calculation Time!
$r=(a($n))/$b[$n]

# A small golf, as $p[$n+1] gets used a couple times
$q=$p[$n+1]

# Need to generate a string of zeroes for padding
$s=""
(0..($q-1))|%{$s+="0"}

# Round the number, then send it to a string so we get the necessary number of zeroes
([math]::Round($r,$q)).ToString("0.$s")

Рекурсия в PowerShell ... медленная, скажем так, поэтому мы должны построить A(N)другое направление и сохранить его в массиве, а затем проиндексировать.


OLD

Кроме того, святая корова, требования к выходу убили это. По умолчанию PowerShell использует округление до ближайшего округления / k / a банкира, что требует использования чрезвычайно многословного [MidpointRounding]::AwayFromZeroдля переключения стилей округления . Кроме того, нам нужно дополнить конечные нули, если таковые имеются. Эти два требования объединены, чтобы превратить последние пару строк из 20 байтов [math]::Round($r,$q) в 102 байта (от $s=""до +$s)) ... вау.

AdmBorkBork
источник
Отличное описание / комментирование! 32 символа для[MidpointRounding]::AwayFromZero одиночку почти слишком хороши / плохи, чтобы быть правдой ... =)
Стьюи Гриффин
1
Смотрите мою записку о округлении в моем ответе. Округление PowerShell по умолчанию должно быть в порядке.
Исаак
1

Javascript (ES6), 302 байта

Одно слово: незаконченное.

x=>{a=[0,3,4],b=[0],c='03141592653589793238462643383279502884197169399375';for(i=1;i<x;a[i+2]=a[i]+a[++i]);for(i=1,p=[];++i<70;v=p.every(x=>i%x),(v?p:b).push(i));r=''+Math.round(a[x]/b[x]*(l=Math.pow(10,c[x])))/l;if(x==33)return r;r.indexOf`.`<0&&(r+='.');while(!r[r.indexOf`.`+ +c[x]])r+='0';return r}

Первые 49 цифр числа пи хранятся в строке, а две другие последовательности генерируются автоматически. Это было в гольф примерно на полпути; Я (почти) уверен, что смогу выжать из нее еще 50 байтов.

Работает для всех тестовых случаев, и должен работать для остальных. Сбои при значениях больше 49 или меньше 0 (в любом случае, они никогда не должны сталкиваться с этими ситуациями). Мне особенно нравится его результат для 0:

NaN.
ETHproductions
источник
Почему это незаконченное?
Бета-распад
@BetaDecay Я имел в виду, что еще не закончил игру в гольф. Я буду, как только у меня будет время.
ETHproductions
1

Октав, 276 236 байт

Прежде всего, я подумал, что было бы здорово использовать некоторую неограниченную точность в этих математических инструментах (и освежить некоторые знания об этом), поэтому я начал писать некоторые алгоритмы, а затем, наконец, обнаружил, что piзначение не настолько точно, что я Придется снова использовать массив. Итак, еще раз, нет большого успеха

function c(A)p="3141592653589793238462643383279502884197169399375";f=ones (1,50);f(1)=3;f(2)=4;for i=3:53f(i)=f(i-1)+f(i-2);end
i=0;x=1;while i<A
x++;for j=2:x/2
if mod(x,j)==0 i++;break;end end end
printf(["%." p(A) "f\n"],f(A)/x);end

Все еще вполне читабельно, не так ли?

использование

скопировать-вставить функцию в октаву, вызвать функцию cс аргументом требуемого значения:

>>> c(1)
0.750
>>> c(49)
407880480.04348

Оптимизации:

  • Вышедший на замену endif, endforи аналогичные с endкоторой работает таким же образом ,
  • уменьшение переменной iна единицу, сохранение одного байта
  • убери num2str(str2num(p(A)))ерунду :)
Jakuje
источник
Мне нравится, что вы опубликовали решение от Octave (я сам из MATLAB!). Обратите внимание, что этот код только Octave, а не MATLAB. MATLAB использует endне endifтак много сохраненных байтов. Если вы посчастливилось иметь символический набор инструментов для MATLAB, вы можете использовать , vpaчтобы получить достаточное количество десятичных точек для пи: vpa(sym(pi),49). У меня его нет на этом ноутбуке, так что я не уверен sym, нужно ли там, но в любом случае следует сохранить немало байтов =) И читабельность не обязательно хорошая вещь в коде гольф =)
Стьюи Гриффин
x ++ также не является командой MATLAB. Я не знал, что между ними есть такие большие различия ... ИМО, так не должно быть. Я думаю, что весь код, написанный на Octave, должен быть переносимым на MATLAB (но не обязательно наоборот, поскольку у MATLAB есть больше опций).
Стьюи Гриффин
Одобрено ваше редактирование. У меня здесь нет matlab, поэтому я не смог его проверить. Я искал решение, чтобы получить больше десятичных дробей в октаве, но, к сожалению, нет ничего короче, чем просто массив. Но пропуски whileиз endwhileи аналогичные работают отлично, поэтому я обновляю ответ,
добавив