Sandboxed and made less complicated and hopefully more fun.

Summary of the challenge

Given a number of particles, either identical bosons or identical fermions, output the total wave function of the state assuming they are all independent.

Physics background

Don't worry, you don't need to know quantum mechanics to solve this challenge. I will explain what you need now.

What is a wave function?

In (non-relativistic) quantum mechanics every particle can be described with a function of the position called the wave function. If you have a system with more than one particle you can describe it using a wave function that will depend on the position of all the particles of the system. In this challenge we will only consider independent (i.e. non-interacting) particles. In this case the total wave function can be written as a combination of the wave function of the single particles. The way you can do this depends of the type of particles you have and the statistics they obey.

Distinguishable particles

Let's start from the case of distinguishable particles even if you will not need them for the challenge. Distinguishable particles are what you have in classical physics. Every object has is own identity. If I throw two coins I have a 25% chance of getting TT, 25% for HH and a 50% for TH because TH and HT are two different events.

For a system of distinguishable particles the total wave function is written as the product of the single wave functions. For a system of n particles, if we call di the i-th particle wave function and xi the i-th particle position we have a total wave function:

1 particle:    d1(x1)
2 particles:   d1(x1)d2(x2)
3 particles:   d1(x1)d2(x2)d3(x3)

Indistinguishable Bosons

Now onto the weird stuff. When you get to the quantum level you will discover that particles with same properties are actually identical and thus obey a different statistics than classical particles. Back to the coin toss example we find that if we assume the coins to be indistinguishable, all the three events are equally likely, that is we have a 33% for TT, 33% for HH and 33% for HT because now TH and HT are the same event.

The total wave function for several bosons is not given by simply the product of the single particle wave functions, but as a sum of all the possible combinations of wave function and positions. You will understand better with some examples, using a similar notation than before:

1 boson:    b1(x1)
2 bosons:   b1(x1)b2(x2) + b2(x1)b1(x2)
3 bosons:   b1(x1)b2(x2)b3(x3) + b2(x1)b1(x2)b3(x3) + b3(x1)b2(x2)b1(x3) + b1(x1)b3(x2)b2(x3) + b2(x1)b3(x2)b1(x3) + b3(x1)b1(x2)b2(x3)

What you have at the end is a total wave function that is symmetric (i.e. stays the same) for any exchange like xi <-> xj or bi <-> bj.

Indistinguishable Fermions

It gets even weirder! Fermions are not only indistinguishable but they also don't like being in the same state. This means that if you toss two fermion coins you are 100% guaranteed of getting TH since TT and HH are now prohibited.

The total fermion wave function is constructed the same way of the boson one, but instead of having all + signs, you have a + or a - depending on the sign of the permutation. For an odd number of swaps to get from the starting order to that permutation you have a - sign, for an even number you have a + sign.

1 fermion:    f1(x1)
2 fermions:   f1(x1)f2(x2) - f2(x1)f1(x2)
3 fermions:   f1(x1)f2(x2)f3(x3) - f2(x1)f1(x2)f3(x3) - f3(x1)f2(x2)f1(x3) - f1(x1)f3(x2)f2(x3) + f2(x1)f3(x2)f1(x3) + f3(x1)f1(x2)f2(x3)

The total wave function is now antisymmetric (i.e. changes sign) for any exchange like xi <-> xj or fi <-> fj. If you have two equal wave functions the total wave function is zero.

Algorithmic way of building the wave function

Suppose you have 3 particles of type p (p=bfor bosons and p=f for fermions).

  • Start from p1(x1)p2(x2)p3(x3)
  • Build each possible swap of two wave functions (or equivalently coordinates)
    • p1(x1)p2(x2)p3(x3)
    • p1(x1)p3(x2)p2(x3)
    • p2(x1)p1(x2)p3(x3)
    • p2(x1)p3(x2)p1(x3)
    • p3(x1)p1(x2)p2(x3)
    • p3(x1)p2(x2)p1(x3)
  • Determine the sign of the permutation (only for fermions)
  • Join everything with the correct sign: + for bosons or the sign of the permutation for fermions


You will get two inputs (or a list of two items). One of them is a number from 0 to 9 inclusive (that will represent the number of particles, the other defines the type of particles in the system. You can choose the order of the input and the format of the two inputs. Some examples of inputs might be:

[n, type]    |    Meaning
[3, "boson"] |    3 bosons
[6, 'f']     |    6 fermions
[4, True]    |    4 fermions (True = fermion, False = boson)

Remember to write in the answer how you are formatting your input.


You have to output the total wave function of the system that obeys the rules explained before. See the examples for an example of formatting. Bosons are represented as bi, fermions as fi and positions as xi where the index i goes from 1 to n (the number of particles).

Each output will have n! terms that contains the product of n terms summed together. The order inside each product or in the total sum does not matter, the important thing is the dependence of each wave function on the positions and the sign of each term.

The output must be a mathematically valid expression, so if you want to add explicit multiplication signs it is fine. You have the freedom of writing the variables and the function as you want, but there needs to be a clear distinction between fermions and bosons.

The output must be written as an explicit sum of explicit products, so no implicit summations or products, no summation signs, no product signs and no determinants of matrices.

The spaces in the example are just for clarity and you can decide not to output them.


This is . Shortest answer in bytes wins. Standard loopholes apply.


Input  ->   Output
[0, b] ->   0 (or empty string)
[1, b] ->   b1(x1)
[2, b] ->   b1(x1)b2(x2) + b2(x1)b1(x2)
[3, b] ->   b1(x1)b2(x2)b3(x3) + b2(x1)b1(x2)b3(x3) + b3(x1)b2(x2)b1(x3) + b1(x1)b3(x2)b2(x3) + b2(x1)b3(x2)b1(x3) + b3(x1)b1(x2)b2(x3)
[1, f] ->   f1(x1)
[2, f] ->   f1(x1)f2(x2) - f2(x1)f1(x2)
[3, f] ->   f1(x1)f2(x2)f3(x3) - f2(x1)f1(x2)f3(x3) - f3(x1)f2(x2)f1(x3) - f1(x1)f3(x2)f2(x3) + f2(x1)f3(x2)f1(x3) + f3(x1)f1(x2)f2(x3)
  • \$\begingroup\$ Might there be 10 or more particles? This could affect string-based approaches that assume digits are a single character. \$\endgroup\$
    – xnor
    Commented Jun 21, 2017 at 17:51
  • \$\begingroup\$ It's not clear to me exactly what liberties one can take with the string representation of the algebraic expression. Peter Taylor mentioned some specifics in the sandbox. I think this would have benefited from more sandbox time -- I would have looked more closely after the simplification revision, and Peter Taylor may have followed up on his comment. \$\endgroup\$
    – xnor
    Commented Jun 21, 2017 at 17:56
  • \$\begingroup\$ @xnor I'll add a rule for the number of particles. For 10 particles the output also gets really long so it makes sense. For your second comment I'm not really sure what to tell you... for sums a+b or b+a are identical outputs and for products b1(x1)b2(x2) or b2(x2)b1(x1) are the same. \$\endgroup\$
    – FrodCube
    Commented Jun 21, 2017 at 18:05
  • \$\begingroup\$ Is handling the 0 particle case required? \$\endgroup\$ Commented Jun 21, 2017 at 18:06
  • \$\begingroup\$ @CalculatorFeline Yes. You can either output a 0 or have an empty output \$\endgroup\$
    – FrodCube
    Commented Jun 21, 2017 at 18:08

2 Answers 2


Jelly,  47  46 bytes

He he, what a ṭ€€ż€...


A full program which prints such that the summands are in lexicographical order once the multiplications of particle functions are all ordered by the position arguments.
f1(x1)f2(x2)...fn-1(xn-1)fn(xn) (or b...) will always be first, followed by
f1(x1)f2(x2)...fn(xn-1)fn-1(xn), and so on up to

Try it online!


Ṭ€z0ÆḊ×”fe⁴¤«0ị⁾-+ - Link 1: get the sign character: list, permutation of [1,N], P
Ṭ€                 - untruth €ach - that is [0,0,...,0,1] of length v for each v in P
  z0               - transpose with filler 0 (yields transpose of the permutation matrix)
    ÆḊ             - determinant (yields the parity of the permutation)
           ¤       - nilad followed by link(s) as a nilad:
       ”f          -   literal character 'f'
          ⁴        -   4th command line argument = 2nd program input = particle type, T
         e         -   exists in? (1 for "f", 0 for "b")
      ×            - multiply (force all results from +1 or -1 to 0 for T="b")
            «0     - minimum of that and 0 (force the +1s to 0s)
               ⁾-+ - literal list of characters = ['-', '+']
              ị    - index into (the -1s yield '-'  while the 0s yield '+')

ṭ€”xj@€⁾() - Link 2: construct parenthesised positions: number of particles, N
  ”x       - literal character = 'x'
ṭ€         - tack for €ach -> [['x', 1], ['x', 2], ..., ['x', N]]
       ⁾() - literal list of characters = ['(', ')']
    j@€    - join with swapped @rguments for €ach -> [['(', 'x', 1, ')'],...]

Œ!©ṭ€€ż€⁸Ǥ®Ñ€¤ż - Main link: number of particles, N; type of particle P
Œ!               - all permutations of N -> [[1,2,...,N-1,N],[1,2,...,N,N-1],...]
  ©              - copy to the register and yield
   ṭ€€           - tack T for €ach for €ach (place the type in front of every number)
          ¤      - nilad followed by link(s) as a nilad:
        ⁸        -   chain's left argument, N
         Ç       -   call last link (2) as a monad (get the "(xn)"s)
      ż€         - zip with for €ach (make all the summands)
              ¤  - nilad followed by link(s) as a nilad:
           ®     -   recall value from register (the permutations of N)
            Ñ€   -   call the next link (1) as a monad for €ach (get the signs)
               ż - zip the signs and the summands.
                 - implicit print
  • \$\begingroup\$ Please explain. \$\endgroup\$ Commented Jun 21, 2017 at 19:10
  • \$\begingroup\$ @CalculatorFeline I always do... it may take a while to write this up though. \$\endgroup\$ Commented Jun 21, 2017 at 19:10
  • 2
    \$\begingroup\$ @CalculatorFeline done. \$\endgroup\$ Commented Jun 21, 2017 at 19:42

Python3, 320 bytes:

def f(a,b):
 while q:
  for x in R(a):
   for y in R(x,a):
    if str(C)not in s:s[str(C)]=k+1;q+=[(C,k+1)]
 return''.join(['-','+'][b=='b'or s[j]%2==0]+''.join(f'{b}{eval(j)[k]+1}(x{k+1})'for k in R(a))for j in s)[1:]

Try it online!


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.