Latar Belakang
Pernyataan deklarasi variabel dalam C terdiri dari tiga bagian: nama variabel, tipe dasarnya , dan tipe pengubah .
Ada tiga jenis pengubah tipe:
- Pointer
*
(awalan) - Array
[N]
(postfix) - Fungsi
()
(postfix)- Anda dapat menentukan daftar argumen fungsi di dalam parens, tetapi untuk tantangan ini, mari kita abaikan dan gunakan saja
()
(yang secara teknis berarti "fungsi dapat mengambil segala jenis argumen").
- Anda dapat menentukan daftar argumen fungsi di dalam parens, tetapi untuk tantangan ini, mari kita abaikan dan gunakan saja
Dan cara membaca notasi adalah sebagai berikut:
int i; // i is an int
float *f; // f is a pointer to a float
my_struct_t s[10]; // s is an array of 10 my_struct_t
int func(); // func is a function returning an int
Tangkapannya adalah kita dapat menggabungkan semua ini untuk membentuk tipe yang lebih rumit, seperti array array atau array fungsi pointer atau pointer ke array pointer :
int arr[3][4];
// arr is an array of 3 arrays of 4 ints
int (*fptrs[10])();
// fptrs is an array of 10 pointers to functions returning an int
float *(*p)[16];
// p is a pointer to an array of 16 pointers to float
Bagaimana saya membaca pernyataan rumit ini?
- Mulai dari nama variabel.
(name) is ...
- Pilih pengubah dengan prioritas tertinggi.
- Membacanya:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Ulangi 2 dan 3 sampai pengubah habis.
- Terakhir, baca tipe dasar.
... (base type).
Dalam C, operator postfix didahulukan dari pada operator prefix, dan pengubah tipe tidak terkecuali. Karena itu, []
dan ()
ikat terlebih dahulu, lalu *
. Apa pun di dalam sepasang parens (...)
(jangan dikelirukan dengan operator fungsi) mengikat pertama di atas apa pun di luar.
Contoh ilustrasi:
int (*fptrs[10])();
fptrs fptrs is ...
[10] array of 10 ... // [] takes precedence over *
(* ) pointer to ...
() function returning ...
int int
Tugas
Diberikan garis pernyataan deklarasi variabel yang ditulis dalam C, output ekspresi bahasa Inggris yang menggambarkan garis, menggunakan metode yang ditunjukkan di atas.
Memasukkan
Input adalah pernyataan C tunggal yang mencakup jenis basis tunggal, nama variabel tunggal, nol atau lebih jenis pengubah dan titik koma akhir. Anda harus menerapkan semua elemen sintaks yang dibahas di atas, ditambah:
- Baik tipe dasar dan nama variabel cocok dengan ekspresi reguler
[A-Za-z_][A-Za-z0-9_]*
. - Secara teoritis, program Anda harus mendukung pengubah tipe dalam jumlah tidak terbatas.
Anda dapat menyederhanakan elemen sintaks C lainnya dengan cara berikut (implementasi penuh juga diterima):
- Jenis dasar selalu satu kata, misalnya
int
,float
,uint32_t
,myStruct
. Sesuatu sepertiunsigned long long
tidak akan diuji. - Untuk notasi array
[N]
, angkaN
akan selalu berupa bilangan bulat positif tunggal yang ditulis dalam basis 10. Hal-hal sepertiint a[5+5]
,int a[SIZE]
atauint a[0x0f]
tidak akan diuji. - Untuk notasi fungsi
()
, tidak ada parameter yang ditentukan sama sekali, seperti yang ditunjukkan di atas. - Untuk spasi putih, hanya karakter spasi yang
0x20
akan digunakan. Anda dapat membatasi program Anda untuk penggunaan spasi putih tertentu, misalnya- Gunakan hanya satu spasi setelah tipe dasar
- Gunakan ruang di mana-mana di antara token
- Namun, Anda tidak dapat menggunakan dua atau lebih spasi berturut-turut untuk menyampaikan lebih banyak informasi daripada menjadi pemisah token.
Menurut sintaks C, tiga kombinasi berikut tidak valid, dan karenanya tidak akan diuji:
f()()
Fungsi mengembalikan fungsif()[]
Berfungsi mengembalikan arraya[]()
Array fungsi N
Pengembang C menggunakan formulir yang setara ini sebagai gantinya (dan semua ini tercakup dalam kasus uji):
(*f())()
Fungsi mengembalikan pointer ke fungsi*f()
Fungsi mengembalikan pointer ke elemen pertama array(*a[])()
Array N pointer berfungsi
Keluaran
Outputnya adalah satu kalimat bahasa Inggris. Anda tidak perlu (tetapi Anda bisa jika mau) menghormati tata bahasa Inggris, misalnya penggunaan a, an, the
, bentuk tunggal / jamak, dan titik akhir (titik). Setiap kata harus dipisahkan oleh satu atau lebih spasi putih (spasi, tab, baris baru) sehingga hasilnya dapat dibaca oleh manusia.
Sekali lagi, inilah proses konversi:
- Mulai dari nama variabel.
(name) is ...
- Pilih pengubah dengan prioritas tertinggi.
- Membacanya:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- Ulangi 2 dan 3 sampai pengubah habis.
- Terakhir, baca tipe dasar.
... (base type).
Uji kasus
int i; // i is int
float *f; // f is pointer to float
my_struct_t s[10]; // s is array of 10 my_struct_t
int func(); // func is function returning int
int arr[3][4]; // arr is array of 3 array of 4 int
int (*fptrs[10])(); // fptrs is array of 10 pointer to function returning int
float *(*p)[16]; // p is pointer to array of 16 pointer to float
_RANdom_TYPE_123 (**(*_WTH_is_TH15)())[1234][567];
/* _WTH_is_TH15 is pointer to function returning pointer to pointer to array of
1234 array of 567 _RANdom_TYPE_123 */
uint32_t **(*(**(*(***p)[2])())[123])[4][5];
/* p is pointer to pointer to pointer to array of 2 pointer to function returning
pointer to pointer to array of 123 pointer to array of 4 array of 5 pointer to
pointer to uint32_t */
uint32_t (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5]);
// Same as above, just more redundant parens
some_type (*(*(*(*(*curried_func())())())())())();
/* curried_func is function returning pointer to function returning pointer to
function returning pointer to function returning pointer to
function returning pointer to function returning some_type */
Kriteria Penilaian & Menang
Ini adalah tantangan kode-golf . Program dengan jumlah byte terkecil menang.
int arr[3][4];
adalahan array of 3 arrays of 4 ints
(seperti yang Anda katakan), atauan array of 4 arrays of 3 ints
?sizeof(arr[0]) == sizeof(int[4])
, jadi itemarr
berisi empatint
s.;
di akhir baris?Jawaban:
Python 3 ,
331 312 294 261240 byteCobalah online!
-19 byte dengan beralih ke python 2 dan menempatkan definisi kelas menjadi sebuah
exec
-18 byte dengan mengubah regex dari
[a-zA-Z_][a-zA-Z0-9_]*
menjadi\\w+
, terima kasih kepada Kevin Cruijssen-33 byte dengan mengerjakan beberapa sihir definisi kelas dan memanfaatkan str, terima kasih kepada Lynn, berubah kembali ke python 3
-21 byte dengan menggabungkan beberapa regex, berkat infmagic2047
Mengharuskan hanya satu ruang yang terkandung dalam input (antara jenis dan ekspresi).
Saya pikir ini adalah pendekatan yang cukup unik untuk masalah ini. Ini sebagian besar menggunakan fakta bahwa Python sendiri dapat mengevaluasi string seperti
(**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5])
dan mendapatkan urutan yang benar dari panggilan fungsi, indeks array dan pointer - dan bahwa pengguna dapat membebani ini.sumber
[a-zA-Z_][A-Za-z0-9_]*
untuk[a-zA-Z_]\\w*
menyimpan beberapa byte. EDIT: Sebenarnya, saya pikir Anda bisa menggunakan\\w+
saja[a-zA-Z_][A-Za-z0-9_]*
.[0]
daripada.group()
sejak Python 3.6.Retina 0.8.2 ,
142138128117 byteCobalah online! Tautan termasuk kasus uji. Tata bahasa yang lebih baik . Sunting: Disimpan
1021 bytes dengan porting @ solusi DLosc Pip. Penjelasan:Pindahkan tipe ke ujung dan bungkus sisa dari deklarasi
()
s jika seandainya itu mengandung bagian luar*
.Memproses fungsi apa pun.
Memproses array apa pun.
Pindahkan pointer ke ujung tanda kurung mereka, dan hapus tanda kurung, berulang kali bekerja dari set kurung terluar ke dalam.
Memproses petunjuk apa pun.
Masukkan
is
.sumber
Java 11,
469467463450 byteCobalah online.
Penjelasan:
sumber
Bash + cdecl + sed GNU, 180
cdecl
adalah utilitas Unix yang terhormat yang melakukan sebagian besar dari apa yang diperlukan di sini, tetapi untuk mencocokkan persyaratan I / O, diperlukan beberapased
pra dan pasca pemrosesan:sed Pra-pemrosesan:
s/^/explain struct /
- Tambahkan "jelaskan struct" ke awal setiap bariss/struct (int|char double|float|void) /\1 /
- Hapusstruct
saat berhadapan dengan jenis bahasa C.s/\bfunc/_func/g
- "func" dikenali sebagai kata kunci oleh cdecl - suppress thissed Pasca pemrosesan:
s/^declare //
- hapus "nyatakan" pada awal bariss/as/is/
- Cukup jelass/struct //g
- hapus semua kata kunci "struct"s/([0-9]+) of/of \1/g
- pemesanan "dari" yang benars/\b_func/func/g
- kembalikan "_func" apa pun yang diganti pada pra-pemrosesanBeraksi:
sumber
s/\bfu/_fu/g
dan menyimpan byte darifunc
penggantian penuh ?as
(+4 byte untuk spasi untuk diperbaiki). Saya tidak memiliki akses kecdecl
tetapi saya pikir Anda dapat menghemat 64 byte menggunakansed -r 's/^(\w+)(\W+)/explain struct \1_\2_/'|cdecl|sed -r 's/^declare struct _|_$//;s/ as / is /;s/([0-9]+) of/of \1/g'
.Pip
-s
,152150148139137126125123 bytePendekatan ketiga!
Mengambil deklarasi sebagai input baris perintah. Cobalah online!
Penjelasan
Kode ini ada dalam tiga bagian: pengaturan awal dan penanganan fungsi dan array; loop yang menangani tanda kurung dan pointer; dan penataan ulang akhir.
Pengaturan, fungsi & array
Kami ingin seluruh deklarasi menjadi tanda kurung (ini membantu dengan loop nanti), jadi kami mengubahnya
type ...;
menjaditype (...)
. Kemudian, amati bahwa tidak ada pemesanan ulang yang dilakukan dengan deskripsi fungsi dan array, sehingga kami dapat melakukan semua penggantian itu terlebih dahulu tanpa mempengaruhi hasil akhir.Jika input asli kami adalah
float *((*p()))[16];
, sekarang kami milikifloat (*((*p function returning)) array of 16)
.Tanda kurung dan pointer
Kami menjalankan lingkaran menggantikan sepasang kurung terluar dan tanda bintang yang langsung di dalam paren pembuka.
Langkah-langkah contoh:
Membersihkan
Satu-satunya yang tersisa adalah memindahkan tipe ke ujung dan menambahkan "adalah":
Untuk definisi seperti
int x;
, pendekatan ini akan menghasilkan ruang tambahan, yang diizinkan oleh tantangan.sumber
JavaScript (ES6),
316...268253 byteCobalah online!
Berkomentar
Fungsi pembantu
Bagian utama
sumber
[...s.split`()`.join`!`]
bukan hanya[...s.replace('()','!')]
, tetapi saya menyadari itu adalah byte-count yang sama persis .. :)s.replace('()','!')
hanya mengganti kejadian pertama..replace
menggantikan semua kejadian, dan.replaceAll
mengganti semua kejadian dengan mengaktifkan regex. Selalu berpikir penamaan itu cukup buruk untuk kedua metode ini di Jawa, karena saya akan memanggil mereka.replaceAll
dan.regexReplaceAll
atau sesuatu di sepanjang garis itu, tapi saya kira untuk codegolf lebih pendek sebagai.replace
dan.replaceAll
.~
) setelah memposting versi pertama dari jawaban saya sendiri. Pikiran besar berpikir sama, saya kira. : pBersih , 415 byte
Cobalah online!
sumber
R ,
225218 byteCobalah online!
Program lengkap, dibungkus dengan fungsi pada TIO untuk memudahkan pengujian semua kasus uji sekaligus.
Pertama, kami menggunakan Regex untuk mengonversi input formulir
type ...name...;
ke..."name is"..."type"
. Notasi fungsi()
kemudian dikonversi ke teks dengan operator gabungan didahulukan tinggi. Sayangnya, kami juga harus mengganti*
dengan+
yang sebelumnya tidak dapat diterima sebagai operator unary. Sisanya dilakukan oleh R'seval
dengan operator kelebihan beban.sumber
Perl 6 ,
209190171162153 byteCobalah online!
Pendekatan regex rekursif. Menghasilkan beberapa karakter ruang ekstra yang dapat dihindari dengan biaya 3 byte .
Penjelasan
sumber
JavaScript 250 Bytes [249?]
Ini menggunakan 250 Bytes:
Penjelasan:
Pada dasarnya, ini membaca dari buffer
a
, yang merupakan input tokenized. Ini terus-menerus memindahkan token dari buffera
ke tumpukans
, hingga mode evaluasi dipicu. Mode evaluasi akan mengkonsumsi operasi postfix terlebih dahulu()
,[]
dari buffer, dan kemudian akan mengkonsumsi operator prefix*
dari stack. Mode evaluasi dipicu ketika keadaan di mana kata akan berada (Entah nama ketik ditemukan dan dikonsumsi, atau akhir)
ditemukan dan dihapus). Mode evaluasi dinonaktifkan ketika tidak ada lagi operator awalan / postfix yang ditemukan.CATATAN
Jika saya mengerti "Gunakan spasi di mana-mana di antara token" dengan benar:
secara teknis valid, dan menggunakan
249 Bytes
Dengan asumsi ada ruang di antara setiap token.
sumber
Merah ,
418410 byteCobalah online!
Penjelasan:
sumber
APL (NARS), karakter 625, byte 1250
ini hanya satu traslasi dari bahasa C ke APL dari kode dalam buku: "Linguaggio C" oleh Brian W. Kerninghan dan Dennis M. Ritchie bab 5.12. Saya tidak tahu bagaimana mengurangi semua itu karena saya belum mengerti 100% kode itu, dan karena saya tidak tahu terlalu banyak tentang APL ... Fungsi untuk latihan itu adalah f; saya pikir hanya diperbolehkan 150 nested parentesis '(' ')' untuk kesalahan mengembalikan satu batang dengan satu nilai negatif di dalamnya atau string descrition jika semuanya ok. Tampaknya ini tidak lebih baik daripada versi lain meskipun karakternya lebih sedikit karena yang lain melihat kesalahan lebih baik. Beberapa tes:
sumber