Kiat Golf di Batch

14

Windows Batch (CMD) mungkin merupakan bahasa yang paling tidak cocok untuk kode golf.

Hindari karakter baris baru . Jika Anda mencari kode terpendek dalam byte, dan bukan karakter, Anda ingin menyingkirkan semua pengembalian carriage yang tidak perlu (karakter baris baru = 2 byte). Anda dapat menggunakan &operasi untuk melakukan ini, memangkas satu byte untuk setiap perintah.

echo Hello&echo World.

Pengaturan variabel . Saat mengatur variabel menggunakan sakelar, setparser akan mengabaikan spasi.

set /a a+=1
set /p b="User Input: "
:: Will be handled the same as..
set/aa+=1
set/pb="User Input: "

Perhatikan bahwa aturan parser yang sama tidak berlaku untuk semua perintah - sebagai contoh, untuk loop membutuhkan spasi. Kecuali antara set, string, or command(yaitu apa yang ada di dalam kurung) dan kata do.

for /f %%a in (file.txt)do ...

Ekspresi matematika sederhana . Juga, perhatikan ekspresi yang saya gunakan untuk penambahan dalam set /aperintah. Untuk ekspresi matematika yang sederhana, gunakan += -= *= /=alih-alih (misalnya) set /a a=%a%+1.

Mengumpulkan output perintah . Untuk mendapatkan output dari suatu perintah, kadang-kadang berguna untuk menampilkan dan membaca dari sebuah file, di mana Anda mungkin menggunakan loop for untuk mengumpulkan output:

for /f %%a in ('echo test') do set a=%%a
:: Can be shortened to
echo test>f&set/pa=<f

echo testkirim stdout ke file bernama f,, >fmulai perintah baru &dan dapatkan isi file dalam variabel set/pa=<f. Jelas ini tidak selalu berguna. Tetapi bisa jadi ketika yang Anda butuhkan adalah satu baris output.

Output perintah . Saat menekan output perintah, gunakan @sebelum perintah, kecuali jika Anda perlu menekan lebih dari 9 perintah, dalam hal ini, gunakan @echo offdi awal skrip Anda. @echo offpanjangnya 9 byte, dan karena itu umumnya akan menghemat lebih banyak byte dengan skrip yang lebih panjang.

Perintah sering melakukan lebih dari sekadar apa yang sudah jelas - pikirkan tentang apa yang dilakukan perintah Anda. Sebagai contoh; jika Anda perlu mengatur variabel dan menggemakan variabel lain, alih-alih:

set a=OUTPUT
echo %a%
echo test>f
set /p b=<f

Anda dapat menggunakan perintah set dengan /pberalih ke output %a%untuk Anda.

set a=OUTPUT
echo test>f
set /p b=%a%<f

Benar-benar bermain golf ...

set a=OUTPUT&echo test>f&set/pb=%a%<f

Beberapa contoh - Hitung jumlah semua digit - dugaan Goldbach .

Kiat lain lebih dihargai - saya akan terus memperbarui ini jika saya memikirkan hal lain.

hapus clemeat
sumber
16
Silakan posting bagian jawaban ini sebagai jawaban, bukan sebagai bagian dari pertanyaan.
Bukan karena Charles
@ Charles Saya cukup yakin bagaimana saya melakukan ini adalah format yang dapat diterima untuk 'pertanyaan tip'. Orang lain dapat menambahkan jawaban dengan tip mereka sendiri.
hapus tanda

Jawaban:

4

Penghitung

Setiap kali Anda memiliki variabel yang akan bertindak sebagai penghitung mulai dari 0Anda mungkin ingin menulis

set count=0
set/acount+=1

; Namun, Anda dapat menghilangkan baris pertama karena setiap kali set/adigunakan dengan variabel yang tidak diset, nilainya diasumsikan0

set/acounter+=1

Blok Kode

Ada beberapa cara Anda dapat mencukur beberapa byte saat Anda harus menggunakan blok kode.

Setiap kali Anda membuka blok kode, Anda tidak perlu memasukkan jeda baris sebelum baris pertama kode di blok itu. Tanda kurung tutup tidak harus pada barisnya sendiri.

If %a%==%b% (
     echo true
) else (
    echo false
)

bisa bermain golf

If %a%==%b% (echo true)else (echo false)

Mencetak Tanpa Mengikuti Garis Baru

Pola umum untuk ini adalah

echo|set/p=text

tetapi, Anda dapat menyimpan 2 byte yang diubah echomenjadicd

cd|set/p=text
ankh-morpork
sumber
2
@ ankp-morpork Hei, aku agak terlambat. Tetapi saya ingin memberi tahu Anda bahwa ifpernyataan itu dapat di-golf lebih lanjut. Yang terbaik adalah:if %a%==%b% (echo true)else echo false
stevefestl
3

Ampersands

Meskipun & membuat kode tampak lebih pendek, karena menggunakan lebih sedikit garis, namun menggunakan karakter sebanyak baris baru. Ini artinya

echo a&echo b

selama

echo a
echo b

sehingga kode Anda dapat tetap dibaca tanpa membuang-buang karakter.

Mungkin ada pengecualian karena beberapa editor teks menggabungkan umpan baris dan pengembalian karbohidrat untuk setiap baris baru.

kitcar2000
sumber
Saya memasukkan ini dalam posting asli karena baris baru dihitung untuk dua byte di setiap editor teks yang saya gunakan. Terima kasih telah menambahkan klarifikasi ini.
buka tutup
2
Linefeed carraige return Window adalah dua karakter dan banyak editor teks akan menghitungnya sebagai dua, tetapi ketika saya mulai menjawab pertanyaan golf, salah satu komentar yang tersisa mengatakan bahwa di akhir baris PPCG selalu dihitung sebagai satu karakter.
Jerry Jeremiah
2
Umpan baris gaya Unix akan bekerja dengan baik di skrip CMD, setidaknya di versi Windows terbaru.
user2428118
1
Bahkan, CMD bahkan menghapus karakter CR sebelum parsing: stackoverflow.com/questions/4094699/…
schnaader
3

Langsung mencetak hasil perhitungan numerik

Jika tantangan mengharuskan Anda untuk mengeluarkan angka yang perlu dihitung, Anda dapat menggunakan cmd/c set/auntuk menampilkan hasil perhitungan secara langsung alih-alih menyimpan perhitungan dan kemudian menggemakannya. Contoh:

@set/a a=%1+%2
@echo %a%

menjadi

@cmd/cset/a%1+%2

Sunting: Rupanya tidak ada spasi sama sekali, menghemat 2 byte lebih banyak.

Neil
sumber
2

Ekspansi Tertunda

Alih-alih menggunakan panjang setLocal enableDelayedExpansionAnda dapat menggunakan cmd /v on(atau cmd/von) yang akan memulai juru bahasa baru dengan ekspansi variabel tertunda diaktifkan.

Saya belum menerapkan ini jadi saya tidak punya contoh, tetapi Anda bisa menggunakan ini bersama dengan /csaklar. Contoh:

@cmd/von/cset test=test^&echo !test!

Perhatikan penggunaan karat sebelum ampersand. jika Anda perlu menggunakan beberapa ampersand atau karakter khusus lainnya, Anda mungkin lebih baik melampirkan semuanya setelah /csakelar dalam tanda kutip:

@cmd/von/c"set test=test&set test1=test1&echo !test! !test1!"

Metode ini juga memiliki keuntungan hanya dengan menggunakan satu @karakter untuk menutupi semua input, dan karenanya dapat digunakan, tanpa /von, sebagai alternatif yang lebih pendek dari @echo off(atau beberapa @simbol).

9 karakter: @echo off
6 karakter:@cmd/c

Untuk skrip yang lebih panjang, yang tidak dapat Anda lakukan dalam satu baris, Anda dapat melakukan hal berikut untuk menyimpan beberapa byte:

@!! 2>nul||cmd/q/v/c%0&&exit/b

Atau, ungolfed:

@!! 2>nul || cmd /q /v on /c %0 && exit/b

Ganti @echo off&setLocal enableDelayedExpansiondengan yang di atas.

Ketika Anda pertama kali menjalankan skrip Anda !!tidak akan berkembang sama sekali, jadi Anda menerima kesalahan karena "!!"bukan perintah. Output kesalahan kemudian disalurkan ke nul ( 2>nul). Ketika 'perintah' pertama ini gagal ( ||), ia memanggil instance baru cmd, yang memanggil file batch itu sendiri (digunakan /v (on)untuk mengaktifkan ekspansi yang tertunda, dan /quntuk mematikan gema). Kemudian !!akan berkembang menjadi nol, karena tidak ada variabel yang dipanggil <NULL>. Sisa skrip Anda kemudian dijalankan. Setelah itu ia akan kembali ke instance asli dari cmd, dan ( &&) keluar dengan /bsyarat untuk menjaga jendela tetap terbuka (keluar adalah agar ia tidak terus berjalan melalui skrip Anda dalam konteks contoh cmd pertama, dengan gema aktif dan menunda ekspansi).

hapus clemeat
sumber
Untuk ini, menjalankan file batch dengan cmd /q /v on /c <filename>seharusnya hanya dihitung sebagai 2 byte karena mereka adalah dua "flag" yang mirip dengan flag Perl seperti -pIyang hanya akan dihitung sebagai 2 byte tambahan.
Artyer
1

String berulang

Atur blok kode berulang dalam variabel, di mana jumlah byte yang digunakan untuk mengatur variabel + jumlah byte untuk menghasilkan variabel kurang dari jumlah byte untuk hanya memanggil kode secara langsung.

Sebagai contoh, lihat: Gambar kombinasi yang menambahkan hingga 100

Anda menyimpan 1 byte per penggunaan perintah set, jika Anda membuat variabel (dinamai dengan satu karakter, seperti "s") yang berisi set<space>. Ini hanya menghasilkan nilai jika Anda menggunakan perintah set lebih dari 12 kali. (Perhatikan ada karakter di akhir string set s=set).

set s=set 
%s%a=1
%s%b=2
%s%c=3
%s%d=4
%s%e=5
%s%f=6
%s%g=7
%s%h=8
%s%i=9
%s%j=10
%s%k=11
%s%l=12
%s%m=13

Di atas adalah 1 byte lebih pendek dari ..

set a=1
set b=2
set c=3
set d=4
set e=5
set f=6
set g=7
set h=8
set i=9
set j=10
set k=11
set l=12
set m=13

Ini mungkin contoh yang sangat buruk - tetapi ini benar.

hapus clemeat
sumber
1

Mulai dari sebuah string

Notasi %var:~start,end%mengekstraksi substring dari variabel var. Namun jika startini 0maka Anda dapat menghilangkan itu sepenuhnya. Kami sudah tahu bahwa Anda dapat menghilangkan ,endjika Anda ingin sisa string, yang membuat %var:~%sinonim yang hampir tidak berguna untuk %var%, kecuali bahwa ia mengembalikan ~ketika %var%kosong. (Mungkin Anda bisa menggunakannya dalam ujian if %var:~%==~:?)

Neil
sumber
Saya suka kalimat terakhir Anda mengingatkan kami bahwa ini akan menghemat beberapa kutipan :) +1 untuk itu.
stevefestl
1

IF EQUPernyataan pemendekan

if %a% equ %b% do_something
if %a%==%b% do_something

Menggunakan ==bukannya equ menghemat 3 byte.


Memperpendek kutipan dalam IFpernyataan

Ini adalah perbandingan tradisional yang disebut "lebih aman" if.

if "%a%"=="%b%" do_something

Untuk mempersingkat pernyataan ini, lakukan hal berikut saat input hanya bisa alfanumerik / kosong :

if %a%.==%b%. do_something

Menyimpan total 2 byte.


Tantangan yang membutuhkan keluaran

Jika pertanyaan mengatakan sesuatu seperti:

Menghasilkan setidaknya 1 karakter yang terlihat.

maka Anda bisa melakukan ini:

cd

The cdmenunjukkan direktori ke STDOUT.


GOTOsebuah label

Berikut adalah beberapa metode gotountuk membuat label, dipesan dalam urutan byte.

goto :l
goto l
goto:l

Metode di atas menghemat 1 byte.

stevefestl
sumber
1
Atau Anda bisa melakukan goto:lyang menghemat 1 byte yang sama dan memiliki bonus tambahan untuk menjaga usus Anda tetap utuh
Matheus Avellar
@MatheusAvellar: Saya telah menambahkan konten yang sesuai dengan komentar Anda
stevefestl
1

Menghilangkan ruang antara perintah dan parameter dengan garis miring

Maaf tentang judul yang tidak informatif. Apa yang saya coba maksudkan adalah bahwa untuk beberapa (tidak semua) perintah Windows, Anda dapat menghilangkan spasi di antara perintah / nama program dan parameter, selama parameter itu dimulai dengan garis miring. Sebagai contoh:

for /f %%G in ...

menjadi

for/f %%G in ...

-1 Byte!

Output perpipaan alih-alih menggunakan ERRORLEVEL

Menggunakan ERRORLEVEL untuk menentukan apakah perintah berjalan dengan benar bukan metode terpendek atau paling elegan. Sebagai gantinya, Anda dapat mem-pipe output. Ini berfungsi sebagai berikut (ingat bahwa perintah apa pun setelah &&operator hanya dijalankan jika perintah sebelum &&dijalankan tanpa kesalahan. Perintah apa pun setelah ||operator, di sisi lain, akan berjalan hanya jika perintah sebelum TIDAK dijalankan dengan benar. Contoh saya adalah :

net session>nul
if %errorlevel%==0 (echo 1) else (echo 0)

Ini bisa diganti dengan:

net session>nul&&echo 1||echo 0

-26 Bytes, wow! Perhatikan bahwa ini tidak bekerja dengan perintah seperti choice, di mana ERRORLEVEL memiliki nilai khusus sesuai dengan beberapa input.

Salam,
Gabe

Gabriel Mills
sumber
1

Menggunakan tanda kurung secara efektif

Halo lagi,

Maaf untuk mengirim jawaban kedua tetapi saya merasa ini pantas untuk itu. Saya perhatikan bahwa orang sering menggunakan salah satu metode berikut untuk menampilkan output perintah tanpa menampilkan C:\Windows\System32>echo foobaris sial sebelum setiap perintah.
Metode pertama (menggunakan echo off):

@echo off
echo foo
echo bar
echo foobar
echo barfoo

Metode kedua:

@echo foo
@echo bar
@echo foobar
@echo barfoo

Namun, tak satu pun dari metode ini sesingkat berikut:

@(echo foo
echo bar
echo foobar
echo barfoo)

Cukup praktis, bukan? Pada catatan lain, ini dapat digunakan untuk menyalurkan banyak jalur output ke file atau perangkat dengan mudah. Misalnya, kode yang panjang ini:

echo foo>file.txt
echo bar>file.txt
echo foobar>file.txt
echo barfoo>file.txt

menjadi jauh lebih singkat:

(echo foo
echo bar
echo foobar
echo barfoo)>file.txt

Terima kasih telah membaca jawaban yang agak panjang ini, dan saya harap ini membantu Anda. Salam,
Gabe

Gabriel Mills
sumber
Mengeposkan banyak jawaban ke kiat pertanyaan tidak buruk.
Erik the Outgolfer