Учитывая список 1
s и -1
s, определите, является ли это действительным кодом OVSF (выводя значение true или false).
Коды OVSF определяются следующим образом:
[1]
это код OVSFЕсли
X
это код OVSF, тоX ++ X
иX ++ -X
оба являются кодами OVSF.Вот
++
конкатенация списка, и-
отрицает каждый элемент в списке.Никакие другие списки не являются действительными кодами OVSF.
Вы можете предположить, что входной список содержит только -1
и 1
, но вы должны правильно обрабатывать пустой список, а также списки, длина которых не равна степени 2.
Самый короткий код (в байтах) выигрывает.
Контрольные примеры
[] -> False
[1] -> True
[-1] -> False
[1, 1] -> True
[1, -1] -> True
[1, 1, 1, 1] -> True
[1, 1, 1, 1, 1] -> False
[1, -1, -1, 1, -1, 1, 1, -1] -> True
[1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1] -> False
[1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1] -> False
[1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1] -> True
Ответы:
Желе ,
18161411 байтВыводы
[1]
(правда) для кодов OVSF,[]
(ложно) в противном случае.Попробуйте онлайн!
Задний план
Как @ MATL ответ LuisMendo в и @ XNOR Ответим Python , это представление проверяет входной массив «от наизнанку».
Каждая (не перекрывающаяся) пара элементов кода OVSF длиной два или выше по сути является копией первой пары, либо с одинаковыми знаками, либо с заменой обоих знаков. Аналогично, каждый (не перекрывающийся) 4-й кортеж элементов кода OVSF длиной четыре или выше по сути является копией первого 4-кортежа, либо с одинаковыми знаками, либо с заменой обоих знаков. То же самое относится к 8-кортежам, 16-кортежам и т. Д., Вплоть до длины кода OVFS.
Один из способов проверить это - сначала проверить все пары на равенство по знаку, а затем удалить второй элемент каждой пары (который теперь является избыточной информацией). Если мы повторим этот процесс еще раз, мы по существу проверяем все 4 кортежа. В следующей итерации мы сравниваем 8 кортежей и т. Д.
Наконец, если все необходимые 2 k- кортежи были равны по модулю знака и массив был уменьшен до одиночного, достаточно проверить, равен ли оставшийся элемент 1 .
Как это работает
источник
Mathematica,
524745 байтЧисло байтов предполагает кодировку CP-1252 и
$CharacterEncoding
установлено в значениеWindowsANSI
(по умолчанию в установках Windows).Это определяет переменную функцию
PlusMinus
, которая принимает входной список как плоский список аргументов и возвращает логическое значение, например,PlusMinus[1, -1, -1, 1]
даетTrue
. Это теоретически также можно использовать в качестве оператора±
, но оператор только синтаксически действует в одинарных и двойных контекстах, поэтому соглашение о вызовах бы получить странно:±##&[1,-1,-1,1]
. Он выдаст кучу предупреждений, которые можно игнорировать.Это также выдаст несколько предупреждений, которые можно игнорировать.
Там может быть что-то, чтобы сократить несколько раздражающую
a!==b!||{a}==-{b}
часть, но я сейчас ничего не нахожу. Ключевые слова, какSubsetQ
иMatrixRank
просто слишком долго. : /объяснение
Решение в основном переносит все хитрости на Mathematica, и поэтому оно очень декларативно по стилю. Помимо некоторого гольф-поля на первой линии, это действительно просто добавляет три разных определения для оператора
±
:Первые две строки были сокращены путем вложения определений и выражения
True
как1>0
.Мы должны деконструировать это далее, чтобы показать, как это на самом деле определяет функцию variadci
PlusMinus
, используя только унарные и двоичные операторные обозначения. Загвоздка в том, что все операторы являются просто синтаксическим сахаром для полных выражений. В нашем случае±
соответствуетPlusMinus
. Следующий код на 100% эквивалентен:Используя в качестве операндов последовательности (вроде сплатов в других языках),
±
мы можем охватить произвольное количество аргументовPlusMinus
, даже если их±
нельзя использовать более чем с двумя аргументами. Основная причина заключается в том, что синтаксический сахар разрешается в первую очередь, прежде чем любая из этих последовательностей будет расширена.По определениям:
Первое определение - просто запасной вариант (
___
соответствует произвольному списку аргументов). Все, что не соответствует более конкретным определениям ниже, дастFalse
.Второе определение - базовый вариант для OVSF, список содержит только
1
. Мы определяем это какTrue
.Наконец, третье определение применяется только к спискам, которые можно разложить на
X ++ X
илиX ++ -X
, и рекурсивно использует результат дляX
. Определение ограничивается этими списками, обеспечивая их можно разделить на подпоследовательностиa
иb
сa__±b__
и затем присоединив условие (/;
) , что либо{a}=={b}
или{a}==-{b}
. ОпределяяPlusMinus
эту функцию как переменную таким странным способом с помощью оператора, вы сэкономите 5 байтов за определение унарного оператора±
в списках.Но подождите, это еще не все. Мы используем
a!==b!
вместо{a}=={b}
. Ясно, что мы делаем это, потому что это на два байта короче, но интересный вопрос, почему это работает. Как я объяснил выше, все операторы являются просто синтаксическим сахаром для некоторого выражения с головой.{a}
естьList[a]
. Ноa
это последовательность (как я уже сказал, что-то вроде восклицательного знака в других языках), так что еслиa
это так,1,-1,1
мы получаемList[1,-1,1]
. Теперь постфикс!
естьFactorial
. Итак, мы получилиFactorial[1,-1,1]
. НоFactorial
он не знает, что делать, когда у него количество аргументов, отличное от одного, поэтому это просто остается недооцененным.==
на самом деле не волнует, являются ли вещи с обеих сторон списками, просто сравниваются выражения, и если они равны, это даетTrue
(в этом случае, на самом деле это не даст,False
если это не так, но шаблоны не совпадают, если условие возвращает что-либо кромеTrue
). Таким образом, проверка на равенство по-прежнему работает, если в списках есть хотя бы два элемента. Что если есть только один? Еслиa
есть,1
тоa!
еще1
. Еслиa
есть,-1
тоa!
даетComplexInfinity
. Теперь, по сравнению1
с самим собой, все еще работает нормально, конечно. НоComplexInfinity == ComplexInfinity
остается неоцененным и не дает правды, хотяa == -1 == b
. К счастью, это не имеет значения, потому что единственная ситуация, в которой это проявляется, это то,PlusMinus[-1, -1]
что в любом случае не является действительным OVSF! (Если условие вернулосьTrue
, рекурсивный вызов сообщитFalse
в конце концов, так что это не имеет значения , что проверка не работает.) Мы не можем использовать тот же трюк для ,{a}==-{b}
потому что-
не будет нить черезFactorial
это только нити болееList
.Сопоставитель шаблонов позаботится обо всем остальном и просто найдет правильное определение для применения.
источник
Haskell, 57 байт
С учетом ввода списка
l
, растет код OVSFs
, начиная с[1]
и повторно конкатенации либоs
или-s
, в зависимости от того делает первый элемент совпадающееl
. Затем проверяет, что результатl
в конце. Это проверено, как толькоs
имеет длину, по крайней мере, длиныl
.Некоторые альтернативы рекурсивным структурам также дают 57:
источник
MATLAB / Octave , 94 байта
При этом используется новый подход: разрешенные коды длины OVSF
N
появляются вlog2(N)
-ой матрице Уолша , так как они в основном определяются одной и той же рекурсией:Матрицы Уолша являются частными случаями матриц Адамара размера,
N x N
еслиN
является степенью двойки. (Существуют также матрицы Адамара других размеров.) MATLAB и Octave имеют множество встроенных функций, которые генерируют тестовые матрицы для проверки свойств численных алгоритмов, среди которых естьhadamard()
. К счастью для степеней использования двух MATLABhadamard()
точно построение валлийских матриц.Таким образом, эта функция сначала проверяет, является ли длина входов степенью двойки, и, если она есть, она проверяет, является ли она строкой валлийской матрицы соответствующего размера.
Попробуйте онлайн!
источник
Python, 64 байта
Разбивает список на четные и нечетные элементы с помощью срезов. Проверяет, являются ли векторы результата равными или отрицательными, умножая один на знак, навязанный его первым элементом. Затем выполняет ту же рекурсивную проверку для элементов с четным индексом.
Для базового случая, если проверка не пройдена, отклоняется, если список не установлен
[1]
. Пустой список также специально отклоняется, чтобы избежать бесконечного цикла.Другая стратегия, такая как мой ответ на Haskell, дает 66 байтов:
источник
Haskell ,
106 91 8786 байтФункция
g
генерируетn
итерацию списков (относительно неэффективно, посколькуlength $ g n == 3^n
, однако, если мы удалим дубликаты, мы получим2^n
),f
проверяет, есть ли наш список в каком-либо из них. Спасибо @Zgrab за несколько советов!Попробуйте онлайн!
источник
g
это очень неэффективно и производит тонну дублей. (Проверьте раздел отладки , это, вероятно, связано с ограничениями по времени или памяти.)JavaScript (ES6),
13093878583 байтадемонстрация
источник
JavaScript (ES6),
8561 байтПредыдущая версия, которая проверяла элементы, чтобы убедиться, что они были
1
или-1
:Объяснение:
a[22] == a[2] * a[4] * a[16]
. Такa[20] == a[4] * a[16]
как уже проверено,a[22] == a[2] * a[20]
нужно только проверить.i
не установлено хотя бы два бита. В случае установки нулевых битов он проверяет этоa[0] == a[0] * a[0]
, что ложно дляa[0] == -1
, в то время как в случае установки одного бита это проверяетa[i] == a[0] * a[i]
.источник
(l=a.length)&&!(l&l-1)
чтобы(l=a.length)&-l==l
сохранить 4 байтаl==0
ли?(l=a.length)&&l&-l==l
? сохранить 1 байт ...[1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,1,1]
даже без моих предложений.l&-l==l
не работает, потому что==
имеет более высокий приоритет, чем&
. И контрольный пример не работает из-за опечатки, которая будет стоить мне байта, чтобы исправить.MATL ,
2120 байтПопробуйте онлайн! Или проверьте все тестовые случаи .
Как это работает
Код разбивает массив на две части равной длины: первая с записями с нечетным индексом, вторая с записями с четным индексом. Две части должны иметь одинаковую длину, с добавочным нулем во второй при необходимости. Затем код проверяет, что
Если эти три условия соблюдены, процесс снова применяется к первому фрагменту. Если цикл завершен из-за того, что длина уже была равна 1, вводом является код OFSV. Иначе это не так.
Условие 1 повторное является эквивалентной версией определяющего свойства кодов OVSF. Для массива, скажем, длины 8, простой подход заключается в проверке того, что записи 1, 2, 3, 4 равны или все отличаются от записей 5, 6, 7, 8 соответственно (это определяющее свойство). Но мы можем эквивалентно проверить, что записи 1,3,5,7 все равны или отличаются от записей 2,4,6,8 соответственно; и это оказывается использовать меньше байтов.
Условие 2 гарантирует, что входная длина является степенью 2: если это не так, на некоторой стадии будет добавлен нулевой отступ.
источник
Haskell, 66 байт
Ууу, бесконечные списки!
Альтернативные версии:
источник
(0-)
трюк, я застрял сnegate
или((-1)*)
APL, 46 байт
Довольно просто:
0::0
: если произошла ошибка, верните 0⍵≡,1:1
: если ввод точно[1]
, вернуть 1⍬≡⍵:0
: если вход пустой список, вернуть 0Z←.5×⍴⍵
:Z
половина длины вводаY←⍵↓⍨Z
:Y
является последней половиной входных данных (это не работает, если⍴⍵
неравномерно, вызывая обработчик исключений)(∇Y)∨∇-Y
: либо последняя половина списка, либо отрицание последней половины списка, должно быть кодом OVSF(∇Z↑⍵)∧
: и первая половина списка должна быть кодом OVSF.источник
Haskell,
6968 байтПример использования:
g [-1,1]
->False
.Даже более неэффективно, чем ответ @ flawr . Это занимает слишком много времени и памяти для списков из 4 элементов. Чтобы увидеть, что список кодов OVSF (с большим количеством дубликатов) действительно создан, попробуйте:
который возвращается
т. е. список начинается со всех 16 списков элементов (из-за четырехкратной конкатенации
[1..4]
), продолжается со всеми 8 списками элементов и так далее, пока не заканчивается[1]
.Редактировать: @xnor сохранил байт. Благодарность!
источник
scanr
!any(elem x)
вместо,elem x$c
а не определяяc
.Python 2 ,
7875 байтПопробуйте онлайн!
источник
JavaScript (ES6), 80
Рекурсивно строит и проверяет каждый список по длине списка ввода, начиная с
[1]
.Возвращаемое значение JS truthy или falsey, в частности ,
1
илиtrue
если действительно,0
или ,false
или ,undefined
если не действует.Тест
источник
Clojure, 118 байт
Разбивает входные данные
c
на две половиныa
иb
и проверяет, все ли их поэлементные произведения идентичны. Если это так, проверяет, что первая половина является допустимой последовательностью.Это 142 байта, но я нашел его более интересным:
loop
вычисляетlog_2
длину ввода,iterate
генерирует последовательности из этого количества итераций на основе определения. Это возвращает входной аргумент, если это допустимая последовательность и вnil
противном случае.источник