Переупорядочение последовательности


23

Вступление

Давайте рассмотрим следующую последовательность (неотрицательные целые числа):

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ...

Например, давайте возьмем первые три числа. Это 0, 1, 2. Числа, используемые в этой последовательности, можно упорядочить шестью различными способами:

012   120
021   201
102   210

Итак, допустим, что F (3) = 6 . Другой пример - F (12) . Это содержит номера:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11

Или каскадная версия:

01234567891011

Чтобы найти количество способов перестроить это, нам сначала нужно взглянуть на длину этой строки. Длина этой строки является 14. Итак, мы вычисляем 14! , Однако, например, те могут поменяться местами, не нарушая окончательную строку. Есть 2 ноля, значит, 2! способы обнулить нули, не нарушая порядок. Также есть 4, так что есть 4! способы поменять. Мы делим сумму на эти два числа:

Это имеет 14! / (4! × 2!) = 1816214400 способов расстановки строк 01234567891011. Таким образом, мы можем сделать вывод, что F (12) = 1816214400 .

Задание

Учитывая N , выведите F (N) . Для тех, кто не нуждается в представлении. Чтобы вычислить F (N), мы сначала конкатенируем первые N неотрицательных целых чисел (например, для N = 12 будет конкатенированная строка 01234567891011) и вычисляем количество способов упорядочить эту строку.

Контрольные примеры

Input:   Output:
0        1
1        1
2        2
3        6
4        24
5        120
6        720
7        5040
8        40320
9        362880
10       3628800
11       119750400
12       1816214400
13       43589145600
14       1111523212800
15       30169915776000

Заметка

Вычислительный ответ должен быть вычислен в течение срока 10 секунд , скотина незначащих будет запрещен .

Это , поэтому выигрывает представление с наименьшим количеством байтов!


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

@ Geobits первые 10цифры 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Десять разных цифр, так что результат 10!
Аднан

Ах, верно. Я думаю, что 0дело сбрасывало мой счет (глупые пустые строки).
Geobits

1
Не нужно больше беспокоиться об этом. Предложение о лазейке было на уровне +4, когда я разместил комментарий. Сейчас на +9 .
Деннис

1
Вот интересный математический вопрос об этой головоломке: каково значение F (N) относительно N !? Существует ряд значений N, для которых F (N) / F (N-1) <N, но обычно оно немного больше. Я уверен , что F(N)это не O(N!)и что log F(N)есть , O(log N!)но это только предчувствия ...
RICi

Ответы:


5

Желе, 17 15 байт

R’DFµ=€QS;@L!:/

Попробуйте онлайн! или проверьте все тестовые случаи одновременно .

Как это устроено

R’DFµ=€QS;@L!:/    Main link. Input: n

R                  Yield [1, ..., n] for n > 0 or [0] for n = 0.
 ’                 Decrement. Yields [0, ..., n - 1] or [-1].
  D                Convert each integer into the list of its decimal digits.
   F               Flatten the resulting list of lists.
    µ              Begin a new, monadic chain. Argument: A (list of digits)
       Q           Obtain the unique elements of A.
     =€            Compare each element of A with the result of Q.
                   For example, 1,2,1 =€ Q -> 1,2,1 =€ 1,2
                                           -> [[1, 0], [0, 1], [1, 0]]
        S          Sum across columns.
                   This yields the occurrences of each unique digit.
         ;@L       Prepend the length of A.
            !      Apply factorial to each.
             :/    Reduce by divison.
                   This divides the first factorial by all remaining ones.

Это действительно желе? Я смотрю на многих персонажей ASCII :-P
Луис Мендо

3
Им всегда удается каким-то образом проникнуть ...
Деннис

10

ES6, 118 81 78 байт

n=>[...[...Array(n).keys()].join``].map(c=>r/=(o[c]=-~o[c])/i++,o=[],i=r=1)&&r

Кто-то обязательно скажет мне, что есть более короткий способ объединения чисел до n.

Сэкономили 37 байтов, взяв идею @ edc65 и применив ее на стероидах. (Сохраните дополнительный байт, используя «|» вместо, &&но это ограничивает результат до 31 бита.)

Редактировать: еще 3 байта сохранены благодаря @ edc65.


Не нашел способа сократить конкатенацию цифр. Но все остальное может быть короче
edc65

Сохраните 2 байта с reduce:n=>[...[...Array(n).keys()].join``].reduce((r,c,i)=>r*++i/(o[c]=-~o[c]),1,o=[])
user81655

1
Вот это да! но 78 лучше:n=>[...[...Array(n).keys()].join``].map(c=>r/=(o[c]=-~o[c])/i++,o=[],i=r=1)&&r
edc65

1
@ edc65 r/=(...)/i++точнее чем r*=i++/(...)? Это самый смешной гольф, который я когда-либо видел!
Нил

2
Я должен был остановиться на мгновение, потому что я думал, что у вас там есть регулярное выражение.
Мама Fun Roll

7

APL (Dyalog Extended) , 13 байт

×/2!/+\⎕D⍧⍕⍳⎕

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

Полная программа. Использует ⎕IO←0.

Как это устроено

×/2!/+\⎕D⍧⍕⍳⎕
               Take input from stdin (N)
               Generate range 0..N-1
               Stringify the entire array (S)
                (The result has spaces between items)
       D       The character array '0123456789'
               Count occurrences of each digit in S
×/2!/+\         Calculate multinomial:
     +\           Cumulative sum
  2!/             Binomial of consecutive pairs
×/                Product

Полиномиальный расчет исходит из следующего факта:

(a1+a2++aN)!a1!a2!aN!знак равно(a1+a2)!a1!a2!×(a1+a2++aN)!(a1+a2)!a3!aN!

знак равно(a1+a2)!a1!a2!×(a1+a2+a3)!(a1+a2)!a3!×(a1+a2++aN)!(a1+a2+a3)!aN!

знак равнознак равно(a1+a2a1)(a1+a2+a3a1+a2)(a1++aNa1++aN-1)


1
И именно поэтому программисты должны изучать математику.
Аноним

@ Аноним ... и использовать математически наклонный язык программирования.
Адам

5

MATL , 21 байт

:qV0h!4Y2=sts:pw"@:p/

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

объяснение

:q     % implicitly input N, and generate vector [0, 1, ..., N-1]
V      % convert to string representation of numbers. Contains spaces,
       % but no matter. Only characters '0', ..., '9' will be counted
0h     % append 0 character (not '0'), so that string is never empty
!      % convert string to column char array
4Y2    % string '0123456789' (row char array)
=      % test all pairs for equality
s      % sum each column. For N = 12 this gives [2, 4, 1, 1, ..., 1]
t      % duplicate
s      % compute sum. For N = 12 this gives 14
:p     % factorial
w      % swap. Now vector [2, 4, 1, 1, ..., 1] is on top
"      % for each number in that vector
  @:p  %   factorial
  /    %   divide
       % implicitly end loop
       % implicitly display

@ Adnan Решено. И с меньшим количеством байтов :-)
Луис Мендо

Выглядит очень хорошо! :)
Аднан

@ Adnan Спасибо! Я добавил объяснение
Луис Мендо

5

Python 2, 142 137 101 97 байт

(Спасибо @adnan за предложение о input)

(Применен инкрементальный расчет из версии C )

f=1;v=10*[0]
for i in range(input()):
 for h in str(i):k=int(h);v[k]+=1;f=f*sum(v)/v[k]
print f

Оригинальная версия с использованием факториала

import math
F=math.factorial
v=10*[0]
for i in range(input()):
 for h in str(i):v[int(h)]+=1
print reduce(lambda a,x:a/F(x),v,F(sum(v)))

Действительно, единственная игра в гольф в вышеперечисленном - это колл math.factorial Fи пропуски некоторых мест, так что, возможно, есть более короткое решение для Python.

Если требуется объяснение, vведется подсчет частоты каждой цифры; счет обновляется для каждой цифры в каждом номере в указанном диапазоне.

В исходной версии мы вычисляем количество перестановок, используя стандартную формулу (Σf i )! / Π (f i !). Для текущей версии это вычисление выполняется постепенно, путем распределения умножений и деления, как мы видим цифры. Может быть неочевидно, что целочисленное деление всегда будет точным, но легко доказать, основываясь на наблюдении, что каждое деление на kдолжно следовать kумножению последовательных целых чисел, поэтому один из этих умножений должен делиться на k. (Это интуиция, а не доказательство.)

Оригинальная версия быстрее для больших аргументов, потому что она делает только 10 делений Бигнума. Хотя деление bignum на маленькое целое число происходит быстрее, чем деление bignum на bignum, когда у вас есть тысячи делений bignum, это становится немного вялым.


f = f * sum (v) / v [k] -> f * = sum (v) / v [k] сохраняет байт
Микко Вирккиля

@superflux: но это не то же самое значение.
Ричи

5

Python 2, 197 байт (редактирование: сохранено 4 байта, спасибо Томасу Ква!)

import math
l,g,f,p,r,s=[],[],math.factorial,1,range,str
for x in r(int(input())):l.append(s(x))
l="".join(l)
for y in r(10):b=s(l).count(s(y));g.append(f(b));
for c in g:p*=y
print f(int(len(l)))/p

Ungolfed:

import math

l=[] #list of the numbers from 0 to n
exchange_list=[] #numbers that can be exchanged with each other, ie      repeats

multiplied = 1 #for multiplying the digits by each other
n = int(input())

for x in range(n): #put all the numbers from 0-n into the list
    l.append(str(x))

l = "".join(l) #put all the digits in a string to remove repeats

for x in range(10): #look at all the digits and check how many are in the     list/string
    count = str(l).count(str(x))
    if count > 1: #if there is more than 1 of the digit, put the factorial of the amount of - 
        exchange_list.append(math.factorial(count)) # - appearances into the exchange list.

for x in exchange_list: #multiply all the values in the list by each other
    multiplied*=x

print math.factorial(int(len(l)))/multiplied #print the factorial of the  length of the string 
#divided by the exchanges multiplied

1
Добро пожаловать в Программирование Пазлов и Code Golf! Этот ответ был помечен как VLQ (очень низкого качества), я подозреваю, потому что он не содержит каких-либо объяснений или разглашенной версии, которые здесь являются нормой. Предполагая, что ваш ответ работает, и вы улучшаете его от того, чтобы быть «только кодом», он кажется довольно хорошим!
кот

range(0,10)может быть range(10).
lirtosiast

4

CJam, 21 19 байтов

ri,s_,A,s@fe=+:m!:/

Проверьте это здесь.

объяснение

ri   e# Read input and convert to integer N.
,    e# Get a range [0 1 ... N-1].
s    e# Convert to string, flattening the range.
_,   e# Duplicate and get its length.
A,s  e# Push "012345789".
@fe= e# Pull up the other copy of the string and count the occurrences of each digit.
+    e# Prepend the string length.
:m!  e# Compute the factorial of each of them.
:/   e# Fold division over the list, dividing the factorial of the length by all the other
     e# factorials.

3

JavaScript (ES6), 100

n=>(f=[...[...Array(n).keys()].join``].map(c=>(k[c]=~-k[c],p*=i++),i=p=1,k=[]),k.map(v=>p/=f[~v]),p)

Тестовое задание

F=n=>(f=[...[...Array(n).keys()].join``].map(c=>(k[c]=~-k[c],p*=i++),i=p=1,k=[]),k.map((v,i)=>p/=f[~v]),p)

// Less golfed
U=n=>( // STEP 1, count digits, compute factorials
      f= // will contain the value of factorials 1 to len of digits string
      [...[...Array(n).keys()].join``] // array of cancatenated digits
      .map(c=> // execute the following for each digit
           (
            k[c]=~-k[c], // put in k[c] the repeat count for digit c, negated 
            p*=i++       // evaluate factorial, will be stored in f
           ),i=p=1,k=[]),// initialisations
       // at the end of step 1 we have all factorials if f and max factorial in p
       // STEP 2, divide the result taking into account the repeated digits
      k.map(v=>p/=f[~v]), // for each digit, divide p by the right factorial (~v === -v-1)
  p // return result in p
) 

// Test
console.log=x=>O.textContent+=x+'\n'

for(j=0;j<=15;j++) console.log(j+' '+F(j))
<pre id=O></pre>


Разве это не k[c]=~-k[c]синоним --k[c]?
usandfriends

1
@usandfriends нет, когда k [c] не определено - k [c] равно NaN
edc65

Ох, хороший набор факториалов.
Нил

... хотя тебе это не нужно. Смотрите мое последнее обновление.
Нил

3

Pyth, 18 байт

/F.!M+lJ.njRTQ/LJT

Попробуйте онлайн: демонстрация

/F.!M+lJ.njRTQ/LJT   implicit: Q = input number
          jRTQ       convert each number in [0, ..., Q-1] to their digits
        .n           flatten to a single list
       J             store this list in J
              /LJT   for each digit count the number of appearances in J
     +lJ             prepend the length of J
  .!M                compute the factorial for each number
/F                   fold by division

3

Haskell, 92 байта

import Data.List
h n|l<-sort$show=<<[0..n-1]=foldl1 div$product.map fst.zip[1..]<$>l:group l

Пример использования: h 12-> 1816214400.

Как это устроено

l<-sort$show=<<[0..n-1]       -- bind l to the sorted concatenated string
                              -- representations of the numbers from 0 to n-1
                              -- e.g. n=12 -> "00111123456789"

               l: group l     -- group the chars in l and put l itself in front
                              -- e.g. ["00111123456789","00","1111","2",..."9"]
            <$>               -- map over this list
    product.map fst.zip[1..]  -- the faculty the length of the sublist (see below)  
                              -- e.g. [87178291200,2,24,1,1,1,..,1]
foldl1 div                    -- fold integer division from the left into this list
                              -- e.g. 87178291200 / 2 / 24 / 1

                              -- Faculty of the length of a list:
                  zip[1..]    -- make pairs with the natural numbers
                              -- e.g. "1111" -> [(1,'1'),(2,'1'),(3,'1'),(4,'1')]
          map fst             -- drop 2nd element form the pairs
                              -- e.g. [1,2,3,4]
  product                     -- calculate product of the list

3

С 236 174 138 121 байт

Большая заслуга Ричи, за массовое сокращение байтов.

long long d,f=1;j,s=1,n,b[10]={1};main(d){for(scanf("%d",&n);n--;)for(j=n;j;j/=10,f*=++s)d*=++b[j%10];printf("%Ld",f/d);}

Ungolfed

long long d,f=1;
j,s=1,n,b[10]={1};

main(d)
{
    scanf("%d",&n); /* get input */
    for(;n--;) /* iterate through numbers... */
        for(j=n;j;j/=10,f*=++s) /* iterate through digits, sum up and factorial */
            d*=++b[j%10]; /* count and factorial duplicates */
    printf("%Ld",f/d); /* print out result */
}

Попробуй это здесь .


1
Вы можете сохранить 43 символа, не копаясь с -lm. Просто #define L long long L d;i,j,k,m,n,s=1,b[10]={1};L f(n){return n?n*f(n-1):1;}main(d){for(scanf("%d",&n);i<n;)for(j=i++;j;j/=10)++b[j%10],++s;for(;m<10;)d*=f(b[m++]);printf("%Ld",f(s)/d);}
посчитайте

Вы также можете посчитать их в цикле, где вычисляете d: for(;m<10;)s+=b[m],d*=f(b[m++])но я думаю, что это еще пара байтов.
Ричи

Это блестяще. Я объединю свои текущие усилия в гольф и отредактирую.
Коул Кэмерон

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

3

C / bc, 233 121 112 байт (при условии 3-байтового штрафа за |bc)

  1. Вдохновленный Коулом Кэмероном, убрал хакерские манипуляции с персонажами и просто сделал арифметику со значением аргумента.

  2. Изменено на scanf с использованием вектора arg.

    C[10]={1},n=1,k,t;main(){for(scanf("%d",&k);k--;)for(t=k;t;t/=10)printf("%d/%d*",++n,++C[t%10]);puts("1");}
    

потребности bc на самом деле сделать вычисление произвольной точности.

Безголовый и без предупреждения:

#include <stdio.h>
int main() {
  int C[10]={1},n=1,k,t;    /* 0 is special-cased */
  for(scanf("%d",&k);k--;)  /* For each integer less than k */
    for(int t=k;t;t/=10)    /* For each digit in t */
      printf("%d/%d*",++n,++C[t%10]);  /* Incremental choice computation */
  puts("1");                /* Finish the expression */
}

Иллюстрированный (которому я доверяю показывает алгоритм):

$ for i in {0..15} 100 ; do printf %4d\  $i;./cg70892g<<<$i;done
   0 1
   1 1
   2 2/1*1
   3 2/1*3/1*1
   4 2/1*3/1*4/1*1
   5 2/1*3/1*4/1*5/1*1
   6 2/1*3/1*4/1*5/1*6/1*1
   7 2/1*3/1*4/1*5/1*6/1*7/1*1
   8 2/1*3/1*4/1*5/1*6/1*7/1*8/1*1
   9 2/1*3/1*4/1*5/1*6/1*7/1*8/1*9/1*1
  10 2/1*3/1*4/1*5/1*6/1*7/1*8/1*9/1*10/1*1
  11 2/1*3/2*4/1*5/1*6/1*7/1*8/1*9/1*10/1*11/1*12/2*1
  12 2/1*3/2*4/3*5/2*6/1*7/1*8/1*9/1*10/1*11/1*12/1*13/1*14/4*1
  13 2/1*3/1*4/2*5/3*6/4*7/2*8/1*9/1*10/1*11/1*12/1*13/1*14/1*15/2*16/5*1
  14 2/1*3/1*4/2*5/1*6/3*7/4*8/5*9/2*10/1*11/1*12/1*13/1*14/1*15/1*16/2*17/2*18/6*1
  15 2/1*3/1*4/2*5/1*6/3*7/1*8/4*9/5*10/6*11/2*12/1*13/1*14/1*15/1*16/1*17/2*18/2*19/2*20/7*1
 100 2/1*3/2*4/3*5/1*6/4*7/1*8/5*9/1*10/6*11/1*12/7*13/1*14/8*15/1*16/9*17/1*18/10*19/1*20/11*21/2*22/2*23/12*24/3*25/4*26/5*27/2*28/6*29/2*30/7*31/2*32/8*33/2*34/9*35/2*36/10*37/2*38/11*39/2*40/12*41/3*42/3*43/13*44/4*45/13*46/5*47/6*48/7*49/3*50/8*51/3*52/9*53/3*54/10*55/3*56/11*57/3*58/12*59/3*60/13*61/4*62/4*63/14*64/5*65/14*66/6*67/14*68/7*69/8*70/9*71/4*72/10*73/4*74/11*75/4*76/12*77/4*78/13*79/4*80/14*81/5*82/5*83/15*84/6*85/15*86/7*87/15*88/8*89/15*90/9*91/10*92/11*93/5*94/12*95/5*96/13*97/5*98/14*99/5*100/15*101/6*102/6*103/16*104/7*105/16*106/8*107/16*108/9*109/16*110/10*111/16*112/11*113/12*114/13*115/6*116/14*117/6*118/15*119/6*120/16*121/7*122/7*123/17*124/8*125/17*126/9*127/17*128/10*129/17*130/11*131/17*132/12*133/17*134/13*135/14*136/15*137/7*138/16*139/7*140/17*141/8*142/8*143/18*144/9*145/18*146/10*147/18*148/11*149/18*150/12*151/18*152/13*153/18*154/14*155/18*156/15*157/16*158/17*159/8*160/18*161/9*162/9*163/19*164/10*165/19*166/11*167/19*168/12*169/19*170/13*171/19*172/14*173/19*174/15*175/19*176/16*177/19*178/17*179/18*180/19*181/10*182/20*183/20*184/20*185/20*186/20*187/20*188/20*189/20*190/20*1

И, с помощью канала через bc (и добавление вычисления F (1000):

$ time for i in {0..15} 100 1000; do printf "%4d " $i;./cg70892g<<<$i|bc;done
   0 1
   1 1
   2 2
   3 6
   4 24
   5 120
   6 720
   7 5040
   8 40320
   9 362880
  10 3628800
  11 119750400
  12 1816214400
  13 43589145600
  14 1111523212800
  15 30169915776000
 100 89331628085599251432057142025907698637261121628839475101631496666431\
15835656928284205265561741805657733401084399630568002336920697364324\
98970890135552420133438596044287494400000000
1000 45200893173828954313462564749564394748293201305047605660842814405721\
30092686078003307269244907986874394907789568742409099103180981532605\
76231293886961761709984429587680151617686667512237878219659252822955\
55855915137324368886659115209005785474446635212359968384367827713791\
69355041534558858979596889046036904489098979549000982849236697235269\
84664448178907805505235469406005706911668121136625035542732996808166\
71752374116504390483133390439301402722573240794966940354106575288336\
39766175522867371509169655132556575711715087379432371430586196966835\
43089966265752333684689143889508566769950374797319794056104571082582\
53644590587856607528082987941397113655371589938050447115717559753757\
79446152023767716192400610266474748572681254153493484293955143895453\
81280908664541776100187003079567924365036116757255349569574010994259\
42252682660514007543791061446917037576087844330206560326832409035999\
90672829766080114799705907407587600120545365651997858351981479835689\
62520355320273524791310387643586826781881487448984068291616884371091\
27306575532308329716263827084514072165421099632713760304738427510918\
71188533274405854336233290053390700237606793599783757546507331350892\
88552594944038125624374807070741486495868374775574664206439929587630\
93667017165594552704187212379733964347029984154761167646334095514093\
41014074159155080290000223139198934433986437329522583470244030479680\
80866686589020270883335109556978058400711868633837851169536982150682\
22082858700246313728903459417761162785473029666917398283159071647546\
25844593629926674983035063831472139097788160483618679674924756797415\
01543820568689780263752397467403353950193326283322603869951030951143\
12095550653333416019778941123095611302340896001090093514839997456409\
66516109033654275890898159131736630979339211437991724524614375616264\
98121300206207564613016310794402755159986115141240217861695468584757\
07607748055900145922743960221362021598547253896628914921068009536934\
53398462709898222067305585598129104976359039062330308062337203828230\
98091897165418693363718603034176658552809115848560316073473467386230\
73804128409097707239681863089355678037027073808304307450440838875460\
15170489461680451649825579772944318869172793737462142676823872348291\
29912605105826175323042543434860948610529385778083808434502476018689\
05150440954486767102167489188484011917026321182516566110873814183716\
30563399848922002627453188732598763510259863554716922484424965400444\
85477201353937599094224594031100637903407963255597853004241634993708\
88946719656130076918366596377038503741692563720593324564994191848547\
42253991635763101712362557282161765775758580627861922528934708371322\
38741942406807912441719473787691540334781785897367428903185049347013\
44010772740694376407991152539070804262207515449370191345071234566501\
33117923283207435702471401696679650483057129117719401161591349048379\
16542686360084412816741479754504459158308795445295721744444794851033\
08800000000

real    0m0.246s
user    0m0.213s
sys     0m0.055s

Это вычисленное F (5000) - число из 18 592 цифр - менее чем за 10 секунд.

$ time ./cg70892g3<<<5000|BC_LINE_LENGTH=0 bc|wc -c
18593

real    0m9.274s
user    0m9.273s
sys     0m0.005s

3

Perl 6, 117 байт

say $_ <2??1!!permutations(+[(my@n=^$_ .join.comb)]).elems÷[*] ([*] 2..$_ for @n.classify(&unique).values)for lines

и в более читаемой моде

for (lines) -> $number {
    say 1 and next if $number < 2;
    my @digits = (^$number).join.comb;
    my @duplicates = @digits.classify(&unique).values;
    my $unique_permutations = permutations(+@digits).elems ÷ [*] ([*] 2..$_ for @duplicates);
    say $unique_permutations;
}

3

Perl 5, 108 байт

sub f{eval join"*",@_,1}push@a,/./g for 0..<>-1;for$i(0..9){$b[$i]=grep/$i/,@a}say f(1..@a)/f map{f 1..$_}@b

Большое спасибо dev-null за то, что он сэкономил мне 17 байт, и japhy за идею факториала.


3

05AB1E , 13 12 11 байтов

ÝD¨SāPr¢!P÷

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

Ý             # range [0..input]
 D            # duplicate
  ¨           # drop the last element
   S          # split into digits
    ā         # length range: [1..number of digits]
     P        # product (effectively a factorial)
      r       # reverse the stack
       ¢      # count occurences of each number in the list of digits
        !     # factorial of each count
         P    # product of those
          ÷   # divide the initial factorial by this product

3

Python 2 , 123 байта

import math
i,b,F="".join(map(str,range(input()))),1,math.factorial
for x in range(10):b*=F(i.count(`x`))
print F(len(i))/b

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

  1. Преобразовать rangeвходные данные в одну строку
  2. Проверьте, сколько раз каждое из чисел от 0 до 9 появляется в строке и получите факториал для каждого, затем умножьте их вместе
  3. Разделите факториал длины строки на число, рассчитанное на шаге 2

2

PowerShell, 125 байт

(1..(($b=0..($args[0]-1)-join'').Length)-join'*'|iex)/((0..9|%{$c=[regex]::Matches($b,$_).count;1..($c,1)[!$c]})-join'*'|iex)

Принимает входные данные $args[0], вычитает 1, строит диапазон целых чисел из 0..этого числа, -joinкоторые вместе в строку, и сохраняет его как $b. Мы берем .Lengthэту строку, строим другой диапазон из 1..этой длины, -joinвместе с этими целыми числами *, а затем передаем это Invoke-Expression(аналогичноeval ). Другими словами, мы построили факториал длины числовой последовательности на основе входных данных. Это наш числитель.

Мы делим это /на ...

Наш знаменатель, который создается путем взятия диапазона 0..9и отправки его через цикл for |%{...}. На каждой итерации мы устанавливаем вспомогательную переменную, $cравную числу раз, в течение которых текущая цифра $_появляется, $bблагодаря вызову .NET,[regex]::matches связанному с .countатрибутом. Затем мы строим новый диапазон от 1..этого значения до тех пор, пока оно не равно нулю. Да, во многих случаях это приведет к диапазону 1..1, который оценивается как справедливый 1. Мы берем все это и -joinих вместе *, а затем передаем это Invoke-Expressionснова. Другими словами, мы построили произведение факториалов на число вхождений каждой цифры.


NB

Обрабатывает ввод до 90без проблем и значительно меньше, чем за секунду.

PS C:\Tools\Scripts\golfing> .\rearranging-the-sequence.ps1 90
1.14947348910454E+159

PS C:\Tools\Scripts\golfing> Measure-Command {.\rearranging-the-sequence.ps1 90} | FL TotalMilliseconds
TotalMilliseconds : 282.587

... кроме того, это приводит Infinityк выводу, поскольку длина переставляемой строки приводит к тому, 170!что соответствует doubleтипу данных ( 7.25741561530799E+306), но 171!не соответствует. PowerShell имеет ... причуду ..., которая автоматически повышает [int]значение [double]в случае переполнения (при условии, что вы явно не приводили переменную для начала). Нет, я не знаю, почему это не относится к [long]целочисленным значениям.

Если бы мы выполнили какое-то явное приведение и манипуляцию (например, используя [uint64]64-разрядные целые числа без знака), мы могли бы получить это выше, но это значительно увеличило бы код, так как нам нужно было бы увеличить длину до 170 с помощью условных выражений, а затем перезаписать каждое умножение оттуда и далее. Поскольку в задаче не указан верхний диапазон, я предполагаю, что этого будет достаточно.


2

Perl6

perl6 -e 'sub p ($a) { my $x = $a.join.comb.classify(+*).values.map(*.elems).classify(+*).values.flatmap(*.list).flatmap((2..+*).list); my $y = 2..$a[*-1]; [/] $x.list * [*] $y.list }; p([1..11]).say'

Скорее разгульный на данный момент - нужно спать сейчас.


2

Groovy, 156 байтов

def f(n){def s=(0..n-1).join('')
0==n?1:g(s.size())/s.inject([:]){a,i->a[i]=a[i]?a[i]+1:1;a}*.value.inject(1){a,i->a*g(i)}}
BigInteger g(n){n<=1?1:n*g(n-1)}

Мое скромное первое решение Code Golf. Вы можете проверить это здесь.

А вот более читаемая версия:

def f(n) {
  def s = (0..n - 1).join('')                       // Store our concatented range, s
  0 == n ? 1 :                                      // Handle annoying case where n = 0
    fact(s.size()) / s.inject([:]) {                // Divide s.size()! by the product of the values we calculate by...
      a, i ->                                       // ...reducing into a map...
        a[i] = a[i] ? a[i] + 1 : 1                  // ...the frequency of each digit
        a                                           // Our Groovy return statement
    }*.value.inject(1) { a, i -> a * fact(i) }      // Finally, take the product of the factorial of each frequency value
}

BigInteger fact(n) { n <= 1 ? 1 : n * fact(n - 1) } // No built-in factorial function...

Довольно просто, но для меня было несколько важных моментов:

  • Выполнение инъекции / редукции из массива charsв Map<Character, Integer>. Это все еще было немного сложным из-за отсутствия значения по умолчанию для значений карты. Это сомнение возможно, но если на карте по умолчанию все значения равны 0, я мог бы избежать троичной системы, которая необходима, чтобы избежать NPE.

  • Оператор распространения Groovy (например }*.value) всегда интересно использовать

Однако досадной особенностью была необходимость объявить функцию факториала с типом возвращаемого значения BigInteger. У меня сложилось впечатление, что Groovy обернул все числа в BigIntegerили BigDecimal, но это может быть не так, когда дело доходит до возвращаемых типов. Мне придется больше экспериментировать. Если этот тип возврата явно не указан, мы очень быстро получаем некорректные значения факториала.


2

J, 33 байта

(#(%*/)&:!&x:#/.~)@([:;<@":"0)@i.

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

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

   f =: (#(%*/)&:!&x:#/.~)@([:;<@":"0)@i.
   (,.f"0) i. 16
 0              1
 1              1
 2              2
 3              6
 4             24
 5            120
 6            720
 7           5040
 8          40320
 9         362880
10        3628800
11      119750400
12     1816214400
13    43589145600
14  1111523212800
15 30169915776000

2

R, 118 байт

Около 8 месяцев опоздал на вечеринку, но подумал, что мне стоит попробовать, потому что это было интересно.

function(n,x=as.numeric(el(strsplit(paste(1:n-1,collapse=""),""))),F=factorial)`if`(n,F(sum(1|x))/prod(F(table(x))),1)

Попробуйте это на R-Fiddle

Разъяснения

  1. Сгенерируйте вектор 0 ... n-1и сверните его в строку:paste(1:n-1,collapse="")
  2. Разбить строку на цифры и преобразовать в числовое значение (сохранить как x):x=as.numeric(el(strsplit(...,"")))
  3. Чтобы вычислить числитель, мы просто делаем, factorial(sum(1|x))что просто#digits!
  4. Чтобы вычислить знаменатель, мы используем tableдля построения таблицы сопряженности, в которой перечислены частоты. В случае F (12) сгенерированная таблица:

    0 1 2 3 4 5 6 7 8 9 
    2 4 1 1 1 1 1 1 1 1 
    
  5. Что означает, что мы можем взять использование factorial()(которое, кстати, векторизовано) на счетчике и просто взять продукт:prod(factorial(table(x)))

Примечание: шаги 4 и 5 выполняются только в n>0случае возврата 1.


1

Mathematica, 65 байт

(Tr@IntegerLength[a=Range@#-1]+1)!/Times@@(Total[DigitCount@a]!)&

Возможно, будет дальше в гольф.




1

Желе , 11 байт

15-байтовое желе от Dennis, отвечающее ...

ḶDFµW;ĠẈ!:/

Монадическая ссылка, принимающая неотрицательное целое число, которое дает положительное целое число.

Попробуйте онлайн! Или посмотрите набор тестов .

Как?

ḶDFµW;ĠẈ!:/ - Link: non-negative integer, N   e.g. 12
Ḷ           - lowered range            [0,1,2,3,4,5,6,7,8,9,10,11]
 D          - to decimal (vectorises)  [[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[1,0],[1,1]]
  F         - flatten                  [0,1,2,3,4,5,6,7,8,9,1,0,1,1]
   µ        - start a new monadic chain - i.e. f(that)
    W       - wrap in a list           [[0,1,2,3,4,5,6,7,8,9,1,0,1,1]]
      Ġ     - group indices by values  [[1,12],[2,11,13,14],3,4,5,6,7,8,9,10]
     ;      - concatenate              [[0,1,2,3,4,5,6,7,8,9,1,0,1,1],[1,12],[2,11,13,14],3,4,5,6,7,8,9,10]
       Ẉ    - length of each           [14,2,4,1,1,1,1,1,1,1,1]
        !   - factorial (vectorises)   [87178291200,2,24,1,1,1,1,1,1,1,1]
          / - reduce by:
         :  -   integer division       1816214400


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.