Toplu Golf için ipuçları


14

Windows Toplu (CMD), kod golfü için muhtemelen en uygun dildir.

Yeni satır karakterlerinden kaçının . Karakterlerin aksine bayt cinsinden en kısa kodu arıyorsanız, tüm gereksiz satırbaşı değerlerinden (yeni satır karakterleri = 2 bayt) kurtulmak isteyeceksiniz. &Her komut için bir bayt kırparak işlemi yapmak için işlemi kullanabilirsiniz .

echo Hello&echo World.

Değişkenleri ayarlama . Anahtarları kullanarak değişkenleri ayarlarken setayrıştırıcı boşlukları yok sayar.

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

Aynı ayrıştırıcı kurallarının tüm komutlar için geçerli olmadığını unutmayın - örnek olarak, döngüler için boşluk gerektirir. Arasında hariç set, string, or command(yani neyi parantez içerisinde yer almaktadır) ve kelime do.

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

Basit matematiksel ifadeler . Ayrıca, set /akomutta artırmak için kullandığım ifadeye dikkat edin . Basit matematiksel ifadeler için += -= *= /=(örneğin) yerine kullanın set /a a=%a%+1.

Komut çıktısını toplama . Bir komutun çıktısını almak için, bazen çıktıyı toplamak için bir for döngüsü kullanmış olabileceğiniz bir dosyaya çıktı almak ve dosyadan okumak yararlı olabilir:

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

echo teststdout'u f adlı bir dosyaya gönderin >f, yeni bir komut başlatın &ve dosyanın içeriğini bir değişkende alın set/pa=<f. Açıkçası bu her zaman yararlı değildir. Ancak, ihtiyacınız olan tek şey tek bir çıktı satırı olduğunda olabilir.

Komut çıkışı . Komut çıktısını bastırırken, 9'dan fazla komutu @bastırmanız gerekmedikçe komutlardan önce kullanın, bu durumda komut dosyanızın başında kullanın . 9 bayt uzunluğundadır ve bu nedenle genellikle daha uzun komut dosyalarıyla daha fazla bayt tasarrufu sağlar.@echo off@echo off

Komutlar genellikle açık olandan daha fazlasını yapar - komutlarınızın ne yaptığını düşünün. Örneğin; bir değişken ayarlamanız ve bunun yerine başka bir değişkeni yankılamanız gerekiyorsa:

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

Sizin /piçin çıktı almak üzere set komutunu anahtarla birlikte kullanabilirsiniz %a%.

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

Tamamen golf oynadı ...

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

Birkaç örnek - Tüm basamakların toplamını sayın - Goldbach'ın varsayımı .

Diğer ipuçları daha fazla takdir - başka bir şey düşünürseniz bu güncelleştirmeye devam edeceğiz.


16
Lütfen bunun cevap kısımlarını sorunun bir parçası olarak değil cevap olarak gönderiniz.
Charles

@Charles Bunu nasıl yaptığımdan eminim 'ipuçları sorusu' için kabul edilebilir bir biçim. Diğer insanlar kendi ipuçları ile cevaplar ekleyebilir.
unclemeat

Yanıtlar:


4

Sayaçlar

Sizden başlayarak sayaç işlevi görecek bir değişkeniniz olduğunda, 0yazmak isteyebilirsiniz

set count=0
set/acount+=1

; ancak, ilk satırları kaldırabilirsiniz, çünkü set/aayarlanmamış bir değişkenle birlikte kullanıldığında değerinin0

set/acounter+=1

Kod Blokları

Kod bloklarını kullanmanız gerektiğinde birkaç bayt tıraş edebileceğiniz çeşitli yollar vardır.

Bir kod bloğunu her açtığınızda, o bloktaki ilk kod satırından önce bir satır sonu eklemenize gerek yoktur. Kapanış parantezlerinin de kendi satırında olması gerekmez.

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

golf oynamak

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

Yeni Çizgi İzlemeden Yazdırma

Bunun ortak örüntüsü

echo|set/p=text

ancak, 2 bayt echodeğerinicd

cd|set/p=text

2
@ ankp-morpork Hey, biraz geç kaldım. Ancak bu ifbildirimin daha da golf yapılabileceğini bildirmek istiyorum . En iyisi olmalı:if %a%==%b% (echo true)else echo false
stevefestl

3

Ampersands

'S kodu daha kısa göstermesine rağmen, daha az satır kullandığından, yeni satır kadar çok karakter kullanır. Bunun anlamı şudur ki

echo a&echo b

kadar uzun

echo a
echo b

böylece kodunuz karakterleri boşa harcamadan okunabilir durumda kalabilir.

İstisnalar olabilir, çünkü bazı metin editörleri her yeni satır için satır besleme ve kartuş dönüşünü birleştirir.


Orijinal yazıya bunu ekledim çünkü kullandığım her metin düzenleyicide yeni satır iki bayt sayılıyor. Bu açıklamayı eklediğiniz için teşekkür ederiz.
unclemeat

2
Window'un carraige dönüş satır beslemesi iki karakterdir ve birçok metin düzenleyicisi bunu iki olarak sayacaktır, ancak golf sorularını ilk cevaplamaya başladığımda kalan yorumlardan biri PPCG satır sonlarında her zaman bir karakter olarak sayıldığını söyledi.
Jerry Jeremiah

2
Unix stili satır beslemeleri, en azından Windows'un son sürümlerinde CMD komut dosyalarında iyi çalışır.
user2428118

1
Aslında, CMD ayrıştırmadan önce CR karakterlerini bile kaldırır: stackoverflow.com/questions/4094699/…
schnaader

3

Sayısal bir hesaplamanın sonucunu doğrudan yazdırma

Zorluk, hesaplanması gereken bir sayı çıkarmanızı gerektiriyorsa cmd/c set/a, hesaplamayı kaydetmek ve sonra yankılamak yerine doğrudan hesaplamanın sonucunu çıktı almak için kullanabilirsiniz . Misal:

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

olur

@cmd/cset/a%1+%2

Düzenleme: Görünüşe göre hiçbir boşluk gerekli, 2 bayt daha tasarruf.


2

Gecikmeli Genişleme

Uzun kullanmak yerine, gecikmeli değişken genişletme etkinleştirilmiş yeni bir yorumlayıcı başlatacak (veya ) setLocal enableDelayedExpansionkullanabilirsiniz .cmd /v oncmd/von

Bunu henüz uygulayamadım, bu yüzden herhangi bir örneğim yok, ancak bunu /canahtarla birlikte kullanabilirsiniz . Misal:

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

Karatın "ve" işaretinden önce kullanıldığına dikkat edin. birden fazla ve işareti veya başka bir özel karakter kullanmanız gerekiyorsa, /canahtardan sonra her şeyi tırnak içine almaktan daha iyi olabilirsiniz :

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

Bu yöntem ayrıca tüm girdiyi @maskelemek için sadece bir karakter kullanmak zorunda olma avantajına sahiptir ve bu nedenle, (veya birden fazla sembol) için daha kısa bir alternatif olarak kullanılabilir ./von@echo off@

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

Bir satırda yapamayacağınız daha uzun komut dosyaları için, bazı baytları kaydetmek için aşağıdakileri yapabilirsiniz:

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

Veya ungolfed:

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

@echo off&setLocal enableDelayedExpansionYukarıdakilerle değiştirin .

İlk çalıştırdığınızda, komut dosyanız !!hiç genişlemez, bu nedenle "!!"bir komut olmadığı için bir hata alırsınız . Hata çıkışı daha sonra nul ( 2>nul) yöntemine bağlanır . Bu ilk 'komut' başarısız olduğunda ( ||), toplu iş dosyasının kendisini çağıran ( /v (on)gecikmeli genişletmeyi etkinleştirmek ve /qyankıyı kapatmak için kullanarak) yeni bir cmd örneği çağırır . Sonra !!denilen bir değişken olmadığı için hiçbir şey genişleyecek <NULL>. Daha sonra komut dosyanızın geri kalanı çalışır. Bundan sonra, cmd'nin orijinal örneğine dönecek ve pencereyi açık tutma koşulu &&ile ( ) çıkış /b(echo, ilk cmd örneği bağlamında, echo ile kodunuzda çalışmaya devam etmeyecektir) açık ve gecikmeli genişleme kapalı).


Bunun için, toplu iş dosyalarını çalıştırmak cmd /q /v on /c <filename>yalnızca 2 bayt olarak sayılmalıdır, çünkü Perl bayraklarına benzer iki "bayrak" dır, -pIbu sadece 2 ekstra bayt olarak sayılır.
Artyer

1

Tekrarlayan dizeler

Değişkeni ayarlamak için kullanılan bayt sayısının + değişkeni çıktılamak için bayt sayısının sadece kodu doğrudan çağıracak bayt sayısından az olduğu değişkenlerde yinelenen kod bloklarını ayarlayın.

Bir örnek için, bkz . 100'e kadar ekleyen kombinasyonları çizme

İçeren bir değişken ("s" gibi bir karakterle adlandırılır) oluşturursanız, set komutunun kullanımı başına 1 bayt kaydedersiniz set<space>. Bu, yalnızca set komutunu 12 kereden fazla kullanırsanız değer üretir. (Dizenin sonunda bir karakter olduğuna dikkat edin 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

Yukarıdaki 1 bayt daha kısadır ..

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

Bu muhtemelen oldukça zayıf bir örnektir - ama bu noktaya değiniyor.


1

Bir dizenin başlangıcı

Gösterim %var:~start,end%, değişkenin bir alt dizesini çıkarır var. Ancak start, 0o zaman tamamen atlayabilirsiniz. Zaten sen atlayabilirsiniz biliyoruz ,endsen yapar dize, geri kalanını istiyorsanız %var:~%için neredeyse işe yaramaz eşanlamlı %var%döndürür dışında ~zaman %var%boştur. (Belki bir testte kullanabilirsiniz:? if %var:~%==~)


Bunun için bazı alıntılar kaydedeceğimizi hatırlatan son cümlenizi beğendim :) +1.
stevefestl

1

kısaltılması IF EQUifadeleri

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

Kullanma ==yerine equ kaydeder 3 bayt.


IFİfadelerde alıntıların kısaltılması

Bu, geleneksel "daha güvenli" bir ifkarşılaştırmadır.

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

Bu ifadeyi kısaltmak için, giriş yalnızca alfasayısal / boş olabiliyorsa aşağıdakileri yapın :

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

Toplam 2 bayt tasarrufu .


Çıktı gerektiren zorluklar

Soru şöyle bir şey söylüyorsa:

En az 1 görünür karakter verir.

o zaman bunu yapabilirsin:

cd

cdGeçerli dizini gösterir STDOUT.


GOTObir etiket vermek

Aşağıda goto, bayt sırasına göre sıralanmış bir etiket yerleştirmenin bazı yöntemleri verilmiştir .

goto :l
goto l
goto:l

Yukarıdaki yöntem 1 bayt tasarrufu sağlar .


1
Alternatif Yapabileceğin goto:laynı 1 bayt kaydeder hangi ve bozulmamış kolon tutmak avantaj vardır
Matheus Avellar

@MatheusAvellar: İçeriği yorumunuza göre ekledim
stevefestl

1

Komut ve eğik çizgilerle parametreler arasında boşluk bırakma

Bilgisiz başlık için üzgünüm. Ne almaya çalışıyorum bazı (hepsi değil) Windows komutu için, bu parametre bir eğik çizgi ile başlayan sürece komut / program adı ve parametre arasındaki boşluk atlayabilirsiniz olduğunu. Örneğin:

for /f %%G in ...

olur

for/f %%G in ...

-1 Bayt!

ERRORLEVEL yerine boru çıkışı

Bir komutun doğru çalışıp çalışmadığını belirlemek için ERRORLEVEL kullanılması en kısa veya en zarif yöntem değildir. Bunun yerine, çıkışı borulayabilirsiniz. Bu şu şekilde çalışır ( &&operatörden sonraki herhangi bir komutun yalnızca komut hatasız çalıştırılmadan önce yürütüldüğünü unutmayın &&. ||Diğer yandan, operatörden sonraki herhangi bir komut yalnızca komut düzgün çalışmadığı takdirde çalıştırılacaktır. :

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

Bu, aşağıdakilerle değiştirilebilir:

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

-26 Bayt, vay! Bunun choice, ERRORLEVEL öğesinin bazı girdilere göre özel bir değere sahip olduğu gibi komutlarla çalışmadığını unutmayın .

Saygılarımızla,
Gabe


1

Parantezleri etkin kullanma

Tekrar merhaba,

İkinci bir cevap gönderdiğim için üzgünüm ama bunu hak ettiğini hissettim. İnsanların C:\Windows\System32>echo fooher komuttan önce o sinir bozucu satırı görüntülemeden komut çıkışını görüntülemek için genellikle aşağıdaki yöntemlerden birini kullandıklarını fark ettim .
İlk yöntem (kullanarak echo off):

@echo off
echo foo
echo bar
echo foobar
echo barfoo

İkinci yöntem:

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

Ancak, bu yöntemlerin hiçbiri aşağıdakiler kadar kısa değildir:

@(echo foo
echo bar
echo foobar
echo barfoo)

Oldukça kullanışlı, değil mi? Başka bir notta, bu, birden fazla çıktı satırını bir dosyaya veya cihaza kolayca bağlamak için kullanılabilir. Örneğin, bu uzun kod:

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

önemli ölçüde kısalır:

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

Bu oldukça uzun cevabı okuduğunuz için teşekkürler, umarım bu size yardımcı olur. Saygılarımızla,
Gabe


İpuçları sorularına birden fazla yanıt göndermek kötü değildir.
Outgolfer Erik
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.