Повторне! Факторії!


34

Не плутати з Find the faorial!

Вступ

Фактор цілого числа nможе бути обчислений

н!=н×(н-1)×(н-2)×(...)×2×1

Це порівняно просто і нічого нового. Однак факториали можна поширити на подвійні , такі, що для парних чисел, і для непарних чисел. Але ми не обмежені подвійними фабриками. Наприклад, n !!! = n \ раз (n-3) \ раз (n-6) \ раз (...) \ раз6 \ раз 3 або n !!! = n \ раз (n-3) \ раз ( n-6) \ times (...) \ times5 \ times2 or n !!! = n \ times (n-3) \ times (n-6) \ times (...) \ times4 \ times1, залежно від вихідне значення.

н!!=н×(н-2)×(н-4)×(...)×4×2
n!!=n×(n−2)×(n−4)×(...)×3×1
n!!!=n×(n−3)×(n−6)×(...)×6×3
n!!!=n×(n−3)×(n−6)×(...)×5×2
n!!!=n×(n−3)×(n−6)×(...)×4×1

Підсумовуючи:

н!(к)={1якщо н=0някщо 0<н≤кн⋅((н-к)!(к))якщо н>к
де
н!(к)=н!…!⏟к
Або простою англійською мовою: Віднімайте фактичний підрахунок від базового числа кілька разів і множте всі отримані додатні цілі числа.

Змагання

Напишіть функцію, яка обчислить будь-який вид повторного факторіала для будь-якого невід’ємного цілого числа.

Вхідні дані

Або

  • Рядок, що містить невід'ємне ціле число базового десяти, а потім 1 або більше знаків оклику. Наприклад , "6!"чи "9!!"або "40!!!!!!!!!!!!!!!!!!!!".

або

  • Одні і ті ж значення, представлені двома цілими числами: одне негативне базове значення та одне додатне значення, що представляє фактичне число. Це можна зробити у будь-якому форматі із стандартних правил вводу / виводу.

Вихідні дані

Результат зазначеного розрахунку.

Зауваження виклику

  • 0!дорівнює 1за визначенням. Ваш код повинен це враховувати.
  • Кількість факторів обмежена
    0<fаcтоriал cоунт≤басе vалуе
    поза цим діапазоном, ви можете виводити все, що завгодно. Крім того 0!, що є єдиним винятком із цього правила.

Приклади

Input                              Output

3!!!                               3
0!                                 1
6!                                 720
9!!                                945
10!!!!!!!!                         20
40!!!!!!!!!!!!!!!!!!!!             800
420!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  41697106428257280000000000000000

Спробуйте це з невтішленою реалізацією Python: Спробуйте в Інтернеті!

Загальні зауваження


6
Перелік прикладів, 0!але зауваження, що стосуються викликів, говорить про те, що базовий показник буде меншим або рівним базовій.
— Джонатан Аллан

1
Чи не 3 !!! бути нулем? n * (n-3) = 3 * (3-3) = 0.
— ouflak

2
@ouflak Якщо це працює як 1!, не дуже. Це більше як 1! = 1. 2 !! = 2. 3 !!! = 3. Немає розрахунку, тому що ви в кінці рекурсивності. Ні 0 в продуктах, інакше кожна фабрика знизиться до 0.
— В. Куртуа

4
3!!!!!!!не повинно бути невизначеним - він повинен просто дати відповідь 3. Це те саме, що 1!!=1(не визначено). Також ваша специфікація вказує, що завжди буде хоча б одна !, тому перший приклад 3не відповідає специфікації.
— Грег Мартін

3
@ FabianRöling: Але це не те, що це. Це не (3!)!натомість це вилучення термінів з факторіалу. Це оманливе ім'я; Я припускав, що припускає, що це функція "Фактор" буде застосовуватися неодноразово в ланцюжку, і мені довелося уважно прочитати, щоб побачити, що це насправді. На щастя, це питання це чітко пояснює. Кращою назвою може бути кроковий факторний або ступінчастий фактор чи щось таке.
— Пітер Кордес

Відповіді:



13

ArnoldC , 702 698 634 байт

LISTEN TO ME VERY CAREFULLY f
I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE n
I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE p
GIVE THESE PEOPLE AIR
HEY CHRISTMAS TREE r
YOU SET US UP 1
HEY CHRISTMAS TREE c
YOU SET US UP 0
STICK AROUND n
GET TO THE CHOPPER r
HERE IS MY INVITATION r
YOU'RE FIRED n
ENOUGH TALK
GET TO THE CHOPPER n
HERE IS MY INVITATION n
GET DOWN p
ENOUGH TALK
GET TO THE CHOPPER c
HERE IS MY INVITATION 0
LET OFF SOME STEAM BENNET n
ENOUGH TALK
BECAUSE I'M GOING TO SAY PLEASE c
GET TO THE CHOPPER n
HERE IS MY INVITATION 0
ENOUGH TALK
YOU HAVE NO RESPECT FOR LOGIC
CHILL
I'LL BE BACK r
HASTA LA VISTA, BABY

Спробуйте в Інтернеті!

Переведено на псевдокод:

f(n,p) {
  r=1;
  c=0;
  while (n) {
    r=r*n;
    n=n-p;
    c=n<0;
    if (c) n=0;
  }
  return r;
}

Примітка: ArnoldC має лише один тип даних: 16-бітове ціле число. Отже, я не можу перевірити цю 420!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!справу.


Просто цікаво про ваш psuedocode. Для чого змінна 'c'?
— ouflak

@ouflak я пару разів відредагував свою відповідь і забув її. cМінлива фактично зберігає значення порівняння між nі 0.
— Чарлі

+1, і я запозичив його (мінус "c") для своєї відповіді на LUA.
— ouflak

12

Желе , 4 байти

RṚmP

Спробуйте в Інтернеті!

Як? Враховуючи і , він спочатку генерує діапазон (with ), потім з ним зберігає кожен елемент цього діапазону (так ), і, нарешті, примножує їх за допомогою .нкн,⋯,1RṚmкгон,н-к,н-2к,⋯,н-⌊н/к⌋кP


Добре працює, і в кінці кінців так просто. Я взагалі не знаю Джеллі, але принаймні це добре виглядає :)
— В. Куртуа

1
@ V.Courtois Даючи і , він спочатку генерує діапазон (з ), потім з ним зберігає кожен елемент цього діапазону (так ) і, нарешті, примножує їх за допомогою . Просто прямолінійний підхід. Редагувати: Це пояснення я додав у відповідь. нкн,⋯,1RṚmкгон,н-к,н-2к,⋯,н-⌊н/к⌋кP
— Містер Xcoder

Ха-ха, дуже дякую Одного разу я можу захотіти покататися на цій мові, тому мені доведеться вивчити ці монади, діади тощо
— В. Куртуа

Альтернативні , який виглядає як CJam: r1mP.
— Ерік Аутгольфер

1
@KyeWShi Jelly має свою кодову сторінку , тому кожен із 256 символів, які вона містить, кодується як 1 байт.
— Містер Xcoder

8

APL (Dyalog Extended) , 7 байт SBCS

Функція анонімного мовчання. Вважається [n,b]аргументом.

×/-\…1¨

Спробуйте в Інтернеті!

1¨ по одному для кожного елемента аргументу; [1,1]

-\ сукупна різниця; [n,n-b]

… діапазон, використовуючи другий елемент лівого аргументу як індикатор кроку, наприклад, [9,7]продовжує з5

×/ продукт


7

Haskell , 21 байт

n%a=product[n,n-a..1]

Спробуйте в Інтернеті!

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

22 байти

n%a|n<1=1|m<-n-a=n*m%a

Спробуйте в Інтернеті!

Ось рішення, яке приймає вклад у такому вигляді рядка 9!!, що, на мою думку, цікавіше.

42 байти

(\[(n,a)]->product[n,n-length a..1]).reads

Спробуйте в Інтернеті!


2
Я думаю, ви могли б скоротити рекурсивне рішення доn%a|n<1=1|m<-n-a=n*m%a
— провалу



5

Пробіл , 91 байт

[S S S T    N
Push_1][S N
S _Duplicate_1][S N
S _Duplicate_1][T   N
T   T   _Read_STDIN_as_integer_(base)][T    T   T   _Retrieve_base][S S S N
_Push_0][T  N
T   T   _Read_STDIN_as_integer_(factorial)][N
S S N
_Create_Label_LOOP][S N
S _Duplicate_base][S S S T  N
_Push_1][T  S S T   _Subtract][N
T   T   S N
_If_negative_jump_to_Label_PRINT_RESULT][S N
S _Duplicate_base][S T  S S T   S N
_Copy_0-based_2nd_(result)][T   S S N
_Multiply][S N
T   _Swap_top_two][S S S N
_Push_0][T  T   T   _Retrieve_factorial][T  S S T   _Subtract][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_PRINT_RESULT][S N
N
_Discard_top][T N
S T _Print_result_as_integer]

Букви S(пробіл), T(вкладка) та N(новий рядок) додаються лише як підкреслення.
[..._some_action]додано лише як пояснення.

Спробуйте його в режимі он-лайн (лише з просторами, вкладками та новими рядками).

Пояснення в псевдокоді:

Integer result = 1
Integer base = STDIN as integer
Integer factorial = STDIN as integer
Start LOOP:
  If(base <= 0):
    Call function PRINT_RESULT
  result = result * base
  base = base - factorial
  Go to next iteration of LOOP

function PRINT_RESULT:
  Print result as integer to STDOUT


4

Perl 6 , 22 байти

{[*] $^a,*-$^b...^1>*}

Спробуйте в Інтернеті!

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


4

05AB1E , 10 8 7 байт

ݦRIιнP

Введіть як два відокремлені входи: перший вхід base; друге введення factorial.

Спробуйте в Інтернеті або перевірте всі тестові справи .

-2 байти завдяки @ Mr.Xcoder .
-1 байт завдяки @JonathanAllan .

Пояснення:

Ý        # Create a list in the range [0, (implicit) base-input]
 ¦       # And remove the first item to make it the range [1, base]
         # (NOTE: this is for the edge case 0. For the other test cases simply `L` instead
         #  of `ݦ` is enough.)
  R      # Reverse this list so the range is [base, 1]
   Iι    # Uninterleave with the second input as step-size
         #  i.e. base=3, factorial=7: [[3],[2],[1],[],[],[],[]]
         #  i.e. base=10, factorial=8: [[10,2],[9,1],[8],[7],[6],[5],[4],[3]]
         #  i.e. base=420, factorial=30: [[420,390,360,...,90,60,30],[419,389,359,...],...]
     н   # Only leave the first inner list
      P  # And take the product of its values
         # (which is output implicitly as result)

Оригінальна відповідь на 10 байт :

L0KD¤-IÖÏP

Введіть як два відокремлені входи: перший вхід base; друге введення factorial.

Спробуйте в Інтернеті або перевірте всі тестові справи .

Пояснення:

L           # Create a list in the range [1, (implicit) base-input]
 0K         # Remove all 0s (edge case for input 0, which will become the list [1,0])
   D        # Duplicate this list
    ¤       # Get the last value (without popping)
            # (could also be `Z` or `¹` for max_without_popping / first input respectively)
     -      # Subtract it from each item in the list
      IÖ    # Check for each if they're divisible by the second factorial-input
        Ï   # In the list we copied, only leave the values at the truthy indices
         P  # And take the product of those
            # (which is output implicitly as result)

1
Цей 6-byter: LR²ιнP( ! Спробуйте його в Інтернеті ) працює для кожного тестового випадку, за винятком 0.
— г Xcoder

Але я здогадуюсь, що 0 випадок можна зафіксувати щонайбільше в 2 байтах. Якщо ви знайдете спосіб виправити це, ви можете скористатися :) РЕДАКТУВАТИ: Можливо, LR²ιн0KPна 8 байт?
— Містер Xcoder

@ Mr.Xcoder Приємна відповідь! Ніколи навіть не використовував непереплутування із заданим кроком. :)
— Кевін Круїссен

0KПотрібно бути непотрібним, оскільки 0!це недійсне введення специфікацією (навіть якщо це було включено в приклади) - я коментував це.
— Джонатан Аллан

1
... а якщо 0! є у вхідному домені, ݦRXιнPзберігається байт.
— Джонатан Аллан

4

машинний код x86-64, 12 байт

Цей же машинний код робить те саме, що і в 32-бітному режимі, і для 16-бітних цілих чисел у 16-бітному режимі.

Це функція, яка викликається з арг n=RCX, k=ESI. 32-бітове повернене значення в EAX.

Зателефонувавши з C за допомогою системи V86 x86-64, яка викликає конвенцію з фіктивними аргами, щоб отримати справжні аргументи в потрібні регістри. uint32_t factk(int, uint32_t k, int, uint64_t n); Я не міг просто використовувати Windows x64, оскільки 1- mulоперандний клобує RDX, і ми не хочемо, щоб REX-префікси мали доступ до R8 / R9. nне повинно бути сміття у високих 32 бітах, тому JRCXZ працює, але крім цього, це все 32-розрядні.

Перелік NASM (відносна адреса, код машини, джерело)

 1                         factk:
 2 00000000 6A01             push 1
 3 00000002 58               pop rax             ; retval = 1
 4 00000003 E306             jrcxz  .n_zero      ; if (n==0) return
 5                         .loop:                ; do {
 6 00000005 F7E1              mul   ecx            ; retval *= n  (clobbering RDX)
 7 00000007 29F1              sub   ecx, esi       ; n -= k
 8 00000009 77FA              ja   .loop         ; }while(sub didn't wrap or give zero)
 9                         .n_zero:
10 0000000B C3               ret

0xc = 12 байт


Або 10 байт, якщо нам не потрібно було обробляти n=0спеціальний корпус, залишаючи без уваги jrcxz.

У стандартному факторіалі ви використовуєте loopзамість sub / ja для збереження 2 байтів, але в іншому випадку точно такий же код.


Випробувальний абонент, який проходить argcяк kіз nжорстким кодом.

align 16
global _start
_start:
  mov  esi, [rsp]
;main:
  mov  ecx, 9
  call factk

  mov  esi, eax
  mov  edx, eax
  lea  rdi, [rel print_format]
  xor  eax, eax
extern printf
  call printf
extern exit
  call exit

section .rodata
print_format: db `%#x\t%u\n`

```

3

APL (Dyalog Unicode) , 11 байт SBCS

Функція анонімного мовчазного виправлення. Приймається nяк правий аргумент і bяк лівий аргумент.

×/1⌈⊢,⊢-×∘⍳

Спробуйте в Інтернеті!

×∘⍳ кратно bпо ɩ ntegers 1 черезn

⊢- відняти, що від n

⊢, подавати n

1⌈ максимум один і кожен із них

×/ продукт



3

Мова Вольфрама (Mathematica) , 22 21 байт

1##&@@Range[#,1,-#2]&

Спробуйте в Інтернеті!

-1 спасибі attinat: Times --> 1##&

Пояснення: використовуйте Rangeдля складання списку значень {n, n-k, n-2k, n-3k, ...}, зупиняючись перед тим, як перейти нижче 1 (тобто, зупиняючись прямо праворуч). Потім помножте всі числа в цьому списку на Times(або 1##&).


-1 байт з 1##&замістьTimes
— attinat

3

Java 10, 44 байти

f->b->{int r=1;for(;b>0;b-=f)r*=b;return r;}

Приймає факторіал як перший вхід, базу - як другий.

Спробуйте в Інтернеті.

Це вище не працює для найбільшого тестового випадку через обмежений цілий діапазон (32 біт). Щоб виправити це , ми можемо використовувати BigIntegers, який по збігу є саме подвійний розмір - 88 79 байт :

f->b->{var r=f.ONE;for(;b.signum()>0;b=b.subtract(f))r=r.multiply(b);return r;}

-9 байт завдяки @ OlivierGrégoire .

Спробуйте в Інтернеті.

Пояснення:

f->b->{       // Method with two integer parameters and integer return-type
  int r=1;    //  Result-integer, starting at 1
  for(;b>0;   //  Loop as long as the base is still larger than 0
      b-=f)   //    After every iteration: decrease the base by the factorial
    r*=b;     //   Multiply the result by the base
  return r;}  //  Return the result


@ OlivierGrégoire Np, і дякую! :)
— Кевін Крейссен



2

MathGolf , 7 6 байт

╙╒x%ε*

Спробуйте в Інтернеті!

Знайшли розумний спосіб впоратися з 0! не змінюючи інших тестових випадків. Приймає дані як k n(зворотний порядок), що допомагає при неявному вискакуванні.

Пояснення

╙        maximum of two elements (pops largest of k and n,
         which is n for every valid case except 0!, where 1 is pushed)
 ╒       range(1,n+1)
  x      reverse int/array/string
   %     slice every k:th element
    ε*   reduce list with multiplication

2

Attache , 21 19 байт

${x<y∨x*$[x-y,y]}

Спробуйте в Інтернеті! Досить пряма рекурсивна реалізація. (Примітка. По trueсуті 1, оскільки його можна використовувати в арифметичних операціях як 1.) Це одна з небагатьох програм, які я написав для цього сайту, де використання оператора unicode зберігає байти (1, якщо бути точним).

Альтернативи

20 байт: ${x<y or x*$[x-y,y]}

21 байт: Prod@${{_%y=x%y}\1:x}

27 байт: ${x*[`1,$][x>y][x-y,y]∨1}

27 байт: ${If[x>y,x*$[x-y,y],_or 1]}

27 байт: ${x*[`1,$][x>y][x-y,y]or 1}

29 байт: ${If[x>y,x*$[x-y,y],_+not _]}


2

Іржа , 92 73 61 байт

fn f(n:i128,k:i128)->i128{if n<=0{return 1}return n*f(n-k,k)}

Я тільки починаю вивчати іржу, тому впевнений, що це може бути коротшим. Буде оновлюватися, коли я дізнаюся. Повертане значення повинно бути таким i128, щоб обчислити останній тест.

Правка: Рекурсія коротша.

Спробуйте в Інтернеті!

Ви можете додати власний тест або відредагувати один із вже існуючих.


2

q , 59 57 55 53 байт

{prd 2+(&)1_i=last i:("J"$x(&)not[n])#(!)sum n:"!"=x}

пояснення:

q)x:"12!!" / let our input be 12!!, assign to x
q)sum n:"!"=x / count "!"s
2i
q)(!)sum n:"!"=x / (!)m -> [0,m)
0 1
q)("J"$x(&)not[n]) / isolate the number in input
12
q)("J"$x(&)not[n])#(!)sum n:"!"=x / x#y means take x items from list y, if x>y, circle around
0 1 0 1 0 1 0 1 0 1 0 1
q)i:("J"$x(&)not[n])#(!)sum n:"!"=x / assign to i
q)i
0 1 0 1 0 1 0 1 0 1 0 1
q)(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / take last elem of i and see which are equal in i
010101010101b
q)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / drop first elem
10101010101b
q)(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / indices of 1b (boolean TRUE)
0 2 4 6 8 10
q)2+(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / add 2 across array
2 4 6 8 10 12
q)prd 2+(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / product across array
46080

тут також є версія в k (така ж логіка), 42 41 байт

{*/2+&1_i=last i:("J"$x@&~:n)#!+/n:"!"=x}

Ласкаво просимо на сайт! До вашої публікації я додав форматування коду, яке можна виконати з чотирьох пробілів перед рядком або додавши його до потрійних зворотних посилань.
— Пшеничний майстер

@ SriotchilismO'Zaic спасибо :-)
— каракулі

1
Я рекомендую додати пояснення та, можливо, посилання на онлайн-перекладача, наприклад TIO . Відповіді, що стосуються лише коду, зазвичай автоматично позначаються як низька якість.
— mbomb007

@ mbomb007 цікаво. чи є відповіді на позначення бота? що відбувається з низькоякісними поданнями? я скоро оновлю!
— скраб

Так, є бот. StackExchange використовує ботів для пошуку потенційного спаму та низької якості відповідей. Люди з достатньо високою репутацією можуть переглядати Чергу огляду. meta.stackexchange.com/a/161391/285610
— mbomb007


1

Сітківка , 66 байт

^0
1
\d+
*!,
+`(!+)(!+),\1$
$1$2,$2,$1
!+$
1
+`(!+),(\d+)
$.($2*$1

Спробуйте в Інтернеті! Посилання включає більш швидкі тестові випадки. Знімає цифри без знаків оклику. Пояснення:

^0
1

Виправити 0!.

\d+
*!,

Перетворити nв одинарний і додати роздільник.

+`(!+)(!+),\1$
$1$2,$2,$1

Кілька разів відняти kз в nтой час n>k, і зібрати результати.

!+$
1

Замініть kна 1(десятковим).

+`(!+),(\d+)
$.($2*$1

Помножте на кожне проміжне значення по черзі, перетворюючи на десятковий.




1

Четвертий (gforth) , 50 байт

: f 1 1 2over / 1+ 0 do 2over i * - 1 max * loop ;

Спробуйте в Інтернеті!

Пояснення коду

: f                \ start a new word definition
  1 1              \ add placeholder and accumulator to stack
  2over / 1+       \ get the number of times to run the loop (num/factorial + 1)
  0 do             \ start loop from 0 to num/factorial
    2over          \ copy num and factorial to the top of the stack
    i * -          \ get the current number to multiply by (num - factorial * i)
    1 max          \ make sure it can't be 0 or negative [set to 1 if it is]
    *              \ multiply accumulator by result
  loop             \ end loop
;                  \ end the word definition           



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.