Kita semua telah melihat "hax matematika" daring yang terlihat seperti ini:
Think of a number, divide by 2, multiply by 0, add 8.
Dan, secara ajaib, semua orang berakhir dengan angka 8!
Bahasa
Mari kita mendefinisikan bahasa pemrograman yang menggunakan sintaks teks di atas, yang disebut "WordMath". Script WordMath ikuti templat ini:
Think of a number, <commandlist>.
Yang pada dasarnya berarti: Ambil nomor (sebagai input dari STDIN) sebagai akumulator awal, lakukan semua perintah di atasnya, dan hasilkan hasilnya.
Perintah dipisahkan oleh pembatas ,
(koma + spasi). Perintah yang valid adalah (catatan yang #
mewakili integer non-negatif :) :
add #
/subtract #
- Tambahkan / kurangi nilai dari akumulator.divide by #
/multiply by #
- floordiv / kalikan akumulator dengan nilai yang diberikan.subtract from #
- Mirip dengansubtract
, tetapiacc = # - acc
bukanacc = acc - #
repeat
- lakukan perintah terakhir lagi. Ini bukan perintah pertama, tetapi Anda harus mendukung berulang berulang kali.
Tantangan
Tugas Anda adalah untuk membuat program atau fungsi yang mengambil script WordMath berlaku sebagai masukan dan transpiles menjadi program penuh valid - dalam bahasa yang sama kode Anda di.
Misalnya, jika kode saya ada di Python 2 dan skripnya adalah:
Think of a number, subtract from 10, add 10, multiply by 2.
Program yang dihasilkan dapat:
a = input()
a = 10 - a
a += 10
a *= 2
print(a)
Atau sebagai alternatif:
print(((10-input())+10)*2)
Selama itu adalah program lengkap yang mengambil input dari STDIN
dan dicetak ke STDOUT
, atau setara bahasa terdekat.
Aturan
- Program asli Anda dapat mengasumsikan bahwa input selalu berupa skrip WordMath yang valid.
- Program yang diubah-ubah tidak harus menangani kesalahan matematika seperti pembagian dengan 0.
- Program yang diubah-ubah dapat mengasumsikan bahwa input mewakili integer bertanda tangan yang valid, dalam rentang integer standar bahasa Anda.
- Ini adalah kode-golf , sehingga solusi terpendek (dalam byte) menang.
- Hanya hitungan byte dari program asli Anda yang penting - kode yang dihasilkan dapat sepanjang yang Anda inginkan!
Contoh Skrip
Contoh 1:
Think of a number.
Ambil input, jangan lakukan apa-apa, tampilkan: Program kucing WordMath.
Contoh 2:
Think of a number, divide by 5, subtract from 9.
Ingat bahwa "membagi" adalah pembagian lantai, jadi untuk program ini 6 -> 8
, dan 29 -> 4
.
Contoh 3:
Think of a number, add 5, add 10, multiply by 2, subtract 15, repeat, divide by 2.
Program kucing diperpanjang!
Contoh 4:
Think of a number, subtract 1, repeat, repeat.
Mengambil angka dan mengurangi 3.
-5/3
? Apakah kita berputar menuju0
atau menuju infinity negatif?Jawaban:
05AB1E ,
59565452 byteCobalah online!
Otak saya sakit sekali setelah itu ... Outputnya dalam kode 05AB1E sebagai berikut:
Think of a Number
dihapus, karena input implisit.Subtract From #
bulu ke#s-
(pertukarana
danb
dan melakukan operasi).Subtract #
dikonversi ke#-
.Add #
dikonversi ke#+
.Multiply by #
dikonversi ke#*
.Divide by #
dikonversi ke#/
.Repeat
meraih apa pun yang terakhir disimpan dalam register dan menyatukannya.Dijelaskan:
Contoh:
Memasukkan:
Keluaran:
Coba solusi dengan input 10:
Cobalah online!
Lihat di google:
Berikut tautan ke persamaan yang sama yang diketikkan ke google.
sumber
C Preprocessor, 362 Bytes
SAYA HAMPIR menjalankan ini di HANYA preprocessor C, tetapi perintah repeat ternyata terlalu sulit untuk diimplementasikan. Jadi alih-alih saya menggunakan preprocessor untuk mengubah input menjadi array yang kemudian ditafsirkan oleh beberapa kode tambahan.
Input harus disediakan di "input.wm" atau baru saja dibuang di sumber di baris itu. Saya memasukkan byte-nya ke dalam hitungan saya karena saya pikir itu sedikit aneh dan sedikit bertentangan dengan aturan tantangan, jadi itu hanya cocok.
Bagaimanapun, setelah Anda membuang sumber WordMath Anda ke input.wm di mana kompiler dapat menemukannya, Anda harus dapat mengkompilasi ini, seperti halnya, dengan peringatan untuk menghasilkan executable yang melakukan apa yang dikatakan sumber WordMath.
sumber
Retina, 170 byte
Karena siapa yang tidak mau melihat ini ?!
Saya memikirkan betapa hebatnya melihat solusi Retina, dan saya memutuskan untuk membuatnya dengan cepat. Hanya butuh satu jam. Seperti biasa, hitungan byte mengasumsikan penyandian ISO 8859-1.
Cobalah online
Output memiliki baris baru yang tidak boleh disalin ketika menguji program yang dihasilkan. Program ini tidak mendukung negatif, karena rentang integer standar Retina (dalam unary) tidak.
Penjelasan:
Program matematika:
Menambahkan:
Tambahkan jumlah yang ke awal. Tambahkan 5:
Mengurangi:
Hapus jumlah yang dari awal. Kurangi 5:
Kurangi dari:
Ganti input
1
denganx
s. Letakkan di sebelah nomor tetap. Hapus berulang kalix1
. Kurangi dari 10:Kalikan dengan:
Gantilah setiap orang
1
dengan jumlah tertentu. Kalikan dengan 3:Dibagi dengan:
Ini menggunakan program Retina saya untuk Divisi Integer . Bagi dengan 2:
sumber
$
cocok di bagian paling akhir string atau di depan linefeed line. Anda perlu\z
jika Anda hanya menginginkan yang pertama.GNU awk, 139 byte
Doa:
Kasus uji:
sumber
Haskell,
232231 byteTentu saja seorang programmer fungsional lebih suka mengembalikan fungsi daripada string yang mewakili suatu program, tetapi di sini kita mulai:
Keterangan: Kami selalu memulai dengan menambahkan nol, jika tidak, transpilasi dari program WordMath yang sepele tidak akan memberikan informasi yang cukup untuk menyimpulkan jenis yang
read
digunakan.subtract from n
dapat diimplementasikan sebagai(n-)
, tapi saya gunakan((-)n)
untuk lebih banyak keseragaman. Dalam halsubtract n
saya menyalinsubtract
dari input jadi saya tidak perlu menulisnya, tapi saya harus mengganti ruang yang hilang di bagian akhir.repeat
digunakan sebagai operasi default; bersama dengan operasi awal awal kosong ini memungkinkan untuk dengan mudah mengabaikan empat kata pertama.Contoh penggunaan:
Contoh lain memberikan hasil sebagai berikut:
sumber
h
mungkin terlihat sepertih s n r|x<-s.read.init$n=x%r.x
dan dipanggil dengan argumen pertama fungsi sepertih(+)n r
(dan perlu ada beberapaflip
tempat untuk mendapatkan urutan operator yang benar), kasus dasar adalah_%_=id
. Fungsi utama dapat menghindari semua boilerplate dan hanya menjadit l=id%words l
. - Berkat currying, itu mungkin dilihat sebagai penerjemah, dan gagasan itu mungkin mengarah pada solusi yang lebih mudah dan / atau lebih pendek.Python 2,
263258260221 byteIni mungkin masih bisa jauh lebih pendek.
Cobalah online
Saya menggunakan
//
bukan/
, karena instruksi terakhir akan memiliki.
pada akhirnya, membuat angka apa pun menjadi mengambang. Jadi untuk menjaga agar divisi tetap konsisten, saya menggunakan divisi integer.Output kasus uji:
sumber
if
so
menjadi yang berikut (yang menurut saya harusnya berfungsi)o=[[o+[['+-'['s'in c],'//']['v'in c],'*']['m'in c]+n,n+'-'+o]['f'in c],'input()']['T'in c]
:, Anda bisa turun ke 224.Befunge,
342305 byteCobalah online!
Keluaran
Kode yang dihasilkannya dimulai dengan perintah
&
(nilai input), dan diakhiri dengan perintah.
(nilai output) dan@
(keluar). Di antara kita memiliki berbagai perhitungan dalam bentuk<number><operation>
, di mana operasi dapat+
(tambah),-
(kurangi),/
(bagi dengan),*
(dikalikan dengan), dan\-
(kurangi dari).The jumlah itu sendiri adalah sedikit rumit, karena Befunge hanya mendukung literal numerik di kisaran 0 sampai 9, jadi segala sesuatu lebih besar dari kebutuhan yang dihitung secara manual. Karena kita sudah membaca angka-angka dalam karakter demi karakter, kita cukup membangun angka ketika setiap digit dibaca, jadi misalnya, 123 menjadi
155+*2+55+*3+
, yaitu(((1 * 10) + 2) * 10) + 3
.Contohnya
Penjelasan
Befunge tidak memiliki kemampuan untuk memanipulasi string, jadi sebagian besar parsing ditangani dengan menghitung karakter. Kita mulai hanya dengan melewatkan 18 karakter pertama, yang membuat kita melewati Think of a number number (ditambah koma atau titik). Kemudian jika karakter berikutnya adalah beberapa bentuk baris baru atau EOF kita langsung ke rutin output, jika tidak kita terus mencari daftar perintah.
Untuk mem-parsing perintah, kita terus menghitung karakter sampai kita mencapai angka atau pemisah. Jika itu pemisah, itu pasti perintah ulang yang kami tangani sebagai kasus khusus. Jika ini digit, kami menambahkannya ke buffer output, dan terus mencari digit lainnya. Setiap kali angka adalah output, kami awali dengan
55+*
(untuk mengalikan total sejauh ini dengan 10) dan sufiks dengan+
(untuk menambahkannya ke total). Setelah digit selesai kita tambahkan karakter perintah.Adapun cara perintah ditentukan, kita mengambil jumlah karakter hingga modulo digit pertama 7. Untuk menambahkan ini adalah 4 (termasuk spasi berikut), untuk kurangi itu 2, untuk bagi dengan itu 3, untuk kalikan dengan itu 5 , dan untuk mengurangi dari 0. Kurangi dari memerlukan sedikit penanganan tambahan karena membutuhkan
\-
kombo perintah, tetapi yang lain hanya menggunakan nilainya untuk mencari karakter perintah yang sesuai dalam sebuah tabel.Proses ini diulangi untuk setiap perintah, membangun output menjadi string yang telah dibangun sebelumnya pada baris 8. Setiap kali perintah tambahan ditambahkan, kami juga menambahkan kutipan penutup ke string untuk memastikan selalu diakhiri dengan benar. Kemudian ketika kita akhirnya mencapai akhir dari input kita, kita cukup "mengeksekusi" string ini untuk mendorongnya ke stack, kemudian ikuti itu dengan urutan output standar untuk menuliskan semuanya.
sumber
JavaScript (ES6), 163 byte
Cobalah:
sumber
Vim
208171168 byteMenambahkan kemampuan untuk melakukan beberapa pengulangan berturut-turut seperti pada @ Flp.Tkc tetapi golf cukup byte sehingga saya masih bisa menurunkan jumlah byte.
TryItOnline
Karakter yang tidak dapat dicetak:
Output kasus uji:
cw^R=^R" ^[
TryItOnlinecw^R=((^R" /5) *-1+9) ^[
TryItOnlinecw^R=((((((^R" +5) +10) *2) -15) -15) /2) ^[
TryItOnlinesumber
lex, 246 byte
lex menargetkan ke C, jadi kompiler C perlu mengkompilasinya menjadi sesuatu yang dapat dieksekusi. Pustaka lexer (
ll
) juga perlu ditautkan. Ini dapat menambahkan byte-penalti, tetapi saya tidak yakin berapa byte jika demikian.Program ini menghasilkan program lex (per spesifikasi) yang mengevaluasi ekspresi wordmath yang di-transpilasikan. Kode antara
%{
dan%}
hanya untuk "transpiler":Antara dua
%%
baris adalah bagian regex / action. Aturan pertama yang harus dicocokkan adalahT
("Pikirkan ...") yang membangun mukadimah (paling sedikit program lex harus memuat bagian aturan setidaknya, danyytext
merupakan teks yang cocok terakhir, sehingga aturan tersebut pada dasarnya menaburkan akumulator dengan input pengguna. ).Program membuang semua masukan kecuali yang yang cocok, dan aturan-aturan lainnya (
ad
,fr
, sampaire
) menangani klausa ekspresi wordmath dengan sebagai pertandingan seminimal mungkin untuk menjadi unik. Dalam sebagian besar dari ini, ia menetapkanc
ke infix ekspresi, yang akan digabungkan antaran
dan bilangan bulat terakhir dibaca ketikaO
dipanggil (jadi misalnya, membaca "tambah 9" akan mengatur infiks menjadi+=
, v ke9
, dan panggilan keO
akan menampilkann+=9;
) . (Disamping yang menarik adalah bahwa "kurangi dari 8" akan menyebabkan keduanyas
danfr
aturannya cocok, tetapi karenaO
dipanggil hanya pada angka, aturan yang tepatn=-n+8;
adalah satu-satunya ekspresi yang mendapat output). There
aturan untuk "repeat" hanya panggilanO
lagi, yang menampilkan ekspresi yang terakhir dibuat (dan karena kecocokan berikutnya akan gagalyytext
, mendukung "ulangi" adalah mengapa konversi integer dalam[0-9]+
aturan diperlukan). Akhirnya, suatu periode menyebabkan trailer program menjadi output, yang hanya menampilkan akumulator dan ditutup dengan%%
pasangan yang menunjukkan akhir dari program lex output.Catatan: Program transpiler utama atau program keluaran tidak akan berakhir. Input perpipaan akan berfungsi, atau menyediakan EOF (ctrl-D). Jika penghentian diperlukan setelah input pertama, exit () s dapat ditambahkan.
Untuk membangun / menjalankan:
Tes 1:
Tes 2:
Tes 3:
Tes 4:
sumber
Pyth,
6967 byteProgram yang mengambil input dari
"quoted string"
dan mencetak hasilnya.Suite uji
Bagaimana itu bekerja
Pyth memiliki operator awalan, sehingga operasi aritmetika dasar dilakukan menggunakan
(operator)(operand1)(operand2)
, sedangkan variabel pra-diinisialisasiQ
memberikan input. Oleh karena itu, program WordMath yang dibuat ulang dibangun dengan memulai dengan string'Q'
, dan pada setiap tahap, membuat prap Operator, dan kemudian menambahkan atau menambahkan operan sebagai neccessary.J\Q
AturJ
, string program yang ditranskripsikan, ke string'Q'
tcQ\,
Pisahkan input pada koma, dan buang elemen pertama (yaitu 'Think of a number'
)V
UntukN
itu:Iq@N1\r
Jika karakter atN[1]
is'r'
(repeat):=NZ
SetelN
keZ
(nilai sebelumnyaN
, atur di akhir for for loop)x"asdm"@N1
Temukan indeksN[1]
dalam"asdm"
(tambah, kurangi, bagikan, gandakan)@"+-/*"
Indeks dengan itu menjadi"+-/*"
, memberikan operator yang dibutuhkan,J-eCN)\.
Hasilkan daftar dua elemen[J, -eCN)\.]
, di mana elemen kedua adalah elemen terakhir dariN
perpecahan pada spasi putih dengan'.'
karakter apa pun dihapus (operan)qh@cN)1\f
Jika karakter pertama dari elemen keduaN
split di whitespace adalah'f'
(kurangi dari):.>
Tukar elemen daftar dua elemen+
Gabungkan daftar operator dan dua elemen menjadi satu daftar=Jjd
SetelJ
ke yang bergabung di spasi=ZN
SetelZ
keN
J
MencetakJ
sumber
Pip , 58 byte
Sayang sekali saya belum mengimplementasikan operator reverse-pengurangan itu.
Program ini mengambil skrip WordMath dari stdin dan menampilkan kode Pip ke stdout. Kode yang merupakan keluaran, juga mengambil angka dari stdin dan menampilkan hasilnya ke stdout. Cobalah online!
Strategi
Untuk input seperti ini:
kami ingin output seperti ini:
yang berfungsi sebagai berikut:
Penjelasan + tidak dikelompokkan
Struktur dasar dari program ini adalah
{...}Mq^k
, yang membelahq
(garis stdin) padak
(koma-ruang) danM
aps fungsi untuk setiap elemen.Di dalam fungsi, kita mulai dengan menangani
repeat
kasing. Tes terpendek di Pip tampaknyasNa
(apakah ada spasi di perintah). Jika demikian, kami ingin menggunakana
; jika tidak, gunakanp
, yang menyimpan perintah sebelumnya. Tetapkan nilai itu kembali kea
dan juga kep
(untuk waktu berikutnya).Untuk nilai pengembalian kami, kami menggunakan daftar, yang baik-baik saja karena format output default untuk daftar adalah menyatukan semuanya. Hasilnya selalu dimulai dengan
Y
. Selanjutnya, kita perlu tabel pencarian untuk operasi.Perhatikan bahwa panjang
add
(4),subtract
(9),divide by
(10),multiply by
(12), dansubtract from
(14) semuanya berbeda. Lebih jauh mengamati bahwa mereka masih berbeda ketika diambil mod 7. Dengan demikian, kita dapat menggunakannya untuk mengindeks ke dalam daftar tujuh elemen (berisi lima snipet kode dan dua penampung) untuk memetakan setiap perintah WordMath ke kode Pip yang sesuai (dirancang sedemikian sehingga jumlahnya dapat disatukan sampai akhir):-y+
(subtract from
)y-
(subtract
)y//
(divide by
)y+
(add
)y*
(multiply by
)Untuk indeks, kita menggunakan regex untuk mendapatkan indeks dari digit pertama dalam perintah:
a@?`\d`
. Kami juga menarik regexy
untuk digunakan di masa depan. Tabel pencarian dihasilkan dengan memisahkan string"-y+ y- y// y+ y* "
padas
(spasi).Kami masih harus menangani entri pertama, yang harus diterjemahkan ke dalam kode
Yq
. KarenaThink of a number
tidak mengandung digit apa pun,@?
operator mengembalikan nol. Menggunakan nil sebagai indeks ke dalam tabel pencarian juga mengembalikan nil. Nil itu palsu, jadi yang perlu kita lakukan hanyalah menambah|'q
penggunaanq
alih-alih operasi untuk kasus ini.Elemen terakhir dari daftar yang dikembalikan adalah nomor itu sendiri. Kami memperoleh ini melalui
a@y
(temukan semua kecocokan dalam perintah digit regex yang kami tarik sebelumnya). Ini mengembalikan daftar digit, tetapi sekali lagi, itu tidak masalah karena semua daftar akan digabungkan ketika output. Untuk entri pertama,a@y
tidak cocok dengan digit dan memberikan daftar kosong, yang tidak menambahkan apa pun ke output.Sebagai contoh
Dengan input
ekspresi peta memberikan daftar
yang, ketika digabungkan, output
sumber
Python 2 ,
154153146 byteMemperbaiki, dan bahkan menyimpan beberapa byte dalam proses. ^ __ ^
Cobalah online!
Berdasarkan strategi yang sama dengan jawaban Pip saya . Fitur khusus python:
Think of
dan penutup.
dihapus dari string sebelum pemisahan (input()[9:-1]
). Periode itu terlalu sial untuk ditangani dalam loop utama. Menghapus sembilan karakter pertama membantu karena alasan yang berbeda (lihat di bawah).import re
), kita gunakanrfind(" ")
untuk menemukan ruang terakhir dalam perintah. Kami juga dapat menggunakan ini untuk memeriksarepeat
kasus ini.a number
, di mana indeks ruangnya1
. Indeks ini dengan mudah mengisi lubang lain di tabel pencarian. Masalah lain dengan memproses tahap input dalam loop utama adalah+c[s:]
bagian, yang akan menghasilkanx=input() number
. Untuk mengatasi masalah itu, kami mengalikan denganc[0]<"a"
:1
untuk semua perintah biasa, yangc
dimulai dengan spasi, tetapi0
untuk yang awala number
.sumber
WinDbg,
449388 byte-61 byte dengan mendefinisikan alias untuk kode yang diulang
Terinspirasi oleh penggunaan LambdaBeta untuk
#define
. Pendekatan ini memodifikasi sintaksis WordMath sedikit (,
dan.
harus dibatasi ruang seperti kata-kata lain, dan,
tidak mengikutirepeat
), dan membuat alias sehingga sintaksis WordMath yang dimodifikasi adalah kode WinDbg yang valid. Baris terakhir melakukan apa yang ditanyakan dan diubah oleh pertanyaan dengan mengubah input menjadi sintaks yang dimodifikasi.Input diambil dengan mengatur string pada alamat memori dan mengatur pseudo-register
$t0
ke alamat itu. Catatan: ini akan menimpaint
at0x2000000
, jadi jika Anda memulai string Anda di sana, itu akan ditimpa sebagian.$t0
juga akan ditimpa.Karena itu membuat alias, tergantung pada apakah kode ini telah berjalan sebelum atau setelah pengaturan string, kode output akan berbeda (baik alias atau tidak). Sayangnya, saya tidak menemukan cara untuk membuat alias berkembang dengan baik tanpa dibatasi spasi (artinya skrip WordMath tidak bisa dieksekusi secara langsung tanpa ditransformasikan terlebih dahulu).
Bagaimana itu bekerja:
Contoh output, memasukkan string sebelum menjalankan kode ini satu kali (program yang dihasilkan menyerupai WordMath):
Contoh output, memasukkan string setelah setelah kode ini dijalankan sekali (alias diperluas ketika memasukkan string sehingga program yang dihasilkan tidak cantik):
Beberapa keluaran sampel lagi, hanya menggunakan sintaks WordMath yang sedikit dimodifikasi:
sumber
Scala, 338 byte
Cobalah sendiri di ideone
Penjelasan:
sumber