Поради щодо гольфу в Партії


14

Windows Batch (CMD), мабуть, найменш підходяща мова для кодового гольфу.

Уникайте символів нового рядка . Якщо ви шукаєте найкоротший код у байтах, на відміну від символів, вам захочеться позбутися від усіх непотрібних повернень каретки (символи нового рядка = 2 байти). Ви можете використовувати &операцію для цього, обрізаючи один байт для кожної команди.

echo Hello&echo World.

Встановлення змінних . Під час встановлення змінних за допомогою перемикачів setаналізатор проігнорує пробіли.

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

Зауважте, що однакові правила аналізатора не застосовуються до всіх команд - як приклад, для циклів потрібні пробіли. За винятком між set, string, or command(тобто тим, що знаходиться у дужках) та словом do.

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

Прості математичні вирази . Також помітьте вираз, який я використовував для збільшення в set /aкоманді. Для простих математичних виразів використовуйте += -= *= /=замість (наприклад)set /a a=%a%+1 .

Збір командного виводу . Щоб отримати вихід команди, іноді може бути корисно вивести і прочитати з файлу, де ви інакше могли б використовувати цикл для збору результатів:

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

echo test відправити stdout у файл, який називається f, >f запустіть нову команду &та отримайте вміст файлу у змінній set/pa=<f. Очевидно, це не завжди корисно. Але це може бути тоді, коли все, що вам потрібно, - це один рядок виводу.

Командний вихід . Під час придушення виводу команд використовуйте @перед командами, якщо не потрібно придушувати більше 9 команд, у такому випадку використовуйте @echo offна початку вашого сценарію. @echo offдорівнює 9 байтам, і тому, як правило, зберігається більше байтів при триваліших сценаріях.

Команди часто роблять більше, ніж просто те, що очевидно - подумайте, що роблять ваші команди. Наприклад; якщо вам потрібно встановити змінну та повторити іншу змінну, а не:

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

Ви можете використовувати команду set з /pперемикачем на вихід%a% для вас.

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

Цілком гольф ...

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

Пара прикладів - підрахуйте суму всіх цифр - здогадка Гольдбаха .

Будь-які інші поради більш ніж оцінені - я продовжуватиму оновлювати це, якщо придумати щось інше.


16
Будь ласка, опублікуйте частину відповіді як відповідь, а не як частину запитання.
Не те, що Чарльз

@Charles Я досить впевнений, як я це зробив, це прийнятний формат для "підказки питання". Інші люди можуть додавати відповіді з власними порадами.
нечисте

Відповіді:


4

Лічильники

Кожен раз, коли у вас є змінна, яка буде діяти як лічильник, починаючи з цього 0, можливо, ви захочете написати

set count=0
set/acount+=1

; однак, ви можете усунути перші рядки, оскільки щоразу, коли set/aвикористовується з невстановленою змінною, її значення вважається рівним0

set/acounter+=1

Кодові блоки

Існує декілька способів відголити кілька байтів, коли доведеться використовувати блоки коду.

Щоразу, коли ви відкриваєте блок коду, вам не потрібно вставляти розрив рядка перед першим рядком коду в цьому блоці. Дужки, що закриваються, також не повинні знаходитись у власній лінії.

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

можна в гольф

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

Друк без закінчення нового рядка

Загальна модель для цього є

echo|set/p=text

але ви можете зберегти 2 байти, змінивши echoнаcd

cd|set/p=text

2
@ ankp-morpork Гей, я трохи запізнююся. Але я хочу повідомити вам, що ця ifзаява може бути додатково гольф. Найкращим має бути:if %a%==%b% (echo true)else echo false
stevefestl

3

Амперсанди

Хоча код і здається коротшим, оскільки він використовує менше рядків, він використовує стільки ж символів, скільки нового рядка. Це означає що

echo a&echo b

поки що

echo a
echo b

тож ваш код може залишатися читабельним, не витрачаючи символів.

Можуть бути винятки, оскільки деякі текстові редактори поєднують подачу рядків та повернення картриджа для кожного нового рядка.


Я включив це в оригінальний пост, тому що новий рядок нараховує два байти у кожному текстовому редакторі, який я використовую. Дякуємо, що додали це пояснення.
нечисте м'ясо

2
Carraige, що повертається, повертається до двох символів, і багато редакторів тексту вважають це двома, але коли я вперше почав відповідати на питання про гольф, один із залишених коментарів сказав, що закінчення рядків PPCG завжди зараховуються як один символ.
Джеррі Єремія

2
Лінійки стрічок у стилі Unix будуть добре працювати в сценаріях CMD, принаймні, в останніх версіях Windows.
користувач2428118

1
Насправді, навіть CMD видаляє символи CR перед розбором: stackoverflow.com/questions/4094699 / ...
schnaader

3

Безпосередньо надрукуйте результат числового обчислення

Якщо виклик вимагає, щоб ви вивели число, яке потрібно обчислити, ви можете використовувати cmd/c set/aдля виведення результату обчислення безпосередньо, а не зберігати обчислення, а потім повторювати його. Приклад:

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

стає

@cmd/cset/a%1+%2

Редагувати: Мабуть, пробіли взагалі не потрібні, заощаджуючи ще 2 байти.


2

Затримка розширення

Замість використання тривалих setLocal enableDelayedExpansionви можете використовувати cmd /v on(абоcmd/von ), який запустить новий інтерпретатор із увімкненим розширеним змінним розширенням.

Я ще не втілю це, тому я не маю прикладів, але ви можете використовувати це спільно з /cкомутатором. Приклад:

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

Зверніть увагу на використання карата перед амперсандом. якщо вам потрібно використовувати кілька амперсандів або будь-які інші спеціальні символи, можливо, вам буде краще вкласти все після /cперемикача в лапки:

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

Цей метод також має перевагу лише в тому, що потрібно використовувати один @символ для маскування всіх вхідних даних, і тому він може бути використаний без використання /vonв якості коротшої альтернативи @echo off(або декількох @символів).

9 символів: @echo off
6 символів:@cmd/c

Для більш тривалих сценаріїв, які неможливо зробити в одному рядку, ви можете зробити наступне, щоб зберегти кілька байт:

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

Або, неозорих:

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

Замініть @echo off&setLocal enableDelayedExpansionвище.

Під час першого запуску сценарій !!взагалі не розшириться, тому ви отримаєте помилку, оскільки "!!"це не команда. Потім вихід помилки передається на nul ( 2>nul). Коли ця перша команда не працює ( ||), вона викликає новий екземпляр cmd, який викликає сам пакетний файл (використовуючи /v (on)для включення затримки розширення та /qвимкнення луни). Тоді !!розшириться ні до чого, оскільки змінної не називається <NULL>. Решта вашого сценарію потім запускається. Після цього він повернеться до початкового екземпляра cmd та ( &&) виходу із /bумовою, щоб тримати вікно відкритим (вихід такий, щоб він не продовжував працювати через ваш сценарій у контексті першого екземпляра cmd, з відлунням увімкнено та відстрочено розширення).


Для цього запущені пакетні файли cmd /q /v on /c <filename>повинні враховувати лише 2 байти, оскільки вони є двома "прапорами", схожими на прапори Perl, подібні до цього, -pIякий би вважався лише 2 додатковими байтами.
Художник

1

Струни, що повторюються

Встановіть повторювані блоки коду у змінних, де кількість байтів, які використовуються для встановлення змінної + кількість байтів для виведення змінної, менша за кількість байтів, щоб просто викликати код безпосередньо.

Наприклад, див.: Намалюйте комбінації, що містять до 100

Ви зберігаєте 1 байт на використання команди set, якщо ви створюєте змінну (названу одним символом, наприклад "s"), яка містить set<space> . Це створює значення лише в тому випадку, якщо ви використовуєте команду set більше 12 разів. (Зауважте, що в кінці рядка є символ 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

Наведене вище на 1 байт коротше, ніж ..

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

Це, мабуть, досить поганий приклад - але це вдається зрозуміти.


1

Початок рядка

Позначення %var:~start,end%витягує підрядку змінної var. Однак якщо startє, 0то можете повністю пропустити це. Ми вже знаємо, що ви можете опустити, ,endякщо хочете решту рядка, що робить %var:~%майже непотрібним синонімом, за %var%винятком того, що він повертається, ~коли %var%порожній. (Можливо, ви могли б використати це в тесті if %var:~%==~:?)


Мені подобається, що ваше останнє речення нагадало нам, що це заощадить кілька цитат :) +1.
stevefestl

1

Скорочення IF EQUтверджень

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

Використання ==замість equ економії 3 байти.


Скорочення цитат у IF висловлюваннях

Це традиційне так зване «безпечніше» ifспівставлення.

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

Щоб скоротити це твердження, виконайте наступне, коли вхід може бути буквено-цифровим / порожнім :

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

Збереження всього 2 байт.


Проблеми, які потребують результатів

Якщо питання говорить щось на кшталт:

Виводить щонайменше 1 видимий символ.

тоді ви могли просто зробити це:

cd

The cdПоказує поточний каталог STDOUT.


GOTOін етикет

Ось кілька методів goto відтворення мітки, упорядкованих у порядку зменшення байтів.

goto :l
goto l
goto:l

Вищеописаний спосіб економить 1 байт.


1
Крім того, ви можете зробити це, goto:lщо зберігає той самий 1 байт і має додатковий бонус за збереження своєї товстої кишки
Матеус Авельяр

@MatheusAvellar: Я додав вміст відповідно до вашого коментаря
stevefestl

1

Опускаючи простір між командою та параметрами з косою рисою

Вибачте за неінформативну назву. Що я намагаюся досягти, це те, що для деяких (не всіх) команд Windows ви можете опустити пробіл між назвою команди / програми та параметром, доки цей параметр починається з косої риски. Наприклад:

for /f %%G in ...

стає

for/f %%G in ...

-1 байт!

Виведення трубопроводів замість використання ERRORLEVEL

Використання ERRORLEVEL для визначення правильності виконання команди - це не найкоротший або найелегантніший метод. Замість цього ви можете подати трубу. Це працює наступним чином (пам’ятайте, що будь-яка команда після того, як &&оператор виконує лише те, якщо команда перед запуском &&без помилок. Будь-яка команда після ||оператора, з іншого боку, буде виконуватися лише в тому випадку, якщо команда до неї НЕ працює належним чином. Мій приклад: :

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

Це можна замінити на:

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

-26 байт, ух! Зауважте, що це не працює з такими командамиchoice ERRORLEVEL має спеціальне значення відповідно до деякого вводу.

З повагою,
Гейб


1

Ефективне використання дужок

Привіт ще раз,

Вибачте за публікацію другої відповіді, але я вважав, що це заслуговує. Я помітив, що люди часто використовують один із наступних методів для відображення виводу команд, не показуючи цей прискіпливий C:\Windows\System32>echo fooрядок перед кожною командою.
Перший метод (з використанням echo off):

@echo off
echo foo
echo bar
echo foobar
echo barfoo

Другий спосіб:

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

Однак жоден із цих методів не є таким коротким, як наступний:

@(echo foo
echo bar
echo foobar
echo barfoo)

Дуже зручно, правда? З іншого боку, це можна легко передати декілька ліній виводу у файл чи пристрій. Наприклад, цей тривалий код:

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

стає значно коротше:

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

Дякуємо, що прочитали цю досить тривалу відповідь, і я сподіваюся, що це вам допоможе. З повагою,
Гейб


Опублікувати кілька відповідей на підказки - це непогано.
Ерік Аутгольфер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.