Wskazówki do gry w golfa w partii

14

Windows Batch (CMD) jest prawdopodobnie najmniej odpowiednim językiem do gry w golfa.

Unikaj znaków nowej linii . Jeśli szukasz najkrótszego kodu w bajtach, w przeciwieństwie do znaków, będziesz chciał pozbyć się wszystkich niepotrzebnych zwrotów karetki (znaki nowego wiersza = 2 bajty). Możesz to zrobić za pomocą &operacji, skracając jeden bajt dla każdego polecenia.

echo Hello&echo World.

Ustawianie zmiennych . Podczas ustawiania zmiennych za pomocą przełączników setparser zignoruje spacje.

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

Zauważ, że te same reguły parsera nie dotyczą wszystkich poleceń - na przykład dla pętli wymagane są spacje. Z wyjątkiem między set, string, or command(tj. Co jest w nawiasach) a słowem do.

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

Proste wyrażenia matematyczne . Zwróć też uwagę na wyrażenie, którego użyłem do zwiększania set /apolecenia. Do prostych wyrażeń matematycznych użyj += -= *= /=zamiast (na przykład) set /a a=%a%+1.

Zbieranie danych wyjściowych polecenia . Aby uzyskać dane wyjściowe polecenia, czasami przydatne może być wyjście do pliku i odczytanie go z pliku, w innym przypadku można użyć pętli for do zebrania danych wyjściowych:

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

echo testwyślij stdout do pliku o nazwie f, >furuchom nowe polecenie &i uzyskaj zawartość pliku w zmiennej set/pa=<f. Oczywiście nie zawsze jest to przydatne. Ale może się zdarzyć, gdy potrzebujesz tylko jednego wiersza wyników.

Dane wyjściowe polecenia . Podczas tłumienia danych wyjściowych poleceń używaj @przed poleceniami, chyba że musisz pominąć więcej niż 9 poleceń, w takim przypadku użyj @echo offna początku skryptu. @echo offma długość 9 bajtów i dlatego na ogół zaoszczędzi więcej bajtów dzięki dłuższym skryptom.

Polecenia często robią coś więcej niż to, co oczywiste - pomyśl o tym, co robią twoje polecenia. Na przykład; jeśli musisz ustawić zmienną i wywołać echo innej zmiennej, zamiast:

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

Możesz użyć polecenia set z /pprzełącznikiem, aby uzyskać dane wyjściowe %a%.

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

Całkowicie golfowy ...

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

Kilka przykładów - Policz sumę wszystkich cyfr - hipoteza Goldbacha .

Wszelkie inne wskazówki są mile widziane - będę je aktualizować, jeśli pomyślę o czymś innym.

nieszczęście
źródło
16
Proszę zamieścić części odpowiedzi jako odpowiedź, a nie jako część pytania.
Nie, że Charles
@Charles Jestem całkiem pewien, jak to zrobiłem, jest akceptowalnym formatem dla „pytania z poradami”. Inne osoby mogą dodawać odpowiedzi z własnymi wskazówkami.
niepomyślnie

Odpowiedzi:

4

Liczniki

Ilekroć masz zmienną, która będzie działać jako licznik zaczynając od, 0możesz chcieć zapisać

set count=0
set/acount+=1

; można jednak wyeliminować pierwsze wiersze, ponieważ za każdym razem, gdy set/aużywana jest z nieuzbrojoną zmienną, przyjmuje się, że jest to wartość0

set/acounter+=1

Bloki kodu

Istnieje kilka sposobów na zmniejszenie liczby bajtów, gdy trzeba użyć bloków kodu.

Za każdym razem, gdy otwierasz blok kodu, nie musisz wstawiać podziału linii przed pierwszą linią kodu w tym bloku. Nawiasy zamykające również nie muszą znajdować się w osobnej linii.

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

można grać w golfa

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

Drukowanie bez końca nowej linii

Częstym tego przykładem jest

echo|set/p=text

ale możesz zapisać 2 bajty zmieniając echonacd

cd|set/p=text
ankh-morpork
źródło
2
@ ankp-morpork Hej, jestem trochę spóźniony. Ale chcę cię poinformować, że ifoświadczenie można pograć jeszcze bardziej. Najlepszym powinno być:if %a%==%b% (echo true)else echo false
stevefestl
3

Ampersands

Chociaż & sprawia, że ​​kod wydaje się krótszy, ponieważ używa mniej linii, używa tyle samo znaków, co nowa linia. To znaczy że

echo a&echo b

jest tak długo jak

echo a
echo b

dzięki czemu kod może pozostać czytelny bez marnowania znaków.

Mogą istnieć wyjątki, ponieważ niektóre edytory tekstu łączą przesunięcie wiersza i zwrot karetki dla każdej nowej linii.

kitcar2000
źródło
Zawarłem to w oryginalnym poście, ponieważ nowa linia liczy dwa bajty w każdym edytorze tekstu, którego używam. Dziękujemy za dodanie tego wyjaśnienia.
rozwiązany
2
Linia powrotu Carraige Window składa się z dwóch znaków i wielu edytorów tekstu liczy ją jako dwa, ale kiedy zacząłem odpowiadać na pytania dotyczące golfa, jeden z pozostałych komentarzy powiedział, że w PPCG zakończenia linii są zawsze liczone jako jeden znak.
Jerry Jeremiah
2
Podawanie wierszy w stylu uniksowym będzie działać dobrze w skryptach CMD, przynajmniej w najnowszych wersjach systemu Windows.
user2428118,
1
W rzeczywistości CMD usuwa nawet znaki CR przed analizą: stackoverflow.com/questions/4094699/…
schnaader
3

Wydrukuj bezpośrednio wynik obliczeń numerycznych

Jeśli wyzwanie wymaga podania liczby, która musi zostać obliczona, można użyć cmd/c set/ado wydrukowania wyniku obliczeń bezpośrednio zamiast zapisywania obliczeń, a następnie ich powtórzenia. Przykład:

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

staje się

@cmd/cset/a%1+%2

Edycja: Najwyraźniej nie są potrzebne żadne spacje, oszczędzając 2 kolejne bajty.

Neil
źródło
2

Opóźniona ekspansja

Zamiast długiego setLocal enableDelayedExpansionmożna użyć cmd /v on(lub cmd/von), który uruchomi nowego interpretera z włączonym opóźnionym rozszerzaniem zmiennych.

Muszę to jeszcze zaimplementować, więc nie mam żadnych przykładów, ale możesz użyć tego w połączeniu z /cprzełącznikiem. Przykład:

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

Zwróć uwagę na użycie karatu przed znakiem ampersand. jeśli potrzebujesz użyć wielu znaków ampersands lub innych znaków specjalnych, lepiej umieścić wszystko po /cprzełączeniu w cudzysłowie:

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

Ta metoda ma również tę zaletę, że musi używać tylko jednego @znaku do maskowania wszystkich danych wejściowych, a zatem może być stosowana bez /vonkrótszej alternatywy dla @echo off(lub wielu @symboli).

9 znaków: @echo off
6 znaków:@cmd/c

W przypadku dłuższych skryptów, których nie można wykonać w jednym wierszu, można wykonać następujące czynności, aby zapisać niektóre bajty:

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

Lub bez golfa:

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

Zastąp @echo off&setLocal enableDelayedExpansionpowyższym.

Po pierwszym uruchomieniu skrypt w !!ogóle się nie rozwija, więc "!!"pojawia się błąd, ponieważ nie jest poleceniem. Wyjście błędu jest następnie przesyłane do nul ( 2>nul). Kiedy to pierwsze „polecenie” nie powiedzie się ( ||), wywołuje nową instancję cmd, która wywołuje sam plik wsadowy (za pomocą, /v (on)aby umożliwić opóźnione rozwijanie i/q wyłączyć echo). Następnie !!rozwinie się do zera, ponieważ nie wywołuje żadnej zmiennej <NULL>. Reszta skryptu jest następnie uruchamiana. Po czym powróci do oryginalnej instancji cmd i ( &&) zakończy /bwarunek, aby okno pozostało otwarte (wyjście jest tak, że nie będzie kontynuowało uruchamiania skryptu w kontekście pierwszej instancji cmd z echo włączone i opóźnione rozszerzenie wyłączone).

nieszczęście
źródło
W tym celu uruchamianie plików wsadowych z cmd /q /v on /c <filename>powinno liczyć się tylko jako 2 bajty, ponieważ są to dwie „flagi” podobne do flag Perla, -pIktóre mogłyby się liczyć tylko jako 2 dodatkowe bajty.
Artyer
1

Powtarzające się ciągi

Ustaw powtarzalne bloki kodu w zmiennych, gdzie liczba bajtów użytych do ustawienia zmiennej + liczba bajtów, które należy wyprowadzić, jest mniejsza niż liczba bajtów, aby bezpośrednio wywołać kod.

Na przykład zobacz: Rysuj kombinacje, które sumują się do 100

Zapisujesz 1 bajt na użycie polecenia set, jeśli utworzysz zmienną (nazwaną jednym znakiem, np. „S”), która zawiera set<space>. Generuje to wartość tylko wtedy, gdy użyjesz polecenia set więcej niż 12 razy. (Uwaga: na końcu łańcucha znajduje się znak 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

Powyżej jest o 1 bajt krótszy niż ..

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

Jest to prawdopodobnie dość słaby przykład - ale ma sens.

nieszczęście
źródło
1

Początek ciągu

Notacja %var:~start,end%wyodrębnia podciąg zmiennej var. Jeśli starttak, 0to możesz to całkowicie pominąć. Wiemy już, że możesz pominąć, ,endjeśli chcesz resztę ciągu, co tworzy %var:~%prawie bezużyteczny synonim %var%, z wyjątkiem tego, że zwraca, ~gdy %var%jest pusty. (Być może mógłbyś użyć go w teście if %var:~%==~:?)

Neil
źródło
Podoba mi się twoje ostatnie zdanie przypominające nam, że oszczędzisz kilka cytatów :) +1 za to.
stevefestl
1

IF EQUOświadczenia skracające

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

Użycie ==zamiast equ oszczędza 3 bajty.


Skracanie cytatów w IF wyciągach

Jest to tradycyjne tak zwane „bezpieczniejsze” porównanie if.

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

Aby skrócić tę instrukcję, wykonaj następujące czynności, gdy dane wejściowe mogą być tylko alfanumeryczne / puste :

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

Zapisywanie w sumie 2 bajtów.


Wyzwania wymagające wydajności

Jeśli pytanie brzmi:

Wysyła co najmniej 1 widoczny znak.

możesz po prostu to zrobić:

cd

cdPokazuje bieżący katalog STDOUT.


GOTOwprowadzenie etykiety

Oto kilka metod gotowprowadzania etykiety uporządkowanych w kolejności malejącej bajtów.

goto :l
goto l
goto:l

Powyższa metoda pozwala zaoszczędzić 1 bajt.

stevefestl
źródło
1
Alternatywnie możesz zrobić, goto:lco oszczędza ten sam 1 bajt i ma dodatkową
zaletę
@MatheusAvellar: Dodałem treść zgodnie z Twoim komentarzem
stevefestl
1

Pominięcie spacji między poleceniem a parametrami z ukośnikami

Przepraszam za nieinformacyjny tytuł. Próbuję uzyskać, że w przypadku niektórych (nie wszystkich) poleceń systemu Windows można pominąć spację między nazwą polecenia / programu a parametrem, o ile parametr ten zaczyna się od ukośnika. Na przykład:

for /f %%G in ...

staje się

for/f %%G in ...

-1 bajt!

Przesyłanie danych wyjściowych zamiast używania ERRORLEVEL

Użycie ERRORLEVEL do ustalenia, czy polecenie zostało poprawnie uruchomione, nie jest najkrótszą ani najbardziej elegancką metodą. Zamiast tego możesz przesyłać dane wyjściowe. Działa to w następujący sposób (pamiętaj, że każde polecenie po &&operatorze jest wykonywane tylko wtedy, gdy polecenie poprzedzone &&uruchomiono bez błędów. ||Z drugiej strony każde polecenie po operatorze będzie działać tylko wtedy, gdy polecenie przed nim NIE zadziałało poprawnie. Mój przykład to :

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

Można to zastąpić:

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

-26 Bajtów, wow! Zauważ, że to nie działa z takimi poleceniamichoice , gdzie ERRORLEVEL ma specjalną wartość zgodnie z niektórymi danymi wejściowymi.

Pozdrawiam,
Gabe

Gabriel Mills
źródło
1

Skuteczne stosowanie nawiasów

Witaj ponownie,

Przepraszam, że opublikowałem drugą odpowiedź, ale czułem, że ta zasługuje na to. Zauważyłem, że ludzie często używają jednej z następujących metod, aby wyświetlić dane wyjściowe polecenia bez wyświetlania tej irytującej C:\Windows\System32>echo foolinii przed każdym poleceniem.
Pierwsza metoda (przy użyciu echo off):

@echo off
echo foo
echo bar
echo foobar
echo barfoo

Druga metoda:

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

Jednak żadna z tych metod nie jest tak krótka jak:

@(echo foo
echo bar
echo foobar
echo barfoo)

Bardzo przydatna, prawda? Z drugiej strony można tego użyć do łatwego połączenia wielu linii danych wyjściowych z plikiem lub urządzeniem. Na przykład ten długi kod:

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

staje się znacznie krótszy:

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

Dziękuję za przeczytanie tej dość długiej odpowiedzi i mam nadzieję, że ci to pomoże. Pozdrawiam,
Gabe

Gabriel Mills
źródło
Publikowanie wielu odpowiedzi na pytania ze wskazówkami nie jest złe.
Erik the Outgolfer