Nombre de surjections

16

Tâche

Étant donné 2 entiers positifs net k, où n > k, sortir le nombre de surjections d'un ensemble d' néléments distinguables à un ensemble d' kéléments distinguables.

Définition

Une fonction f: S → T est appelée surjection si pour chaque t∈T il y a s∈S tel que f (s) = t.

Exemple

Quand n=3et k=2, la sortie est 6, car il y a des 6surjections de {1,2,3}à {1,2}:

  1. 1↦1, 2↦1, 3↦2
  2. 1↦1, 2↦2, 3↦1
  3. 1↦1, 2↦2, 3↦2
  4. 1↦2, 2↦1, 3↦1
  5. 1↦2, 2↦1, 3↦2
  6. 1↦2, 2↦2, 3↦1

Cas de test

n k output
5 3 150
8 4 40824
9 8 1451520

Référence

Notation

C'est du . La réponse la plus courte en octets l'emporte.

Des échappatoires standard s'appliquent.

Leaky Nun
la source
11
Une définition de la surjection serait bien.
Stewie Griffin
3
Est-il intentionnel que n ne puisse pas être égal à k ?
Dennis
1
@Dennis J'aime exclure tous les cas de bord possibles de mes défis
Leaky Nun
3
Cela semble être un cas de bord important à inclure. Je suppose que la plupart des réponses qui fonctionnent pour n> k fonctionneront également pour n == k, mais cela pourrait permettre un golf sournois quelque part
dylnan
@ quiconque a voté pour fermer quelle est votre raison?
dylnan

Réponses:

5

Gelée , 5 4 octets

ṗṬML

Il s'agit d'une solution de force brute O (k n ) .

Essayez-le en ligne!

Comment ça fonctionne

ṗṬML  Main link. Left argument: k. Right argument: n.

ṗ     Cartesian power; yield the list of all n-tuples over {1, ..., k}.
      Each tuple represents a (not necessarily surjective) function from
      {1, ..., n} to {1, ..., k}.
 Ṭ    Apply the "untruth" atom to each tuple.
      Ṭ maps a list of indices to an array with 1's at those indices, and exactly
      as many zeroes as needed to build the array.
      Examples:
           [1, 2, 3, 3, 3] -> [1, 1, 1]
           [1, 3, 5]       -> [1, 0, 1, 0, 1]
           [2, 6, 2, 4, 4] -> [0, 1, 0, 1, 0, 1]
  M   Yield all indices of maximal elements, i.e., all indices of [1] * k.
   L  Take the length.
Dennis
la source
4

Haskell , 48 octets

s(_,1)=1
s(1,_)=0
s(m,n)=n*(s(m-1,n-1)+s(m-1,n))

Essayez-le en ligne!

Pourquoi le nombre de surjection s(m,n)=n*s(m-1,n-1)+n*s(m-1,n)?

afin de récolter des nimages, je peux soit

  • presser une [m]création singleton dans l'une des nfrontières entourant les n-1groupes
  • ou ajouter mon nouveau mdans l'un des ngroupes déjà existants de[1..m-1]

Haskell , 38 octets

m#n|n<2=1|m<2=0|o<-m-1=n*(o#(n-1)+o#n)

Essayez-le en ligne!

Roman Czyborra
la source
2
38 octets en utilisant un opérateur infixe: essayez-le en ligne!
Laikoni
4

Lean , 66 octets

def s:_->nat->nat|(m+1)(n+1):=(n+1)*(s m n+s m(n+1))|0 0:=1|_ _:=0

Essayez-le en ligne!


Preuve d'exactitude

Essayez-le en ligne!


Explication

Libérons la fonction:

def s : nat->nat->nat
| (m+1) (n+1) := (n+1)*(s m n + s m (n+1))
| 0     0     := 1
| _     _     := 0

La fonction est définie par la correspondance de motifs et la récursivité, qui ont toutes deux un support intégré.

Nous définissons s(m+1, n+1) = (n+1) * (s(m, n) + s(m, n+1)et s(0, 0) = 1, qui laisse ouvert s(m+1, 0)et s(0, n+1), qui sont tous deux définis pour être0 par le dernier cas.

Lean utilise la syntaxe de calcul lamdba, tout s m ncomme s(m, n).


Maintenant, la preuve d'exactitude: je l'ai dit de deux manières:

def correctness : ∀ m n, fin (s m n) ≃ { f : fin m → fin n // function.surjective f } :=
λ m, nat.rec_on m (λ n, nat.cases_on n s_zero_zero (λ n, s_zero_succ n)) $
λ m ih n, nat.cases_on n (s_succ_zero m) $ λ n,
calc fin (s (nat.succ m) (nat.succ n))
   ≃ (fin (n + 1) × (fin (s m n + s m (n + 1)))) :
  (fin_prod _ _).symm
... ≃ (fin (n + 1) × (fin (s m n) ⊕ fin (s m (n + 1)))) :
  equiv.prod_congr (equiv.refl _) (fin_sum _ _).symm
... ≃ (fin (n + 1) × ({f : fin m → fin n // function.surjective f} ⊕
         {f : fin m → fin (n + 1) // function.surjective f})) :
  equiv.prod_congr (equiv.refl _) (equiv.sum_congr (ih n) (ih (n + 1)))
... ≃ {f // function.surjective f} : s_aux m n

def correctness_2 (m n : nat) : s m n = fintype.card { f : fin m → fin n // function.surjective f } :=
by rw fintype.of_equiv_card (correctness m n); simp

Le premier est ce qui se passe vraiment: une bijection entre [0 ... s(m, n)-1]et les surjections de [0 ... m-1]sur[0 ... n-1] .

Le second est la façon dont il est généralement indiqué, s(m, n)c'est la cardinalité des surjections de [0 ... m-1]sur [0 ... n-1].


Lean utilise la théorie des types comme fondement (au lieu de la théorie des ensembles). En théorie des types, chaque objet a un type qui lui est inhérent. natest le type de nombres naturels, et la déclaration qui 0est un nombre naturel est exprimée par 0 : nat. Nous disons que 0c'est de type nat, et cela nata0 comme habitant.

Les propositions (déclarations / assertions) sont également des types: leur habitant est une preuve de la proposition.


  • def: Nous allons introduire une définition (car une bijection est vraiment une fonction, pas seulement une proposition).

  • correctness: le nom de la définition

  • ∀ m n: pour chaque met n(Lean déduit automatiquement que leur type est nat, à cause de ce qui suit).

  • fin (s m n)est le type de nombres naturels inférieur à s m n. Pour faire un habitant, on fournit un nombre naturel et une preuve qu'il est plus petit que s m n.

  • A ≃ B: bijection entre le type Aet le type B. Dire la bijection est trompeur, car il faut en fait fournir la fonction inverse.

  • { f : fin m → fin n // function.surjective f }le type de surjections de fin mà fin n. Cette syntaxe construit un sous-type à partir du type fin m → fin n, c'est-à-dire le type de fonctions de fin mà fin n. La syntaxe est { var : base type // proposition about var }.

  • λ m: ∀ var, proposition / type involving varest vraiment une fonction qui prend varen entrée, donc λ mintroduit l'entrée. ∀ m n,est raccourci pour∀ m, ∀ n,

  • nat.rec_on m: faire récursivité sur m. Pour définir quelque chose pour m, définir la chose pour 0et puis donner la chose pour k, construire la chose pour k+1. On remarquerait que cela est similaire à l'induction, et c'est en fait le résultat de la correspondance Church-Howard . La syntaxe est nat.rec_on var (thing when var is 0) (for all k, given "thing when k is k", build thing when var is "k+1").

Hé, ça devient long et je ne suis qu'en troisième ligne de correctness...

Leaky Nun
la source
3

J , 19 octets

-/@(^~*]!0{])],i.@-

Essayez-le en ligne!

Explication

-/@(^~*]!0{])],i.@-  Input: n (LHS), k (RHS)
                  -  Negate k
               i.@   Range [k-1, k-2, ..., 0]
             ]       Get RHS
              ,      Join, forms [k, k-1, ..., 0]
   (        )        Dyad between n (LHS), [k, k-1, ..., 0] (RHS)
           ]           Get RHS
         0{            Select value at index 0
       ]               Get RHS
        !              Binomial coefficient
    ^~                 Raise each in RHS to power of n
      *                Multiply
-/@                  Reduce from right to left using subtraction (forms alternating sum)
miles
la source
-/@(^~*]!0{])]-i.
FrownyFrog
2

R , 49 octets

function(n,k,j=0:k)((-1)^(k-j)*j^n)%*%choose(k,j)

Essayez-le en ligne!

Implémente l'une des formules de Mario Catalani:

T(n, k) = Sum_{j=0..k} (-1)^(k-j)*j^n*binomial(k, j)

ou alternativement:

T(n, k) = Sum_{j=0..k} (-1)^j*binomial(k, j)*(k-j)^n

qui donne le même nombre d'octets dans R.

Giuseppe
la source
2

Python 2 , 56 53 50 octets

f=lambda n,k:n/k and(1/k or f(n-1,k-1)+f(n-1,k))*k

Essayez-le en ligne!

-3 octets grâce à H.PWiz.

-3 octets grâce à Dennis.

  • Si n<ktous ne kpeuvent pas être cartographiés, il n'y a donc pas de surjections. n/k ands'occupe de cela.
  • Prendre f(0,0)=1nous donne le seul cas de base non nul dont nous avons besoin. 1/k ory parvient.
dylnan
la source
2

Brain-Flak , 142 octets

({}<({}()){({}[(())]<<>{({}({})<>)<>}{}>)}{}>)<>{<>(({}<>)<{({}[()]<([])({([{}]()({}))([{}]({}))}{}[{}])>)}{}({}<>)>)<>}<>{}{}{({}<>[{}])<>}<>

Essayez-le en ligne!

Celui-ci utilise la formule standard d'inclusion-exclusion.

Je ne peux pas écrire une explication complète pour le moment, mais voici une explication de haut niveau:

# Compute k-th row of Pascal's triangle
({}<({}()){({}[(())]<<>{({}({})<>)<>}{}>)}{}>)<>

# Multiply each element by n^j (and reverse to other stack)
{<>(({}<>)<{({}[()]<([])({([{}]()({}))([{}]({}))}{}[{}])>)}{}({}<>)>)<>}

# Compute alternating sum
<>{}{}{({}<>[{}])<>}<>
Nitrodon
la source
2

Pari / GP , 38 octets

(n,k)->Pol(exp(x+O(x^n))-1)^k*n!\x^n%x

Essayez-le en ligne!

En utilisant la formule de Vladimir Kruchinin sur OEIS:

E.g.f.: (exp(x)-1)^k = sum T(n,k)x^n/n!
alephalpha
la source
2

Husk , 7 octets

#`¦ḣ¹π²

Essayez-le en ligne!

Explication

#`¦ḣ¹π²  Inputs: n (²), implicit k (¹)
     π²  Cartesian power of [1..k] to n
#        Count if:
   ḣ¹      Range [1..k]
 `¦        Is a subset
Fyr
la source
1

05AB1E , 10 octets

sLsãʒêgQ}g

Essayez-le en ligne!

Explication

sLsã       # Cartesian product of range(k) repeated n times
    ʒ   }  # Filter by ...
     êgQ   # Connected uniquified length == k  (every item in range(k) appears at least once)
         g # Count
Kaldo
la source