เร็วเกินไปเกินไปฟูริเยร์: กอล์ฟรหัส FFT


48

ใช้การแปลงฟูริเยร์อย่างรวดเร็วในตัวละครที่มีความเป็นไปได้น้อยที่สุด

กฎ:

  • ทางออกที่สั้นที่สุดชนะ
  • สามารถสันนิษฐานได้ว่าอินพุตเป็นอาร์เรย์ 1D ที่ความยาวคือพลังของสอง
  • คุณอาจจะใช้ขั้นตอนวิธีการที่คุณเลือก แต่การแก้ปัญหาจริงจะต้องเป็นฟูริเยร์ได้อย่างรวดเร็วแปลงไม่เพียง แต่ไร้เดียงสาแบบไม่ต่อเนื่องแปลงฟูเรีย (นั่นคือจะต้องมีค่าใช้จ่ายในการคำนวณเชิงของO(NlogN) )

แก้ไข:

  • รหัสควรใช้มาตรฐานไปข้างหน้าอย่างรวดเร็วฟูริเยร์แปลงรูปแบบของการที่สามารถเห็นได้ในสมการ (3) ของบทความวุลแฟรมนี้ ,

    ป้อนคำอธิบายรูปภาพที่นี่

  • ไม่อนุญาตให้ใช้ฟังก์ชัน FFT จากไลบรารีมาตรฐานหรือแพ็คเกจสถิติที่มีอยู่ก่อน ความท้าทายที่นี่คือการใช้อัลกอริทึม FFT อย่างชัดเจน

3
สิ่งนี้ไม่ได้ระบุไว้ อย่างน้อยที่สุดคุณจำเป็นต้องกำหนดปัจจัยการทำให้เป็นมาตรฐานและคุณควรทราบด้วยว่าความคลุมเครือใด ๆ จะถูกตีความผิดอย่างจงใจ เช่น "ใช้งาน" พอใจกับคำตอบ " FFT(3 ตัวอักษร): อยู่ในไลบรารีมาตรฐาน" หรือไม่ บางกรณีทดสอบก็จะดีเช่นกัน
Peter Taylor

มันมีความสำคัญเกี่ยวกับลำดับขององค์ประกอบเอาท์พุทหรือไม่เช่นเราจำเป็นต้องใช้บิตย้อนกลับไม่เสียการพนันหรือเราสามารถปล่อยเอาท์พุทตามลำดับสัญญาณรบกวนหรือไม่?
พอล R

ดูการแก้ไขกฎ เอาต์พุตควรเป็นลิสต์ / อาร์เรย์ที่มีค่าซึ่งเรียงลำดับตามดัชนีในนิพจน์ DFT มาตรฐานที่อ้างถึงข้างต้น
jakevdp

2
คุณสามารถโพสต์ตัวอย่างอินพุตและเอาต์พุตเพื่อให้เราสามารถทดสอบการใช้งานของเราได้หรือไม่
FUZxxl

2
ชื่อควรมีชื่อว่า "Fast and Fourier-s" (เร็วและรุนแรง)
clismique

คำตอบ:


12

Mathematica, 95 ไบต์

การดำเนินงานอีกหนึ่งของคูลลีย์-Tukey FFT ด้วยความช่วยเหลือจาก @ chyaong

{n=Length@#}~With~If[n>1,Join[+##,#-#2]&[#0@#[[;;;;2]],#0@#[[2;;;;2]]I^Array[-4#/n&,n/2,0]],#]&

Ungolfed

FFT[x_] := With[{N = Length[x]},
  If[N > 1,
    With[{a = FFT[ x[[1 ;; N ;; 2]] ], 
          b = FFT[ x[[2 ;; N ;; 2]] ] * Table[E^(-2*I*Pi*k/N), {k, 0, N/2 - 1}]},
      Join[a + b, a - b]],
    x]]

1
ผมคิดและ#[[;;;;2]]==#[[1;;N;;2]] [[2;;;;2]]==[[2;;N;;2]]
chyanog

1
101 ตัวอักษร:With[{L=Length@#},If[L>1,Join[+##,#-#2]&[#0@#[[;;;;2]],#0@#[[2;;;;2]]E^(-2I*Pi(Range[L/2]-1)/L)],#]]&
chyanog

ดีมากคุณสามารถรวมฟังก์ชันนิรนามไว้ข้างในได้โดยไม่ขัดแย้งกับ recursive ยังได้เรียนรู้ว่าส่วนที่เติมด้วยดัชนีที่หายไป เราสามารถนำมันไปใช้เพิ่มเติมโดยใช้ Unicode
ไมล์

9

J, 37 ไบต์

_2&(0((+,-)]%_1^i.@#%#)&$:/@|:]\)~1<#

การปรับปรุงหลังจากไม่กี่ปี ยังคงใช้อัลกอริทึม Cooley-Tukey FFT

บันทึก 4 ไบต์โดยใช้e πi = -1 ขอบคุณ @รั่วนูน

ลองออนไลน์!

การใช้

   f =: _2&(0((+,-)]%_1^i.@#%#)&$:/@|:]\)~1<#
   f 1 1 1 1
4 0 0 0
   f 1 2 3 4
10 _2j2 _2 _2j_2
   f 5.24626 3.90746 3.72335 5.74429 4.7983 8.34171 4.46785 0.760139
36.9894 _6.21186j0.355661 1.85336j_5.74474 7.10778j_1.13334 _0.517839 7.10778j1.13334 1.85336j5.74474 _6.21186j_0.355661

คำอธิบาย

_2&(0((+,-)]%_1^i.@#%#)&$:/@|:]\)~1<#  Input: array A
                                    #  Length
                                  1<   Greater than one?
_2&(                            )~     Execute this if true, else return A
_2                            ]\         Get non-overlapping sublists of size 2
    0                       |:           Move axis 0 to the end, equivalent to transpose
                          /@             Reduce [even-indexed, odd-indexed]
                       &$:               Call recursively on each 
                   #                     Get the length of the odd list
                i.@                      Range from 0 to that length exclusive
                    %#                   Divide each by the odd length
             _1^                         Compute (-1)^x for each x
           ]                             Get the odd list
            %                            Divide each in that by the previous
       +                                 Add the even values and modified odd values
         -                               Subtract the even values and modified odd values
        ,                                Join the two lists and return

1
ดูเพิ่มเติมที่นี่: blog.ndpar.com/2014/10/11/dft-j
FUZxxl

9

Python, 166 151 150 ตัวอักษร

วิธีนี้ใช้อัลกอริทึม Radix-2 Cooley-Tukey FFT

from math import*
def F(x):N=len(x);t=N<2or(F(x[::2]),F(x[1::2]));return N<2and x or[
a+s*b/e**(2j*pi*n/N)for s in[1,-1]for(n,a,b)in zip(range(N),*t)]

ทดสอบผลลัพธ์

>>> import numpy as np
>>> x = np.random.random(512)
>>> np.allclose(F(x), np.fft.fft(x))
True

1
2 สิ่งที่มันมักจะเป็นที่ดีที่สุดที่จะใช้from x import*และมีความยาวมากกว่าsum(([x for x in y] for y in z),[]) [x for y in z for x in y]
บูธตาม

1
ขอบคุณ - ที่ช่วยประหยัด 15 ตัวละคร! อีก 11 คนและเป็นทวีต
jakevdp

โอ้นั่นเป็นไปได้อย่างแน่นอน บ่อยครั้งที่คุณพบว่ามีการปรับปรุงอย่างใดอย่างหนึ่งเก่าจะกลายเป็นบล็อกสะดุด
บูธตาม

5

Python 3: 140 134 113 อักขระ

เวอร์ชั่นย่อ - สั้นและหวานพอดีในทวีต (ขอบคุณไมล์ ):

from math import*
def f(v):
 n=len(v)
 if n<2:return v
 a,b=f(v[::2])*2,f(v[1::2])*2;return[a[i]+b[i]/1j**(i*4/n)for i in range(n)]

(ใน Python 2 /เป็นการตัดทอนการหารเมื่อทั้งสองด้านเป็นจำนวนเต็มดังนั้นเราจึงแทนที่(i*4/n)ด้วย(i*4.0/n)ซึ่งทำให้ความยาวเป็น 115 ตัวอักษร)

รุ่นยาว - ความชัดเจนมากขึ้นเกี่ยวกับการใช้งานภายในของคลาสสิก Cooley-Tukey FFT:

import cmath
def transform_radix2(vector):
    n = len(vector)
    if n <= 1:  # Base case
        return vector
    elif n % 2 != 0:
        raise ValueError("Length is not a power of 2")
    else:
        k = n // 2
        even = transform_radix2(vector[0 : : 2])
        odd  = transform_radix2(vector[1 : : 2])
        return [even[i % k] + odd[i % k] * cmath.exp(i * -2j * cmath.pi / n) for i in range(n)]

1
ลดขนาดเหลือ113 ไบต์โดยใช้e^(-2j * pi * i / n) = (-1)^(2 * i / n) = (1j)^(4 * i / n)
ไมล์

@miles การสังเกตที่น่าประทับใจมากขอบคุณ! หลังจากใช้ DFT มาหลายสิบปีฉันหมกมุ่นอยู่กับบาป / cos / exp และลืมว่าฉันสามารถใช้พลังที่เรียบง่ายได้ ฉันแก้ไขคำตอบของฉันเพื่อรวมข้อมูลเชิงลึกใหม่และให้เครดิตคุณ
Nayuki

5

R: 142 133 99 95 ไบต์

ขอบคุณ@Giuseppeช่วยฉันลดขนาดลง32 36 ไบต์!

f=function(x,n=sum(x|1),y=1:(n/2)*2)`if`(n>1,f(x[-y])+c(b<-f(x[y]),-b)*exp(-2i*(y/2-1)*pi/n),x)

เคล็ดลับเพิ่มเติมที่นี่คือการใช้อาร์กิวเมนต์หลักของฟังก์ชันเริ่มต้นเพื่อยกตัวอย่างตัวแปรบางตัว
การใช้งานยังคงเหมือนเดิม:

x = c(1,1,1,1)
f(x)
[1] 4+0i 0+0i 0+0i 0+0i

รุ่นเก่า 4 ปีที่ 133 ไบต์:

f=function(x){n=length(x);if(n>1){a=Recall(x[seq(1,n,2)]);b=Recall(x[seq(2,n,2)]);t=exp(-2i*(1:(n/2)-1)*pi/n);c(a+b*t,a-b*t)}else{x}}

ด้วยการเยื้อง:

f=function(x){
    n=length(x)
    if(n>1){
        a=Recall(x[seq(1,n,2)])
        b=Recall(x[seq(2,n,2)])
        t=exp(-2i*(1:(n/2)-1)*pi/n)
        c(a+b*t,a-b*t)
        }else{x}
    }

มันใช้อัลกอริทึม Cooley-Tukey เทคนิคเดียวที่นี่คือการใช้ฟังก์ชั่นRecallที่อนุญาตให้มีการเรียกซ้ำและการใช้ R vectorization ที่ทำให้การคำนวณจริงสั้นลงอย่างมาก

การใช้งาน:

x = c(1,1,1,1)
f(x)
[1] 4+0i 0+0i 0+0i 0+0i

1
สี่ปีต่อมาและเราได้รับมันลงไป101 ไบต์ ไม่แน่ใจ 100% ว่าทำไมคุณถึงใช้Recallชื่อฟังก์ชั่นที่มีอยู่แล้ว แต่เดี๋ยวก่อนมันง่ายที่จะเล่นกอล์ฟในการเข้าใจถึงปัญหาหลังเหตุการณ์! :) +1 ดีมาก
Giuseppe

ใช่Recallตอนนี้ไม่จำเป็นแน่นอน ฉันสังเกตเห็นว่าไม่กี่เดือนที่ผ่านมา แต่ขี้เกียจเกินไปที่จะเปลี่ยนมัน :) ฉันจะแก้ไขมัน
plannapus

ดีมาก! ฉันบีบออกอีก 4 ไบต์! วางสิ่งนี้ให้เท่าเทียมกับ Mathematica
Giuseppe

ขอบคุณ! ฉันคิดว่าจะyไปที่นั่น แต่ไม่ได้สังเกตว่ามันสามารถใช้กับexp(...)ส่วนนี้ได้เช่นกัน
plannapus

4

Python, 134

สิ่งนี้ยืมมาอย่างมากจากโซลูชันของ jakevdp ดังนั้นฉันจึงตั้งค่านี้เป็นวิกิชุมชน

from math import*
F=lambda x:x*(len(x)<2)or[a+s*b/e**(2j*pi*n/len(x))for s in(1,-1)for n,(a,b)in
enumerate(zip(F(x[::2]),F(x[1::2])))]

การเปลี่ยนแปลง:

-12 ตัวอักษร: tฆ่า

def F(x):N=len(x);t=N<2or(F(x[::2]),F(x[1::2]));return ... in zip(range(N),*t)]
def F(x):N=len(x);return ... in zip(range(N),F(x[::2]),F(x[1::2]))]

-1 อักขระ: เคล็ดลับการยกกำลังx*y**-z == x/y**z (นี่อาจช่วยคนอื่นได้)

...[a+s*b*e**(-2j*pi*n/N)...
...[a+s*b/e**(2j*pi*n/N)...

-2 อักขระ: แทนที่andด้วย*

...return N<2and x or[
...return x*(N<2)or[

+1 ถ่าน: lambdaize ฆ่าN

def F(x):N=len(x);return x*(N<2)or[a+s*b/e**(2j*pi*n/N) ... zip(range(N) ...
F=lambda x:x*(len(x)<2)or[a+s*b/e**(2j*pi*n/len(x)) ... zip(range(len(x)) ...

-2 อักขระ: ใช้enumerateแทนzip(range(len(

...for(n,a,b)in zip(range(len(x)),F(x[::2]),F(x[1::2]))]
...for n,(a,b)in enumerate(zip(F(x[::2]),F(x[1::2])))]

ฉันคิดว่านี่ไม่ใช่การแปลงฟูริเยร์ที่รวดเร็วอีกต่อไปแม้ว่า ... โดย "kill t" คุณได้เพิ่มการคำนวณที่ไม่จำเป็นซึ่งย้ายจาก O [N log (N)] ไปยัง O [N ^ 2]
jakevdp

ดูเหมือนว่าฉันไม่สามารถลงคะแนนโพสต์ของฉันเอง คุณถูกต้องฉันแลกเปลี่ยนลำดับวงและฆ่าประสิทธิภาพ ฉันจะปล่อยมันไว้ตอนนี้ในกรณีที่ฉันหาวิธีแก้ไข
บูธโดย

101 ไบต์ด้วยf=lambda x:x*(len(x)<2)or[u+v/1j**(4*i/len(x))for i,(u,v)in enumerate(zip(f(x[::2])*2,f(x[1::2])*2))]
ไมล์

คุณสามารถแทนที่for s in(1,-1)forด้วยหรือแม้กระทั่งถ้าสั่งไม่ได้เรื่องfor s in 1,-1for for s in-1,1for
Jonathan Frech

4

C, 259

typedef double complex cplx;
void fft(cplx buf[],cplx out[],int n,int step){
if(step < n){
fft(out, buf,n, step * 2);
fft(out+step,buf+step,n,step*2);
for(int i=0;i<n;i+=2*step){
cplx t=cexp(-I*M_PI*i/n)*out[i+step];
buf[i/2]=out[i]+t;
buf[(i+n)/2]=out[i]-t;
}}}

ปัญหาคือการใช้งานดังกล่าวไม่มีประโยชน์และอัลกอริทึมตรงไปตรงมาเร็วขึ้น


2
คุณสามารถลบบางช่องว่างมากขึ้นที่จะได้รับ amout ล่างของตัวอักษรเช่นstep < nสามารถเปลี่ยนเป็นstep<nและสามารถเปลี่ยนเป็นstep * 2 step*2
ProgramFOX

2
ตัวแปรและฟังก์ชั่นและ typedef ทั้งหมดควรมีชื่อตัวอักษรหนึ่งตัวเพื่อประหยัดตัวอักษรจำนวนมาก

2
คุณมีคนแนะนำการปรับปรุงมากมายสำหรับสิ่งนี้ ดูได้ที่นี่: codegolf.stackexchange.com/review/suggested-edits/17119
Justin

1
คุณสามารถลบบรรทัดใหม่ทั้งหมดบรรทัดใหม่ไม่มีประโยชน์ใน C
TuxCrafting

@ TùxCräftîñgบรรทัดใหม่ทั้งหมดไม่มีประโยชน์ พวกเขาจำเป็นสำหรับคำสั่งเช่น #include, #define, #if, ฯลฯ
Nayuki

3

Matlab, 128 118 107 102 101 94 93 ไบต์

แก้ไข 6: ขอบคุณ @algmyr สำหรับไบต์อื่น!

function Y=f(Y);
n=numel(Y);
k=2:2:n;
if k;
   c=f(Y(k-1));
   d=f(Y(k)).*i.^(2*(2-k)/n);
   Y=[c+d;c-d];
end

แก้ไข 5: ยังคงสั้นลง :) ขอบคุณ @sanchises

function Y=f(Y)
n=numel(Y);
k=2:2:n;
if k;
   c=f(Y(k-1));
   d=f(Y(k)).*(-1).^((2-k)/n);
   Y=[c+d;c-d];
end

EDIT4: ยิ่งไปกว่านั้น -1 ตัวอักษรมากขึ้น (อาจทำได้โดยไม่ต้องk):

function Y=f(Y)
n=numel(Y);
if n>1;
   k=2:2:n;
   c=f(Y(k-1));
   d=f(Y(k)).*(-1).^((k/2-1)*2/n)';
   Y=[c+d;c-d];
end

แก้ไข 2/3: ขอบคุณสำหรับ @sanchises สำหรับการปรับปรุงเพิ่มเติม!

function Y=f(Y)
n=numel(Y);  
if n>1;
   c=f(Y(1:2:n));
   d=f(Y(2:2:n)).*(-1).^(-(0:n/2-1)*2/n).';
   Y=[c+d;c-d]; 
end

แก้ไข: สามารถทำการปรับปรุงบางอย่างและสังเกตเห็นว่าไม่จำเป็นต้องมีการปรับสเกล

นี่เป็นรุ่นที่ขยายจำนวนตัวอักษรจะถูกต้องหากคุณลบบรรทัดใหม่ / ช่องว่าง (ใช้ได้กับเวกเตอร์คอลัมน์เท่านั้น)

function y=f(Y)
n=numel(Y);  
y=Y;
if n>1;
   c=f(Y(1:2:n));
   d=f(Y(2:2:n));
   n=n/2;
   d=d.*exp(-pi*i*(0:n-1)/n).';
   y=[c+d;c-d]; 
end

เคล็ดลับ: คุณสามารถรวมทั้งสองสายเป็นหนึ่ง:d= m=n/2;d=f(Y(2:2:n)).*exp(-pi*i*(0:m-1)/m).';นอกจากนี้ให้พิจารณาเปลี่ยนy=f(Y)เป็นY=f(Y)และลบบรรทัดที่ 3 (และสัญญาว่าคุณจะไม่ทำอย่างนั้นนอกรหัสกอล์ฟ)
Sanchises

โอ้ขอบคุณ! ไม่function Y = f(Y)ต้อง disadvanteages อื่น ๆ กว่า unreadability ใด ๆ
ข้อบกพร่อง

MATLAB จะไม่บ่นเกี่ยวกับมูลค่าส่งคืนแม้ว่า Y จะไม่เปลี่ยนแปลงก็ตาม มันเป็นเพียงเล็กน้อยได้เร็วขึ้นแม้ว่าดังนั้นผมคิดว่ามันจะไม่เลวร้ายหลังจากทั้งหมดเพื่อวัตถุประสงค์บางอย่าง (เช่นฟังก์ชั่นที่เกือบจะไม่เคยเปลี่ยนแปลงตัวแปรการป้อนข้อมูล)
Sanchises

ตอนนี้สำหรับการโกนที่มากขึ้น: m=n/2สามารถลบออกได้และmแทนที่ด้วยn/2และn*2ตามลำดับแทน จากนั้นฉันเชื่ออย่างยิ่งว่าโปรแกรมจะสั้นที่สุดเท่าที่จะทำได้ใน MATLAB
Sanchises

1
จากนั้นฉันเชื่ออย่างยิ่งว่าโปรแกรมจะสั้นที่สุดเท่าที่จะทำได้ใน MATLAB - Sanchises 8 มีนาคม '15 ที่ 21:05คำสุดท้ายที่มีชื่อเสียง ...
Sanchises

2

เยลลี่, 31 30 28 26 ไบต์ , ไม่ใช่การแข่งขัน

LḶ÷$N-*×,N$+ḷF
s2Z߀ç/µ¹Ṗ?

เจลลี่ถูกสร้างขึ้นหลังจากความท้าทายนี้ดังนั้นจึงไม่ใช่การแข่งขัน

วิธีนี้ใช้อัลกอริทึมแบบเรียกซ้ำ Cooley-Tukey radix-2 สำหรับรุ่นที่ไม่ตีกอล์ฟให้ดูคำตอบของฉันใน Mathematica

ลองมันออนไลน์หรือตรวจสอบกรณีทดสอบหลาย

คำอธิบาย

LḶ÷$N-*×,N$+ḷF  Helper link. Input: lists A and B
L               Get the length of A
   $            Operate on that length
 Ḷ                Make a range [0, 1, ..., length-1]
  ÷               Divide each by length
    N           Negate each
     -          The constant -1
      *         Compute -1^(x) for each x in that range
       ×        Multiply elementwise between that range and B, call it B'  
          $     Operate on that B'
         N        Negate each
        ,         Make a list [B', -B']
            ḷ   Get A
           +    Add vectorized, [B', -B'] + A = [A+B', A-B']
             F  Flatten that and return

s2Z߀ç/µ¹Ṗ?  Main link. Input: list X
         Ṗ   Curtail - Make a copy of X with the last value removed
          ?  If that list is truthy (empty lists are falsey)
       µ       Parse to the left as a monad
s2             Split X into sublists of length 2
  Z            Transpose them to get [even-index, odd-index]
   ߀          Call the main link recursively on each sublist
     ç/        Call the helper link as a dyad on the sublists and return
             Else
        ¹      Identity function on X and return

2

C (gcc) , 188 186 184 183 ไบต์

#define d(a,b,c)f(a,b,c,1,0)
f(a,b,c,n,k)_Complex*a,*b;{_Complex z[c];*b=*a;if(n<c)for(f(a,z,c,n*2),f(a+n,z+n,c,n*2);k<c;k+=n*2)b[k+c>>1]=z[k]*2-(b[k/2]=z[k]+z[k+n]/cpow(1i,2.*k/c));}

ลองออนไลน์!

golfed เล็กน้อยน้อย

#define d(a,b,c)f(a,b,c,1,0)
f(a,b,c,n,k)_Complex*a,*b;{
  _Complex z[c];
  *b=*a;
  if(n<c)
    for(f(a,z,c,n*2),f(a+n,z+n,c,n*2);k<c;k+=n*2)
      b[k+c>>1]=z[k]*2-(b[k/2]=z[k]+z[k+n]/cpow(1i,2.*k/c));
}

1

Pari / GP, 76 ตัวอักษร

X(v)=my(t=-2*Pi*I/#v,s);vector(#v,k,s=t*(k-1);sum(n=0,#v-1,v[n+1]*exp(s*n)))

การใช้

X([1,1,1,1])
%2 = [4.000000000000000000000000000, 0.E-27 + 0.E-28*I, 0.E-28 + 0.E-27*I, 0.E-27 + 0.E-28*I]

3
นี่ไม่ใช่ DFT ที่ไร้เดียงสาหรือ (เช่น theta (N ^ 2))
ไมล์

1

อ็อกเทฟ , 109 103 101 100 ไบต์

f(f=@(f)@(x,n=rows(x)){@(d=f(f)(x(k=2:2:n)).*i.^((k*2-4)/n)')[d+(c=f(f)(x(k-1)));c-d],x}{1+(n<2)}())

ลองออนไลน์!

ooooo ทำตาของฉันมีเลือดออกจากนี้recursiveแลมบ์ดาที่ถูกสาปแช่ง ส่วนใหญ่มาจากคำตอบของ @ flawr

f(                                          % lambda function
  f=@(f)                                    % defined in its own argument list, 
                                            % accepts itself as parameter (for recursion)
    @(x,n=rows(x)){                         % calls another lambda,
                                            % 2nd parameter is just to define a variable
      @(d=f(f)(x(k=2:2:n)).*i.^((k*2-4)/n)')% 1/4 of FFT (argument just defines a variable)
        [d+(c=f(f)(x(k-1)));                % 2/4 of FFT
         c-d                                % 4/4 of FFT
        ],                                  % This is in a @()[] to inhibit evaluation
                                            % unless actually called
      x                                     % FFT of length 1
    }{1+(n<2)}                              % if len(x)==1, return x
                                            % else return [d+c;c-d]
  ()                                        % this is probably important too
)

ฉันไม่เข้าใจสิ่งที่คุณทำ แต่ฉันชอบมันมาก
ข้อบกพร่อง

0

ความจริง259 , 193 , 181 , 179 ไบต์

L(g,n,f)==>[g for i in 1..n|f]
h(a)==(n:=#a;n=1=>a;c:=h(L(a.i,n,odd? i));d:=h(L(a.i,n,even? i));n:=n/2;t:=1>0;v:=L(d.i*%i^(-2*(i-1)/n),n,t);append(L(c.i+v.i,n,t),L(c.i-v.i,n,t)))

แม้ว่า h (ก) สามารถผ่านการทดสอบทั้งหมดและจะ ok เป็นรายการสำหรับการนี้การแข่งขัน 'หนึ่งที่มีการเรียก h () หรือ HLP () ผ่าน FFT () ด้านล่างเพื่อตรวจสอบข้อโต้แย้ง ฉันไม่รู้ว่าซอฟต์แวร์นี้สามารถใช้ได้หรือไม่เพราะฉันเพิ่งเห็นสิ่งที่คนอื่นเขียนและค้นหาวิธีที่มันสามารถทำงานใน Axiom เพื่อให้ได้ผลลัพธ์ที่ถูกต้อง ด้านล่างโค้ด ungolfed มีความคิดเห็นเล็กน้อย:

-- L(g,n,f)==>[g for i in 1..n|f]
-- this macro L, build one List from other list, where in g, there is the generic element of index i
-- (as a.i, or a.i*b.i or a.i*4), n build 1..n that is the range of i, f is the condition 
-- for insert the element in the list result.

hlp(a)==
    n:=#a;n=1=>a
    -- L(a.i,n,odd? i)  it means build a list getting "even indices i of a.i as starting from index 0" [so even is odd and odd is even]
    -- L(a.i,n,even? i) it means build a list getting "odd  indices i of a.i as starting from index 0"
    c:=hlp(L(a.i,n,odd? i));d:=hlp(L(a.i,n,even? i))
    n:=n/2;t:=1>0
    v:=L(d.i*%i^(-2*(i-1)/n),n,t)
    append(L(c.i+v.i,n,t),L(c.i-v.i,n,t))

-- Return Fast Fourier transform of list a, in the case #a=2^n
fft(a)==(n:=#a;n=0 or gcd(n,2^30)~=n=>[];hlp(a))

(5) -> h([1,1,1,1])
   (5)  [4,0,0,0]
                                    Type: List Expression Complex Integer
(6) -> h([1,2,3,4])
   (6)  [10,- 2 + 2%i,- 2,- 2 - 2%i]
                                    Type: List Expression Complex Integer
(7) -> h([5.24626,3.90746,3.72335,5.74429,4.7983,8.34171,4.46785,0.760139])
   (7)
   [36.989359, - 6.2118552150 341603904 + 0.3556612739 187363298 %i,
    1.85336 - 5.744741 %i, 7.1077752150 341603904 - 1.1333387260 812636702 %i,
    - 0.517839, 7.1077752150 341603904 + 1.1333387260 812636702 %i,
    1.85336 + 5.744741 %i,
    - 6.2118552150 341603904 - 0.3556612739 187363298 %i]
                                      Type: List Expression Complex Float
(8) -> h([%i+1,2,%i-2,9])
   (8)  [10 + 2%i,3 + 7%i,- 12 + 2%i,3 - 7%i]
                                    Type: List Expression Complex Integer

ในไม่กี่ที่ฉันเคยเห็น h () หรือ fft () จะกลับมาแก้ปัญหาที่แน่นอน แต่ถ้าการทำให้เข้าใจง่ายไม่ดีเหมือนใน:

(13) -> h([1,2,3,4,5,6,7,8])
   (13)
                    +--+                                   +--+
        (- 4 + 4%i)\|%i  - 4 + 4%i             (- 4 - 4%i)\|%i  - 4 + 4%i
   [36, --------------------------, - 4 + 4%i, --------------------------, - 4,
                    +--+                                   +--+
                   \|%i                                   \|%i
            +--+                                   +--+
    (- 4 + 4%i)\|%i  + 4 - 4%i             (- 4 - 4%i)\|%i  + 4 - 4%i
    --------------------------, - 4 - 4%i, --------------------------]
                +--+                                   +--+
               \|%i                                   \|%i
                                    Type: List Expression Complex Integer

มากกว่าที่จะพอเปลี่ยนประเภทขององค์ประกอบเพียงหนึ่งรายการตามที่เขียนด้านล่าง 8 (ลอย) เพื่อค้นหาวิธีแก้ปัญหาโดยประมาณ:

(14) -> h([1,2,3,4,5,6,7,8.])
   (14)
   [36.0, - 4.0000000000 000000001 + 9.6568542494 923801953 %i, - 4.0 + 4.0 %i,
    - 4.0 + 1.6568542494 92380195 %i, - 4.0, - 4.0 - 1.6568542494 92380195 %i,
    - 4.0 - 4.0 %i, - 4.0 - 9.6568542494 923801953 %i]
                                      Type: List Expression Complex Float

ฉันเขียนไปแล้วเห็นคำตอบอื่น ๆ ทั้งหมดเพราะในลิงค์หน้ามันยากเกินไปดังนั้นฉันไม่รู้ว่ารหัสนี้ถูกต้องหรือไม่ ฉันไม่ใช่ผู้เชี่ยวชาญ fft หนึ่งคนดังนั้นทั้งหมดนี้สามารถ (เป็นไปได้) ผิด


0

APL (NARS), 58 ตัวอักษร, 116 ไบต์

{1≥k←≢⍵:⍵⋄(∇⍵[y∼⍨⍳k])(+,-)(∇⍵[y←2×⍳t])×0J1*t÷⍨2-2×⍳t←⌊k÷2}

ทดสอบ

  f←{1≥k←≢⍵:⍵⋄(∇⍵[y∼⍨⍳k])(+,-)(∇⍵[y←2×⍳t])×0J1*t÷⍨2-2×⍳t←⌊k÷2}
  f 1 1 1 1
4J0 0J0 0J0 0J0 
  f 1 2 3 4
10J0 ¯2J2 ¯2J0 ¯2J¯2 
  f 1J1 2 ¯2J1  9
10J2 3J7 ¯12J2 3J¯7 
  f 5.24626,3.90746,3.72335,5.74429,4.7983,8.34171,4.46785,0.760139
36.989359J0 ¯6.211855215J0.3556612739 1.85336J¯5.744741 7.107775215J¯1.133338726 ¯0.517839J0 
  7.107775215J1.133338726 1.85336J5.744741 ¯6.211855215J¯0.3556612739 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.