Diberikan daftar 1
s dan -1
s, tentukan apakah itu kode OVSF yang valid (dengan mengeluarkan nilai truey atau falsey).
Kode OVSF didefinisikan sebagai berikut:
[1]
adalah kode OVSF.Jika
X
kode OVSF, makaX ++ X
danX ++ -X
keduanya kode OVSF.Berikut
++
adalah daftar gabungan, dan-
meniadakan setiap elemen dalam daftar.Tidak ada daftar lain yang merupakan kode OVSF yang valid.
Anda dapat menganggap daftar input hanya berisi -1
dan 1
, tetapi Anda harus menangani daftar kosong dengan benar, serta daftar yang panjangnya bukan kekuatan 2.
Kode terpendek (dalam byte) menang.
Uji kasus
[] -> 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
Jawaban:
Jelly ,
18161411 byteKeluaran
[1]
(kebenaran) untuk kode OVSF,[]
(falsy) sebaliknya.Cobalah online!
Latar Belakang
Seperti jawaban @ LuisMendo dari MATL dan @nama Python , kiriman ini memverifikasi array input "dari dalam ke luar".
Setiap pasangan (tanpa tumpang tindih) elemen kode OVSF dengan panjang dua atau lebih tinggi pada dasarnya adalah salinan dari pasangan pertama, baik dengan tanda yang sama atau dengan kedua tanda ditukar. Demikian juga, setiap elemen tuple (non-tumpang tindih) 4 elemen dari kode OVSF dengan panjang empat atau lebih tinggi pada dasarnya adalah salinan dari tuple 4-pertama, baik dengan tanda yang sama atau dengan kedua tanda bertukar. Hal yang sama berlaku untuk 8-tupel, 16-tupel, dll., Hingga panjang kode OVFS.
Salah satu cara untuk memverifikasi ini adalah dengan memeriksa semua pasangan untuk modul kesetaraan tanda pertama, kemudian menghapus elemen kedua dari setiap pasangan (yang sekarang menjadi informasi yang berlebihan). Jika kami mengulangi proses ini sekali lagi, pada dasarnya kami memeriksa semua 4-tupel. Dalam iterasi berikutnya, kami membandingkan 8-tupel, dll.
Akhirnya, jika semua yang diperlukan 2 k -tupel sama dengan modulo tanda dan array telah direduksi menjadi singleton, itu sudah cukup untuk memeriksa apakah elemen yang tersisa adalah 1 .
Bagaimana itu bekerja
sumber
Mathematica,
524745 byteHitungan byte mengasumsikan pengkodean CP-1252 dan
$CharacterEncoding
diatur keWindowsANSI
(default pada instalasi Windows).Ini mendefinisikan fungsi variadic
PlusMinus
, yang mengambil daftar input sebagai daftar datar argumen dan mengembalikan boolean, misalnyaPlusMinus[1, -1, -1, 1]
memberiTrue
. Ini secara teoritis juga dapat digunakan sebagai operator±
, namun operator yang hanya sintaksis berlaku dalam konteks unary dan biner, sehingga konvensi pemanggilan akan mendapatkan aneh:±##&[1,-1,-1,1]
. Ini akan membuang banyak peringatan yang bisa diabaikan.Ini juga akan melemparkan beberapa peringatan yang dapat diabaikan.
Ada mungkin berada jauh untuk mempersingkat agak mengganggu
a!==b!||{a}==-{b}
sebagian, tapi aku tidak menemukan apa-apa sekarang. Kata kunci sukaSubsetQ
danMatrixRank
terlalu panjang. : /Penjelasan
Solusi ini pada dasarnya menentang semua hal rumit pada pencocokan pola Mathematica dan karenanya sangat deklaratif dalam gaya. Terlepas dari beberapa golfitude di baris pertama, ini benar-benar hanya menambahkan tiga definisi berbeda untuk operator
±
:Dua baris pertama dipersingkat dengan menyarangkan definisi dan menyatakan
True
sebagai1>0
.Kita harus mendekonstruksi ini lebih jauh untuk menunjukkan bagaimana ini sebenarnya mendefinisikan fungsi variadci
PlusMinus
dengan hanya menggunakan notasi operator unary dan biner. Tangkapannya adalah bahwa semua operator hanyalah gula sintaksis untuk ekspresi penuh. Dalam kasus kami±
sesuai denganPlusMinus
. Kode berikut ini setara 100%:Dengan menggunakan urutan (semacam percikan seperti dalam bahasa lain) sebagai operan untuk
±
kita dapat membahas sejumlah argumen sewenang-wenangPlusMinus
, meskipun±
tidak dapat digunakan dengan lebih dari dua argumen. Alasan mendasarnya adalah bahwa sintaksis gula diselesaikan terlebih dahulu, sebelum sekuens ini diperluas.Aktif ke definisi:
Definisi pertama hanyalah mundur (
___
cocok dengan daftar argumen yang sewenang-wenang). Apa pun yang tidak cocok dengan definisi yang lebih spesifik di bawah ini akan memberikanFalse
.Definisi kedua adalah kasus dasar untuk OVSF, daftar yang hanya berisi
1
. Kami mendefinisikan ini sebagaiTrue
.Akhirnya, definisi ketiga hanya berlaku untuk daftar yang dapat didekomposisi menjadi
X ++ X
atauX ++ -X
, dan secara rekursif menggunakan hasilnyaX
. Definisi ini terbatas pada daftar-daftar ini dengan memastikan bahwa mereka dapat dibagi menjadi bagian-bagian berikutnyaa
danb
dengana__±b__
dan kemudian melampirkan kondisi (/;
) yang salah satu{a}=={b}
atau{a}==-{b}
. MendefinisikanPlusMinus
sebagai fungsi variadic dengan cara yang aneh ini melalui operator menghemat 5 byte kekalahan dari mendefinisikan operator unary±
pada daftar.Tapi tunggu, masih ada lagi. Kami menggunakan
a!==b!
sebagai gantinya{a}=={b}
. Jelas, kami melakukan ini karena dua byte lebih pendek, tetapi pertanyaan yang menarik adalah mengapa ini bekerja. Seperti yang saya jelaskan di atas, semua operator hanyalah gula sintaksis untuk beberapa ekspresi dengan kepala.{a}
adalahList[a]
. Tetapia
adalah urutan (seperti saya katakan, semacam seperti percikan dalam bahasa lain) jadi jikaa
ini1,-1,1
maka kita mendapatkanList[1,-1,1]
. Sekarang postfix!
adalahFactorial
. Jadi di sini, kita dapatkanFactorial[1,-1,1]
. TetapiFactorial
tidak tahu apa yang harus dilakukan ketika memiliki jumlah argumen yang berbeda dari satu, jadi ini tetap tidak dievaluasi.==
tidak benar-benar peduli jika hal di kedua sisi adalah daftar, itu hanya membandingkan ekspresi, dan jika mereka sama itu memberiTrue
(dalam hal ini, itu tidak akan benar-benar memberiFalse
jika tidak, tetapi pola tidak cocok jika kondisi mengembalikan apa pun selainTrue
). Jadi itu berarti, pemeriksaan kesetaraan masih berfungsi jika setidaknya ada dua elemen dalam daftar. Bagaimana jika hanya ada satu? Jikaa
masih1
makaa!
masih1
. Jikaa
ini-1
kemudiana!
memberikanComplexInfinity
. Sekarang, membandingkan1
dengan dirinya sendiri masih berfungsi dengan baik tentu saja. TetapiComplexInfinity == ComplexInfinity
tetap tidak dievaluasi, dan meskipun tidak memberikan kebenarana == -1 == b
. Untungnya, ini tidak masalah, karena satu-satunya situasi yang muncul adalahPlusMinus[-1, -1]
yang bukan OVSF yang valid pula! (Jika kondisinya kembaliTrue
, panggilan rekursif akan melaporkanFalse
lagipula, jadi tidak masalah kalau ceknya tidak berhasil.) Kita tidak bisa menggunakan trik yang sama karena{a}==-{b}
karena-
tidak akan di-threadedFactorial
, itu hanya di-threadedList
.Pencocokan pola akan mengurus sisanya dan hanya menemukan definisi yang tepat untuk diterapkan.
sumber
Haskell, 57 byte
Diberikan daftar input
l
, tumbuhkan kode OVSFs
dengan memulai dari[1]
dan berulang kali menyatukan salah satus
atau-s
, mana yang membuat elemen pertama cocok denganl
. Kemudian, periksa hasilnyal
di akhir. Ini dicentang setelahs
memiliki panjang setidaknya daril
.Beberapa alternatif struktur rekursif juga terjadi untuk memberikan 57:
sumber
MATLAB / Oktaf , 94 byte
Ini menggunakan pendekatan baru: Kode OVSF mengizinkan panjang
N
muncul dilog2(N)
-th Walsh-matriks , karena mereka pada dasarnya ditentukan oleh rekursi yang sama:Matriks Walsh adalah kasus khusus dari matriks Hadamard ukuran
N x N
jikaN
kekuatan dua. (Ada juga matriks Hadamard dengan ukuran lain.) MATLAB dan Oktaf memiliki beragam fungsi bawaan yang menghasilkan matriks uji untuk menguji sifat-sifat algoritma numerik, di antaranya adalahhadamard()
. Untungnya untuk kekuatan duahadamard()
usex MATLAB persis pembangunan matriks Welsh.Jadi fungsi ini pertama-tama memeriksa apakah panjang input adalah kekuatan dua, dan jika ya, ia memeriksa apakah itu adalah deretan ukuran yang sesuai dengan matriks Welsh.
Cobalah online!
sumber
Python, 64 byte
Pisahkan daftar menjadi elemen yang diindeks genap dan elemen indeks yang aneh melalui potongan. Periksa apakah vektor hasil sama dengan atau negatif dengan mengalikannya dengan tanda yang dipaksakan oleh elemen pertama. Kemudian, lakukan pemeriksaan rekursif yang sama pada elemen genap.
Untuk kasus dasar, jika pemeriksaan gagal, tolak kecuali daftar tersebut
[1]
. Daftar kosong juga secara khusus ditolak untuk menghindari loop tak terbatas.Strategi berbeda seperti jawaban Haskell saya memberikan 66 byte:
sumber
Haskell ,
106 91 8786 byteFungsi
g
menghasilkann
iterasi daftar (relatif tidak efisien, karenalength $ g n == 3^n
, namun jika kami menghapus duplikat, kami akan mendapatkan2^n
),f
memeriksa apakah daftar kami ada di salah satu dari mereka. Terima kasih kepada @Zgrab untuk beberapa petunjuk!Cobalah online!
sumber
g
adalah sangat tidak efisien dan menghasilkan ton duplikat. (Periksa bagian debug , mungkin karena keterbatasan waktu atau memori.)JavaScript (ES6),
13093878583 byteDemo
sumber
JavaScript (ES6),
8561 byteVersi sebelumnya yang memeriksa elemen untuk memastikan bahwa mereka
1
atau-1
:Penjelasan:
a[22] == a[2] * a[4] * a[16]
. Karenaa[20] == a[4] * a[16]
sudah diperiksa, hanyaa[22] == a[2] * a[20]
perlu diperiksa.i
tidak memiliki setidaknya dua bit yang ditetapkan. Dalam kasus set bit nol, ia memeriksa itua[0] == a[0] * a[0]
, yang salah untuka[0] == -1
, sedangkan dalam kasus set bit, ia memeriksa itua[i] == a[0] * a[i]
.sumber
(l=a.length)&&!(l&l-1)
ke(l=a.length)&-l==l
untuk menyimpan 4 bytel==0
?(l=a.length)&&l&-l==l
? untuk menghemat 1 byte ...[1,1,1,1,-1,-1,-1,-1,1,1,1,1,1,1,1,1]
bahkan tanpa saran saya.l&-l==l
tidak berfungsi karena==
memiliki prioritas lebih tinggi daripada&
. Dan test case tidak berfungsi karena kesalahan ketik yang akan memakan biaya satu byte untuk memperbaikinya.MATL ,
2120 byteCobalah online! Atau verifikasi semua kasus uji .
Bagaimana itu bekerja
Kode membagi array menjadi dua bagian dengan panjang yang sama: yang pertama dengan entri yang diindeks ganjil, yang kedua dengan entri yang diindeks genap. Dua potong dipaksa memiliki panjang yang sama, dengan bantalan nol di detik jika diperlukan. Kemudian kode memeriksa itu
Jika ketiga kondisi ini terpenuhi, proses tersebut diterapkan kembali pada bagian pertama. Jika loop keluar karena panjangnya sudah 1, inputnya adalah kode OFSV. Kalau tidak, tidak.
Kondisi 1 yang diulang adalah versi yang setara dengan properti pendefinisian kode OVSF. Untuk larik dengan panjang say 8, pendekatan langsung adalah memeriksa bahwa entri 1,2,3,4 semuanya sama atau semuanya berbeda dengan entri 5,6,7,8 (ini adalah properti pendefinisian). Tetapi kita dapat memeriksa secara setara bahwa entri 1,3,5,7 semuanya sama atau berbeda dengan entri 2,4,6,8; dan ini ternyata menggunakan byte lebih sedikit.
Kondisi 2 memastikan bahwa panjang input adalah kekuatan 2: jika tidak, nol padding akan diperkenalkan pada beberapa tahap.
sumber
Haskell, 66 byte
Yay, daftar tak terbatas!
Versi alternatif:
sumber
(0-)
triknya, saya terjebak dengannegate
atau((-1)*)
APL, 46 byte
Cukup mudah:
0::0
: jika terjadi kesalahan, kembalikan 0⍵≡,1:1
: jika inputnya tepat[1]
, kembalikan 1⍬≡⍵:0
: jika inputnya adalah daftar kosong, kembalikan 0Z←.5×⍴⍵
:Z
adalah setengah panjang inputY←⍵↓⍨Z
:Y
adalah bagian terakhir dari input (ini gagal jika⍴⍵
tidak rata, memicu pengendali pengecualian)(∇Y)∨∇-Y
: baik paruh terakhir daftar, atau negasi dari paruh terakhir daftar, harus berupa kode OVSF(∇Z↑⍵)∧
: dan paruh pertama daftar harus berupa kode OVSF.sumber
Haskell,
6968 byteContoh penggunaan:
g [-1,1]
->False
.Bahkan lebih tidak efisien daripada jawaban @ flawr . Terlalu banyak waktu dan memori untuk 4 daftar elemen. Untuk melihat bahwa daftar kode OVSF (dengan banyak duplikat) sebenarnya dibuat, coba:
yang kembali
yaitu daftar dimulai dengan semua 16 daftar elemen (4 kali digabung, karena
[1..4]
), berlanjut dengan semua 8 daftar elemen dan seterusnya sampai berakhir dengan[1]
.Sunting: @xnatau disimpan satu byte. Terima kasih!
sumber
scanr
!any(elem x)
alih - alihelem x$c
dan tidak mendefinisikanc
.Python 2 ,
7875 byteCobalah online!
sumber
JavaScript (ES6), 80
Secara rekursif membangun dan memeriksa setiap daftar hingga panjang daftar input, dimulai dengan
[1]
.Nilai pengembalian adalah kebenaran atau falsey JS, khusus
1
atautrue
jika valid,0
ataufalse
atauundefined
jika tidak valid.Uji
sumber
Clojure, 118 byte
Membagi input
c
menjadi dua bagiana
danb
dan memeriksa apakah produk elemen-bijaksana semuanya identik. Jika demikian, periksa apakah babak pertama adalah urutan yang benar.Yang ini 142 byte tetapi saya merasa lebih menarik:
loop
menghitunglog_2
panjang input,iterate
menghasilkan urutan iterasi yang banyak berdasarkan definisi. Ini mengembalikan argumen input jika urutannya valid dannil
sebaliknya.sumber