An obvious upper bound for the number of programs to sort $n$ numbers is $\left(\dfrac{n(n-1)}2\right)!\,2^{(n(n-1)/2)}$, an astronomical number. This is simply established by considering that you can perform at most $\dfrac{n(n-1)}2$ distinct pairwise comparisons, in any order, and every comparison can have two outcomes. That makes a decision tree of depth $\dfrac{n(n-1)}2$.
Among these, many include useless steps resulting from the transitivity law (if $a<b$ and $b<c$ are known, it is useless to compare $a$ to $c$). In addition, many of these are structurally equivalent, i.e. they are identical to a renaming of the compared elements. The census of these algorithms is a terrible endeavor.
Also quite interesting are the efficient programs, i.e. requiring no more than $O(n\log n)$ comparisons, and even better, the minimum-comparisons algorithms (https://en.wikipedia.org/wiki/Comparison_sort#Number_of_comparisons_required_to_sort_a_list). This is still an open problem.
But for most of these sequences of comparisons, the corresponding program does not "compress" and is virtually as large as the decision tree. That makes them completely impractical.
So a more interesting question is about the number of programs of bounded length, independently of $n$, which deserve the name of algorithms. There is perforce a finite number of such algorithms, though for large lengths it can be huge. This is because there is a finite number of text strings of bounded length (and most of them are no sorting at all, not even valid programs).
Can you beat the length of this code ?
def sort(a, n):
for i in range(n):
for j in range(0, n - i - 1):
if a[j] > a[j + 1]:
a[j], a[j + 1] = a[j + 1], a[j]
return a