Реализуйте быстрое преобразование Фурье, используя как можно меньше символов.
Правила:
- Самое короткое решение побеждает
- Можно предположить, что вход представляет собой одномерный массив, длина которого равна степени двойки.
- Вы можете использовать алгоритм по вашему выбору, но на самом деле решение должно быть быстрым преобразованием Фурье, а не просто наивным дискретным преобразованием Фурье (т. Е. Оно должно иметь асимптотическую стоимость вычисления )
Редактировать:
код должен реализовывать стандартное быстрое быстрое преобразование Фурье, форму которого можно увидеть в уравнении (3) этой статьи Вольфрама ,
- Использование функции FFT из ранее существующей стандартной библиотеки или пакета статистики не допускается. Задача здесь состоит в том, чтобы кратко реализовать сам алгоритм FFT.
code-golf
math
complex-numbers
jakevdp
источник
источник
FFT
(3 символа): это в стандартной библиотеке"? Некоторые тестовые случаи тоже подойдут.Ответы:
Mathematica, 95 байт
Еще одна реализация БПФ Кули – Тьюки с помощью @ chyaong .
Ungolfed
источник
#[[;;;;2]]==#[[1;;N;;2]]
и[[2;;;;2]]==[[2;;N;;2]]
.With[{L=Length@#},If[L>1,Join[+##,#-#2]&[#0@#[[;;;;2]],#0@#[[2;;;;2]]E^(-2I*Pi(Range[L/2]-1)/L)],#]]&
J 37 байт
Улучшение через несколько лет. До сих пор использует алгоритм БПФ Кули-Тьюки.
Благодаря @ Leaky Nun сохранено 4 байта с использованием e πi = -1 .
Попробуйте онлайн!
использование
объяснение
источник
Python,
166151150 символовПри этом используется алгоритм БПФ Кули-Тьюки, основанный на radix-2
Тестирование результата
источник
from x import*
иsum(([x for x in y] for y in z),[])
дольше, чем[x for y in z for x in y]
.Python 3:
140134113 символовКороткая версия - короткая и сладкая, вписывается в твит (благодаря миль ):
(В Python 2
/
происходит усечение деления, когда обе стороны являются целыми числами. Поэтому мы заменим(i*4/n)
на(i*4.0/n)
, что увеличивает длину до 115 символов.)Длинная версия - больше ясности во внутренностях классического Cooley-Tukey FFT:
источник
e^(-2j * pi * i / n) = (-1)^(2 * i / n) = (1j)^(4 * i / n)
R:
1421339995 байтСпасибо @Giuseppe за помощь в сокращении
3236 байт!Дополнительным трюком здесь является использование аргументов основной функции по умолчанию для создания экземпляров некоторых переменных.
Использование остается прежним:
4-летняя версия на 133 байта:
С отступами:
Используется также алгоритм Кули-Тьюки. Единственными хитростями здесь являются использование функции,
Recall
которая допускает рекурсивность, и использование векторизации R, которая значительно сокращает фактические вычисления.Использование:
источник
Recall
уже назвали эту функцию, но эй, в гольф легко заглянуть в прошлое! :) +1, очень приятно.Recall
, сейчас ненужно. Я заметил это несколько месяцев назад, но мне было лень это менять :) Я изменю это.y
там, но не заметил, что это может быть использовано и для этойexp(...)
части.Питон, 134
Это в значительной степени заимствовано из решения jakevdp, поэтому я настроил его на вики сообщества.
Изменения:
-12 символов: убить
t
.-1 символ: трюк экспоненты
x*y**-z == x/y**z
(это может помочь некоторым другим)-2 символа: заменить
and
на*
+1 символ:
lambda
изе, убийствоN
-2 символа: использовать
enumerate
вместоzip(range(len(
источник
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
.С 259
Проблема в том, что такие реализации бесполезны, а простой алгоритм НАМНОГО быстрее.
источник
step < n
можно изменить наstep<n
иstep * 2
изменить наstep*2
.Matlab,
1281181071021019493 байтаEDIT6: спасибо @algmyr за еще один байт!
EDIT5: все еще становится короче :) благодаря @sanchises
EDIT4: Yay, -1 символ больше (мог бы также обойтись без
k
):EDIT2 / 3: Спасибо за @sanchises для дальнейших улучшений!
РЕДАКТИРОВАТЬ: Может внести некоторые улучшения, и заметил, что постоянная масштабирования не требуется.
Это расширенная версия, счетчик символов действителен, если вы удалите символы новой строки / пробелы. (Работает только для векторов столбцов.)
источник
d=
строки в одну:m=n/2;d=f(Y(2:2:n)).*exp(-pi*i*(0:m-1)/m).';
. Кроме того, рассмотреть вопрос об измененииy=f(Y)
кY=f(Y)
и удалить строки 3 (и обещаю вам никогда не будет делать , что за пределами кода-гольф)function Y = f(Y)
какие-либо недостатки, кроме нечитаемости?m=n/2
можно было бы удалить, а вместо этогоm
заменитьn/2
иn*2
соответственно. И потом, я твердо верю, программа настолько коротка, насколько это возможно в MATLAB.Желе,
31302826 байт , неконкурентныйЖеле было создано после этого испытания, поэтому оно не конкурирует.
При этом используется рекурсивный алгоритм Cooley-Tukey radix-2. Для версии без игры в гольф, смотрите мой ответ в Mathematica.
Попробуйте онлайн или проверьте несколько тестовых случаев .
объяснение
источник
C (gcc) ,
188 186 184183 байтаПопробуйте онлайн!
Слегка поиграл меньше
источник
Пари / ГП, 76 знаков
использование
источник
Октава ,
109 103 101100 байтПопробуйте онлайн!
Оооо, мои глаза кровоточат от этой
рекурсивнойпроклятой лямбды. Большая часть этого была снята с ответа @ flawr.источник
APL (NARS), 58 символов, 116 байтов
контрольная работа
источник
Аксиома,
259,193,181, 179 байтДаже если h (a) может пройти весь тест и будет приемлемо в качестве входа для этого «соревнования», для проверки аргументов необходимо вызвать h () или hlp () через fft () ниже . Я не знаю, может ли это программное обеспечение быть в порядке, потому что я видел только то, что написали другие, и искал способ, которым оно могло работать в Аксиоме, чтобы получить какой-то возможный правильный результат. Ниже приведен код без комментариев:
в немногих, которые я видел, h () или fft () вернули бы точное решение, но если упрощение не так хорошо, как в:
Затем достаточно изменить тип только одного элемента списка, как показано ниже в разделе 8. (Float), чтобы найти примерное решение:
Я написал это, видел все другие ответы, потому что в ссылке на странице это было слишком сложно, поэтому я не знаю, может ли этот код быть правильным. Я не один эксперт, так что все это (вероятно) может быть ошибочным.
источник