17
\$\begingroup\$

Hermite polynomials refer to two sequences of polynomials:

  • The "probabilist's Hermite polynomials", given by

    $${He}_n(x) = (-1)^n e ^ \frac {x^2} 2 \frac {d^n} {dx^n} e ^ {-\frac {x^2} 2}$$

    where \$\frac {d^n} {dx^n} f(x)\$ refers to the \$n\$th derivative of \$f(x)\$

  • The "physicist's Hermite polynomials", given by

    $$H_n(x) = (-1)^n e ^ {x^2} \frac {d^n} {dx^n} e ^ {-x^2}$$

The first few terms are

\$n\$ \$He_n(x)\$ \$H_n(x)\$
\$0\$ \$1\$ \$1\$
\$1\$ \$x\$ \$2x\$
\$2\$ \$x^2 - 1\$ \$4x^2 - 2\$
\$3\$ \$x^3 - 3x\$ \$8x^3 - 12x\$
\$4\$ \$x^4 - 6x^2 + 3\$ \$16x^4 - 48x^2 + 12\$
\$5\$ \$x^5 - 10x^3 + 15x\$ \$32x^5 - 160x^3 + 120x\$

Both sequences can be expressed via recurrence relations:

$$ He_{n+1}(x) = xHe_n(x) - nHe_{n-1}(x) \\ H_{n+1}(x) = 2xH_n(x) - 2nH_{n-1}(x) $$

with the base cases

$$ He_0(x) = 1, He_1(x) = x \\ H_0(x) = 1, H_1(x) = 2x $$


You should write a polyglot program that works in at least 2 languages. In one language, it should take a non-negative integer \$n\$ as input and output the polynomial \$H_n(x)\$, and in the second, it should take a non-negative integer \$n\$ and output the polynomial \$He_n(x)\$.

Your programs should be true polyglots, so are the same bytes, rather than the same characters. For example, if your program is g)ʠẹṁ in the Jelly code page, the bytes are 67 29 A5 D6 EF, and the same program in the 05AB1E code page would be g)¥Öï.

You may output the polynomial in any reasonable format, such as a list of coefficients (little- or big-endian) (e.g. \$x^4 - 6x^2 + 3\$ as [1,0,-6,0,3]), a list of pairs of coefficients and powers (e.g. [[1,4], [-6,2], [3,0]]), or a string such as x^4-6x^2+3.

Different versions of languages (e.g. Python 2 and 3) are considered the same language. As a general rule, if 2 languages are considered to be versions of each other (e.g. Seriously and Actually), they may not both be used. Additionally, using command line flags, in this case, does not count as different languages.

This is , so the shortest code in bytes wins.


Test cases

The polynomials here are represented in little-endian format

n -> He(x)                                 H(x)
0 -> [1]                                   [1]                                  
1 -> [0, 1]                                [0, 2]                               
2 -> [-1, 0, 1]                            [-2, 0, 4]                           
3 -> [0, -3, 0, 1]                         [0, -12, 0, 8]                       
4 -> [3, 0, -6, 0, 1]                      [12, 0, -48, 0, 16]                  
5 -> [0, 15, 0, -10, 0, 1]                 [0, 120, 0, -160, 0, 32]             
6 -> [-15, 0, 45, 0, -15, 0, 1]            [-120, 0, 720, 0, -480, 0, 64]       
7 -> [0, -105, 0, 105, 0, -21, 0, 1]       [0, -1680, 0, 3360, 0, -1344, 0, 128]
\$\endgroup\$
1

5 Answers 5

7
\$\begingroup\$

Wolfram Language (Mathematica) + Python 3, 63 bytes

#+HermiteH[#,x]-#&(*
import scipy.special as s;s.hermitenorm#*)

Try it online! (Mathematica)

Try it online! (Python)

Boring solution with built-ins... Gives physicists' version for Mathematica and probabilists' version for Python. There will be floating errors for Python though. The following eliminates that for 102 bytes

#+HermiteH[#,x]-#&(*
f=lambda n:n<2 and[0]*n+[1]or[a-~-n*b for a,b in zip([0]+f(n-1),f(n-2)+[0,0])]#*)

with the Python solution outputting a coefficient list in ascending power

\$\endgroup\$
1
  • 2
    \$\begingroup\$ #~HermiteH~x& for -5 \$\endgroup\$
    – att
    Jul 26, 2021 at 1:26
4
\$\begingroup\$

Ruby/Crystal, 84 bytes

def f(n)n<1?[1]:([0]+f(n-1)).zip(f(n-2)+[0,0]).map{|i,j|('a'=="a"?1:2)*(i+j-n*j)}end

Try it online in Ruby! (probabilist)

Try it online in Crystal! (physicist)

Outputs in little-endian format, as in provided test cases.

This may look similar to a loophole of using different versions of the same language, but Crystal is a different language that just shares most of its syntax with Ruby. The languages are distinguished by their approach to quotes:

  • In Ruby, both single and double quotes denote string literals
  • In Crystal, single quotes denote chars, which do not pass equality check with analogous strings
\$\endgroup\$
2
  • \$\begingroup\$ I'm not sure about how Ruby or Crystal do typing, but can you replace the ternary with something like ('a'!="a")+1 (assuming they're like Python and treat bools as ints) \$\endgroup\$ Jul 25, 2021 at 17:43
  • \$\begingroup\$ Nope, both don't coerce booleans, and Crystal also fails on using < or > condition as the args are differently typed. \$\endgroup\$
    – Kirill L.
    Jul 25, 2021 at 17:53
4
\$\begingroup\$

Gol><> and J (902), 86 bytes

60.]{{'01IF00}L:2+F:}*$:@-{@@}}|{$2+F$}}||LFN~|h'
{{2*-/(0,p=:y),:p*#p}}^:y,1[p=:0$0}}

Try it online in Gol><>!

Try the equivalent code in J 806!

A full program in Gol><> that outputs He(n) in big endian, and a function in J that outputs H(n) in little endian.

Gol><> path

Gol><> operates on a single stack of numbers, and the challenge requires zipping two lists and maintaining two previous states. So I decided to interleave the two coefficient lists on the stack.

60.    01IF00}L:2+F:}*$:@-{@@}}|{$2+F$}}||LFN~|h
60.    Jump into the main code
01     Push 0, 1  (-1th and 0th polynomial, respectively)
IF..|  Take n from input and repeat n times (L: 0..n-1)
       Example: 2nd iteration
       The stack content is 1 0 0 1, which represents two polynomials
       1   0     -> 1 (0th polynomial; P)
         0   1   -> x (1st polynomial; Q)
00}    Push a 0 at the top and another 0 at the bottom
         1   0   0   -> 1
       0   0   1     -> x^2
L:2+F..|    Push L, and then iterate L+2 times (L+2 is the number of pairs)
                   L
         1   0   0
       0   0   1
:}     Put a copy of L to the bottom of the stack
       L             L
           1   0   0
         0   0   1
*$:@-  Multiply L to the current coef of P, and subtract from that of Q
       L             
           1   0   1-0*L
         0   0   1
{@@}}  Pull the copy of L back to the top, and rotate the two coefs to the bottom
                       L
         1-0*L   1   0
       1       0   0
       At the end of this loop:
                               L
         0-1*L   0-0*L   1-0*L
       0       0       1
{$2+F$}}|    Rotate once, consume L, and swap the positions for P and Q
       0       1       0         -> new P
         0-1*L   0-0*L   1-0*L   -> new Q
LFN~|h    Print Q from top to bottom and halt

J path

A multi-line function evaluates each line sequentially, and returns the last line evaluated. So the relevant part is this (with y being the argument and p being a scratch global variable):

{{2*-/(0,p=:y),:p*#p}}^:y,1[p=:0$0

Within the inner function, p stores the previous polynomial, and the return value is the next polynomial. All polynomials are stored in little endian. As in the Gol><> part, P denotes the second-to-last polynomial and Q denotes the last polynomial.

{{2*-/(0,p=:y),:p*#p}}^:y,1[p=:0$0    y: value of n in H(n)
                            p=:0$0    Initialize P to zero polynomial
{{                  }}^:y,1[    Iterate inner func n times to [1]...
                p*#p    each item of P times length of P
      (0,p=:y),:    Zip two arrays Q*x and the above, and update p to Q
  2*-/    Subtract the 2nd row from 1st, and double

Just for fun and more golfiness, replacing J with the Mathematica built-in:

Gol><> and Wolfram Language (Mathematica), 57 bytes

(*1IF00}L:2+F:}*$:@-{@@}}|{$2+F$}}||LFN~|h*)#~HermiteH~x&

Try it online in Gol><>!

Try it online in Mathematica!

These combine smoothly because the comment starter in Mathematica (* pushes a single 0 in Gol><>.

\$\endgroup\$
4
\$\begingroup\$

Using calculus package (for R)

Jelly, probabilist, 51 bytes

\(n)calculus::hermite(n)[[n+1]]$t$c#¶1W¤Ż_בɼ_Ɗ}Ḥʋ¡

Try it online!

R >= 4.1, physicist, 51 bytes

\(n)calculus::hermite(n)[[n+1]]$t$c#1WÒ_ü¦_}¯©

Try it at RDRR

Try both online (sort of - no calculus package on tio so produces link to RDRR)


No external packages

Jelly, probabilist, 81 bytes

\(n){a=1[-1];for(i in seq_len(n))T=-c(a,0,0)*(i-1)+c(0,a<-T);T+0}#¶1W¤Ż_בɼ_Ɗ}Ḥʋ¡

Try it online!

R >= 4.1, physicist, 81 bytes

\(n){a=1[-1];for(i in seq_len(n))T=-c(a,0,0)*(i-1)+c(0,a<-T);T+0}#1WÒ_ü¦_}¯©

Try it online!

A full program in Jelly and a function in R both of which take an integer; the Jelly one takes it via STDIN. Note this is the same code for both, but in the Jelly codepage for Jelly and latin1 codepage for R. Both return the polynomial as the coefficients starting with the coefficient for \$x^0\$.

Python script to try both online

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

Mathics + Wolfram Language (Mathematica), 44 bytes

Expand[s=Sqrt@Depth@{};HermiteH[#,x/s]/s^#]&

Try it online (Mathics physicist)!

Try it online (Mathematica probabilist)!

Mathics and Mathematica are two different implementations of the Wolfram Language. According to this meta post, they are considered different languages.

Depth@{} returns 1 in Mathics, 2 in Mathematica.

I'm not sure if Expand is necessary. Without it the Mathematica probabilist answer would return unsimplified results like (-6*Sqrt[2]*x + 2*Sqrt[2]*x^3)/(2*Sqrt[2]).

\$\endgroup\$

Your Answer

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

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