23
\$\begingroup\$

Introduction

Let's observe the following sequence (non-negative integers):

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

For example, let's take the first three numbers. These are 0, 1, 2. The numbers used in this sequence can be ordered in six different ways:

012   120
021   201
102   210

So, let's say that F(3) = 6. Another example is F(12). This contains the numbers:

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

Or the concatenated version:

01234567891011

To find the number of ways to rearrange this, we first need to look at the length of this string. The length of this string is 14. So we compute 14!. However, for example the ones can exchange places without disrupting the final string. There are 2 zeroes, so there are 2! ways to exhange the zeroes without disrupting the order. There are also 4 ones, so there are 4! ways to switch the ones. We divide the total by these two numbers:

This has 14! / (4! × 2!) = 1816214400 ways to arrange the string 01234567891011. So we can conclude that F(12) = 1816214400.

The task

Given N, output F(N). For the ones who don't need the introduction. To compute F(N), we first concatenate the first N non-negative integers (e.g. for N = 12, the concatenated string would be 01234567891011) and calculate the number of ways to arrange this string.

Test cases

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

Note

Computing the answer must be computed within a time limit of 10 seconds, brute-forcing is disallowed.

This is , so the submission with the least amount of bytes wins!

\$\endgroup\$
7
  • \$\begingroup\$ Is the output for 10 correct? It feels like it should be less than 10!, since that's where the repeating digits start. \$\endgroup\$
    – Geobits
    Commented Feb 3, 2016 at 22:02
  • \$\begingroup\$ @Geobits The first 10 digits are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Ten different digits, so the result is 10!. \$\endgroup\$
    – Adnan
    Commented Feb 3, 2016 at 22:03
  • \$\begingroup\$ Ah, right. I think the 0 case was throwing my count off (stupid empty strings). \$\endgroup\$
    – Geobits
    Commented Feb 3, 2016 at 22:05
  • 1
    \$\begingroup\$ No need to worry about that anymore. The loophole proposal was at +4 when I posted the comment. It is at +9 now. \$\endgroup\$
    – Dennis
    Commented Feb 4, 2016 at 16:09
  • 1
    \$\begingroup\$ Here's an interesting math question about this puzzle: What is the value of F(N) relative to N!? There are a number of values of N for which F(N)/F(N-1) < N, but it is usually slightly greater. I'm pretty sure that F(N) is not O(N!) and that log F(N) is O(log N!) but those are just hunches... \$\endgroup\$
    – rici
    Commented Feb 5, 2016 at 3:10

27 Answers 27

10
\$\begingroup\$

ES6, 118 81 78 bytes

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

Someone's bound to tell me there's a shorter way of concatenating the numbers up to n.

Saved a cool 37 bytes by taking @edc65's idea and running it on steroids. (Save an extra byte by using '|' instead of && but that limits the result to 31 bits.)

Edit: Saved 3 further bytes again thanks to @edc65.

\$\endgroup\$
6
  • \$\begingroup\$ Did not find a way to shorten the digits concatenation. But all the rest can be shorter \$\endgroup\$
    – edc65
    Commented Feb 3, 2016 at 23:54
  • \$\begingroup\$ Save 2 bytes with reduce: n=>[...[...Array(n).keys()].join``].reduce((r,c,i)=>r*++i/(o[c]=-~o[c]),1,o=[]) \$\endgroup\$
    – user81655
    Commented Feb 4, 2016 at 11:43
  • 1
    \$\begingroup\$ Wow! but 78 is better: n=>[...[...Array(n).keys()].join``].map(c=>r/=(o[c]=-~o[c])/i++,o=[],i=r=1)&&r \$\endgroup\$
    – edc65
    Commented Feb 4, 2016 at 11:52
  • 1
    \$\begingroup\$ @edc65 r/=(...)/i++ is more accurate than r*=i++/(...)? That's the most ludicrous golf I've ever seen! \$\endgroup\$
    – Neil
    Commented Feb 4, 2016 at 13:31
  • 2
    \$\begingroup\$ I had to stop for a moment, because I thought you had a regex in there. \$\endgroup\$ Commented Feb 6, 2016 at 5:10
7
+200
\$\begingroup\$

APL (Dyalog Extended), 13 bytes

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

Try it online!

A full program. Uses ⎕IO←0.

How it works

×/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

The multinomial calculation comes from the following fact:

$$ \frac{(a_1 + a_2 + \cdots + a_n)!}{a_1! a_2! \cdots a_n!} = \frac{(a_1 + a_2)!}{a_1! a_2!} \times \frac{(a_1 + a_2 + \cdots + a_n)!}{(a_1 + a_2)! a_3! \cdots a_n!} $$

$$ = \frac{(a_1 + a_2)!}{a_1! a_2!} \times \frac{(a_1 + a_2 + a_3)!}{(a_1 + a_2)! a_3!} \times \frac{(a_1 + a_2 + \cdots + a_n)!}{(a_1 + a_2 + a_3)! \cdots a_n!} $$

$$ = \cdots = \binom{a_1 + a_2}{a_1} \binom{a_1 + a_2 + a_3}{a_1 + a_2} \cdots \binom{a_1 + \cdots + a_n}{a_1 + \cdots + a_{n-1}} $$

\$\endgroup\$
2
  • 1
    \$\begingroup\$ And this is why programmers should learn mathematics. \$\endgroup\$
    – Anonymous
    Commented Nov 28, 2019 at 17:16
  • \$\begingroup\$ @Anonymous … and use a mathematically inclined programming language. \$\endgroup\$
    – Adám
    Commented Dec 1, 2019 at 23:04
5
\$\begingroup\$

Jelly, 17 15 bytes

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

Try it online! or verify all test cases at once.

How it works

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.
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Is this really Jelly? I see to many ASCII characters :-P \$\endgroup\$
    – Luis Mendo
    Commented Feb 3, 2016 at 22:36
  • 4
    \$\begingroup\$ They always manage to sneak in somehow... \$\endgroup\$
    – Dennis
    Commented Feb 4, 2016 at 0:03
5
\$\begingroup\$

MATL, 21 bytes

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

Try it online!

Explanation

: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
 
\$\endgroup\$
3
  • \$\begingroup\$ @Adnan Solved. And with fewer bytes :-) \$\endgroup\$
    – Luis Mendo
    Commented Feb 3, 2016 at 22:19
  • \$\begingroup\$ Looks very nice! :) \$\endgroup\$
    – Adnan
    Commented Feb 3, 2016 at 22:20
  • \$\begingroup\$ @Adnan Thanks! I've added an explanation \$\endgroup\$
    – Luis Mendo
    Commented Feb 3, 2016 at 22:27
5
\$\begingroup\$

Python 2, 142 137 101 97 bytes

(Thanks @adnan for the suggestion about input)

(Applied the incremental calculation from the C version)

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

Original version using factorial

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)))

Really, the only golfing in the above is calling math.factorial F and leaving out some spaces, so there is probably a shorter python solution.

If explanation is needed, v maintains a count of the frequency of each digit; the count is updated for each digit in each number in the indicated range.

In the original version, we compute the number of permutations using the standard formula (Σfi)!/π(fi!). For the current version, this computation is done incrementally by distributing the multiplies and divides as we see the digits. It might not be obvious that the integer divide will always be exact, but it is easy to prove based on the observation that each division by k must follow k multiplies of consecutive integers, so one of those multiplies must be divisible by k. (That's an intuition, not a proof.)

The original version is faster for large arguments because it does only 10 bignum divides. Although dividing a bignum by a small integer is faster than dividing a bignum by a bignum, when you have thousands of bignum divides, it gets a bit sluggish.

\$\endgroup\$
2
  • \$\begingroup\$ f=f*sum(v)/v[k] --> f*=sum(v)/v[k] saves a byte \$\endgroup\$ Commented Feb 6, 2016 at 8:30
  • \$\begingroup\$ @superflux: but it is not the same meaning. \$\endgroup\$
    – rici
    Commented Feb 6, 2016 at 11:15
5
\$\begingroup\$

Python 2, 197 Bytes (edit: saved 4 bytes, thanks Thomas Kwa!)

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
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Welcome to Programming Puzzles and Code Golf! This answer was flagged as VLQ (very low quality), I suspect because it does not contain any explanation or ungolfed version, which are the norm here. Assuming your answer works, and you improve it from being "code only", it seems quite good! \$\endgroup\$
    – cat
    Commented Feb 4, 2016 at 2:53
  • \$\begingroup\$ range(0,10) can be range(10). \$\endgroup\$
    – lirtosiast
    Commented Feb 4, 2016 at 3:09
4
\$\begingroup\$

CJam, 21 19 bytes

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

Test it here.

Explanation

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.
\$\endgroup\$
3
\$\begingroup\$

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)

Test

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>

\$\endgroup\$
4
  • \$\begingroup\$ Isn't k[c]=~-k[c] synonymous with --k[c]? \$\endgroup\$
    – rgajrawala
    Commented Feb 4, 2016 at 0:09
  • 1
    \$\begingroup\$ @usandfriends no, when k[c] is undefined --k[c] is NaN \$\endgroup\$
    – edc65
    Commented Feb 4, 2016 at 0:16
  • \$\begingroup\$ Ooh, nice array of factorials. \$\endgroup\$
    – Neil
    Commented Feb 4, 2016 at 0:23
  • \$\begingroup\$ ... although you don't need it. See my latest update. \$\endgroup\$
    – Neil
    Commented Feb 4, 2016 at 8:52
3
\$\begingroup\$

Pyth, 18 bytes

/F.!M+lJ.njRTQ/LJT

Try it online: Demonstration

/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
\$\endgroup\$
3
\$\begingroup\$

Haskell, 92 bytes

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

Usage example: h 12 -> 1816214400.

How it works

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
\$\endgroup\$
3
\$\begingroup\$

C, 236 174 138 121 bytes

Much credit to rici, for massive reduction of bytes.

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 */
}

Try it here.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ You could save 43 characters by not mucking around with -lm. Just count the digits as you find them: #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);} \$\endgroup\$
    – rici
    Commented Feb 5, 2016 at 15:33
  • \$\begingroup\$ You could also count them in the loop where you compute d: for(;m<10;)s+=b[m],d*=f(b[m++]) but I think that's a couple more bytes. \$\endgroup\$
    – rici
    Commented Feb 5, 2016 at 15:38
  • \$\begingroup\$ That's brilliant. I'll combine with my current golfing efforts and edit. \$\endgroup\$ Commented Feb 5, 2016 at 15:38
  • \$\begingroup\$ Nice: take a look at mine to see how to integrate the factorial computation into the original loop, which has the advantage of working on a slightly larger range if you don't have arbitrary-precision arithmetic. I think that's another 20 bytes to shave. \$\endgroup\$
    – rici
    Commented Feb 5, 2016 at 16:11
3
\$\begingroup\$

C/bc, 233 121 112 bytes (assuming 3 byte penalty for |bc)

  1. Inspired by Cole Cameron, removed the hacky character manipulation and just do arithmetic on the argument value.

  2. Changed to scanf from using arg vector.

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

Needs bc to actually do the arbitrary precision computation.

Ungolfed and warning free:

#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 */
}

Illustrated (which I trust shows the algorithm):

$ 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

And, with the pipe through bc (and adding the computation of 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

This computed F(5000) -- an 18,592-digit number -- in under 10 seconds.

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

real    0m9.274s
user    0m9.273s
sys     0m0.005s
\$\endgroup\$
3
\$\begingroup\$

Perl 6, 117 bytes

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

and in a more readable fasion

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;
}
\$\endgroup\$
3
\$\begingroup\$

Perl 5, 108 bytes

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

Many thanks to dev-null for saving me 17 bytes, and to japhy for the factorial idea.

\$\endgroup\$
0
3
\$\begingroup\$

05AB1E, 13 12 11 bytes

ÝD¨SāPr¢!P÷

Try it online!

Ý             # 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
\$\endgroup\$
3
\$\begingroup\$

Python 2, 123 bytes

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

Try it online!

  1. Convert the range of the input to a single string
  2. Check how many times each of the numbers from 0 to 9 appears in the string and get the factorial for each then multiply them together
  3. Divide the factorial of the length of the string by the number calculated in step 2
\$\endgroup\$
2
\$\begingroup\$

PowerShell, 125 bytes

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

Takes input $args[0], subtracts 1, builds a range of integers from 0.. that number, -joins that together into a string, and saves it as $b. We take the .Length of that string, build another range from 1.. that length, -join those integers together with *, then pipe that to Invoke-Expression (similar to eval). In other words, we've constructed the factorial of the length of the number sequence based on the input. That's our numerator.

We divide that / by ...

Our denominator, which is constructed by taking a range 0..9 and sending it through a for-loop |%{...}. Each iteration, we set a helper variable $c equal to the number of times the current digit $_ appears within $b thanks to the .NET [regex]::matches call coupled with the .count attribute. We then construct a new range from 1.. up to that value, so long as it's non-zero. Yes, in many instances, this will result in a range 1..1, which evaluates to just 1. We take all of those and -join them together with *, then pipe that to Invoke-Expression again. In other words, we've constructed the product of the factorials of the number of occurrences of each digit.


NB

Handles input up to 90 without issue and in significantly less than a second.

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

... beyond that results in Infinity as output, since the length of the permutable string results in 170! which fits in the double datatype (7.25741561530799E+306), but 171! doesn't. PowerShell has a ... quirk ... that automatically up-casts from [int] to [double] in the case of overflow (provided you didn't explicitly cast the variable to start with). No, I don't know why it doesn't go to [long] for integer values.

If we did some explicit casting and manipulation (e.g., using [uint64], for unsigned 64-bit integers), we could get that higher, but it would significantly bloat the code as we would need to range up to 170-length with conditionals and then recast each multiplication from there onward. As the challenge doesn't specify an upper range, I'm presuming this to be adequate.

\$\endgroup\$
2
\$\begingroup\$

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'

Rather ungolfed at the moment - need sleep now.

\$\endgroup\$
2
\$\begingroup\$

Groovy, 156 bytes

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

My humble first Code Golf solution. You can test it here.

And here's a more readable version:

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...

Quite straightforward, but there were a couple highlights for me:

  • Performing an inject/reduce from an array of chars to a Map<Character, Integer>. This was still a little complicated by the lack of a default value for the map values. This doubt this is possible, but if the map defaulted all values to 0, I could avoid the ternary which is necessary to avoid an NPE.

  • The Groovy spread operator (e.g. }*.value) is always fun to use

On annoying feature, however, was the necessity to declare the factorial function with the return type BigInteger. I was under the impression that Groovy wrapped all numerics in BigInteger or BigDecimal, but this might not be the case when it comes to return types. I'll have to experiment more. Without this return type explicitly stated, we get incorrect factorial values very quickly.

\$\endgroup\$
2
\$\begingroup\$

J, 33 bytes

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

Converts the range into a string of digits, counts each digits, and applies the multinomial coefficient to compute the result.

Usage

   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
\$\endgroup\$
2
\$\begingroup\$

R, 118 bytes

About 8 months late to the party but thought I'd give it a go because it looked like an interesting challenge.

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)

Try it on R-fiddle

Explained

  1. Generate vector 0 ... n-1 and collapse it to a string: paste(1:n-1,collapse="")

  2. Split string into its digits and convert to numeric(store as x): x=as.numeric(el(strsplit(...,"")))

  3. To calculate the numerator we simply do factorial(sum(1|x)) which is just #digits!

  4. To calculate the denominator we make use of table to construct a contingency table that list the frequencies. In the case of F(12) the table generated is:

    0 1 2 3 4 5 6 7 8 9 
    2 4 1 1 1 1 1 1 1 1 
    
  5. Which means we can take the use factorial() (which by the way is vectorized) on the count and simply take the product: prod(factorial(table(x)))

Note: step 4 and 5 are only carried through if n>0 otherwise return 1.

\$\endgroup\$
1
\$\begingroup\$

Mathematica, 65 bytes

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

Could probably be golfed further.

\$\endgroup\$
1
\$\begingroup\$

Ruby, 64 bytes

->n,*w{a=1;[*0...n].join.chars{|d|a=a*(w<<d).size/w.count(d)};a}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Stax, 12 bytes

éÄ\↑≈g→FP○░→

Run and debug it at staxlang.xyz!

Unpacked (14 bytes) and explanation:

r$c%|Fso:GF|F/
r                 Range [0..input)
 $                Stringify each and concat
  c               Copy atop the stack
   %|F            Factorial of length
      s           Swap original back to top
       o          Sort
        :G        Run lengths
          F       For each:
           |F       Factorial
             /      Divide running quotient by this factorial
                  Implicit print
\$\endgroup\$
1
\$\begingroup\$

Jelly, 11 bytes

Golfed Dennis' 15 byte Jelly answer...

ḶDFµW;ĠẈ!:/

A monadic Link accepting a non-negative integer which yields a positive integer.

Try it online! Or see the test suite.

How?

Ḷ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
\$\endgroup\$
0
\$\begingroup\$

Python 2, 190 bytes

from collections import*
g,n=range,int(input())
p=lambda r:reduce(lambda x,y:x*y,r,1)
f=lambda n:p(g(1,n+1))
s=''.join(str(i)for i in g(n))
c=Counter(s)
print(f(len(s))/p(f(c[i])for i in c))

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Python 2, 134 bytes

s="".join(map(str,range(input())))
n=d=1
for i in range(1,len(s)+1):n*=i;d*=i**len([c for c in range(10)if s.count(`c`)>=i])
print n/d

Try it online!

An alternate approach...

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.