Conseils pour jouer au golf en lot

14

Windows Batch (CMD) est probablement le langage le moins approprié pour jouer au code.

Évitez les caractères de nouvelle ligne . Si vous recherchez le code le plus court en octets, par opposition aux caractères, vous voudrez vous débarrasser de tous les retours chariot inutiles (caractères de nouvelle ligne = 2 octets). Vous pouvez utiliser l' &opération pour ce faire, en supprimant un octet pour chaque commande.

echo Hello&echo World.

Définition des variables . Lors de la définition de variables à l'aide de commutateurs, l' setanalyseur ignorera les espaces.

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

Notez que les mêmes règles d'analyse ne s'appliquent pas à toutes les commandes - par exemple, pour les boucles nécessitent des espaces. Sauf entre set, string, or command(c'est-à-dire ce qui est à l'intérieur des crochets) et le mot do.

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

Expressions mathématiques simples . Notez également l'expression que j'ai utilisée pour incrémenter dans la set /acommande. Pour des expressions mathématiques simples, utilisez += -= *= /=plutôt (par exemple) set /a a=%a%+1.

Collecte de la sortie de commande . Pour obtenir la sortie d'une commande, il peut parfois être utile de sortir et de lire à partir d'un fichier, où vous auriez sinon pu utiliser une boucle for pour rassembler la sortie:

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

echo testenvoyer stdout dans un fichier appelé f, >fdémarrer une nouvelle commande &et obtenir le contenu du fichier dans une variable set/pa=<f. Évidemment, ce n'est pas toujours utile. Mais cela peut être lorsque tout ce dont vous avez besoin est une seule ligne de sortie.

Sortie de commande . Lors de la suppression de la sortie des commandes, utilisez @avant les commandes, sauf si vous devez supprimer plus de 9 commandes, auquel cas utilisez-les @echo offau début de votre script. @echo offest de 9 octets de long et économisera donc généralement plus d'octets avec des scripts plus longs.

Les commandes font souvent plus que ce qui est évident - pensez à ce que font vos commandes. Par exemple; si vous devez définir une variable et faire écho à une autre variable, au lieu de:

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

Vous pouvez utiliser la commande set avec le /pcommutateur pour sortir %a%pour vous.

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

Entièrement golfé ...

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

Quelques exemples - Compter la somme de tous les chiffres - Conjecture de Goldbach .

Tout autre conseil est plus qu'apprécié - je continuerai à le mettre à jour si je pense à autre chose.

dégrader
la source
16
Veuillez poster les parties de réponse de ceci comme réponse, pas comme partie de la question.
Pas que Charles le
@Charles Je suis assez sûr de la façon dont j'ai fait ceci est un format acceptable pour une «question de conseils». D'autres personnes peuvent ajouter des réponses avec leurs propres conseils.
unclemeat

Réponses:

4

Compteurs

Chaque fois que vous avez une variable qui servira de compteur à partir de 0 vous voudrez peut-être écrire

set count=0
set/acount+=1

; cependant, vous pouvez éliminer les premières lignes car chaque fois qu'il set/aest utilisé avec une variable non définie, sa valeur est supposée être0

set/acounter+=1

Blocs de code

Il existe plusieurs façons de raser quelques octets lorsque vous devez utiliser des blocs de code.

Chaque fois que vous ouvrez un bloc de code, vous n'avez pas besoin d'insérer un saut de ligne avant la première ligne de code dans ce bloc. Les parenthèses fermantes ne doivent pas non plus être sur une ligne propre.

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

peut être joué au golf à

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

Impression sans nouvelle ligne

Le schéma courant est

echo|set/p=text

mais, vous pouvez enregistrer 2 octets echoencd

cd|set/p=text
ankh-morpork
la source
2
@ ankp-morpork Hé, je suis un peu en retard. Mais je veux vous informer que la ifdéclaration peut être approfondie. Le meilleur devrait être:if %a%==%b% (echo true)else echo false
stevefestl
3

Esperluettes

Bien que & rend le code plus court, car il utilise moins de lignes, il utilise autant de caractères qu'une nouvelle ligne. Cela signifie que

echo a&echo b

est aussi long que

echo a
echo b

afin que votre code puisse rester lisible sans perdre de caractères.

Il peut y avoir des exceptions, car certains éditeurs de texte combinent le saut de ligne et le retour de la cartouche pour chaque nouvelle ligne.

kitcar2000
la source
J'ai inclus cela dans le message d'origine, car une nouvelle ligne compte pour deux octets dans chaque éditeur de texte que j'utilise. Merci d'avoir ajouté cette précision.
unclemeat
2
Le saut de ligne de retour carraige de Windows est de deux caractères et de nombreux éditeurs de texte le compteront comme deux, mais lorsque j'ai commencé à répondre aux questions sur le golf, l'un des commentaires laissés disait que dans les terminaisons de ligne PPCG, on comptait toujours comme un caractère.
Jerry Jeremiah
2
Les sauts de ligne de style Unix fonctionneront très bien dans les scripts CMD, au moins dans les versions récentes de Windows.
user2428118
1
En fait, CMD supprime même les caractères CR avant l'analyse: stackoverflow.com/questions/4094699/…
schnaader
3

Imprimer directement le résultat d'un calcul numérique

Si le défi vous oblige à sortir un nombre qui doit être calculé, vous pouvez utiliser cmd/c set/apour sortir le résultat du calcul directement au lieu d'enregistrer le calcul, puis de le répéter. Exemple:

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

devient

@cmd/cset/a%1+%2

Modifier: Apparemment, aucun espace n'est nécessaire, ce qui permet d'économiser 2 octets supplémentaires.

Neil
la source
2

Expansion retardée

Au lieu d'utiliser le long, setLocal enableDelayedExpansionvous pouvez utiliser cmd /v on(ou cmd/von) qui démarrera un nouvel interpréteur avec l'expansion de variable retardée activée.

Je n'ai pas encore implémenté cela, donc je n'ai pas d'exemples, mais vous pouvez l'utiliser en conjonction avec le /ccommutateur. Exemple:

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

Remarquez l'utilisation du carat avant l'esperluette. si vous devez utiliser plusieurs esperluettes ou tout autre caractère spécial, il est préférable de tout mettre /centre guillemets après le commutateur:

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

Cette méthode présente également l'avantage de ne devoir utiliser qu'un seul @caractère pour masquer toutes les entrées, et peut donc être utilisée, sans /von, comme alternative plus courte à @echo off(ou plusieurs @symboles).

9 caractères: @echo off
6 caractères:@cmd/c

Pour des scripts plus longs, que vous ne pouvez pas faire sur une seule ligne, vous pouvez faire ce qui suit pour enregistrer quelques octets:

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

Ou, non golfé:

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

Remplacez @echo off&setLocal enableDelayedExpansionpar ce qui précède.

Lorsque vous exécutez pour la première fois votre script !!ne se développera pas du tout, vous recevez donc une erreur car il "!!"ne s'agit pas d'une commande. La sortie d'erreur est ensuite dirigée vers nul ( 2>nul). Lorsque cette première 'commande' échoue ( ||), elle appelle une nouvelle instance de cmd, qui appelle le fichier batch lui-même (en utilisant /v (on)pour activer l'expansion retardée et /qpour désactiver l'écho). Puis !!se développera à rien, car aucune variable n'est appelée <NULL>. Le reste de votre script s'exécute ensuite. Après quoi, il reviendra à l'instance d'origine de cmd, et ( &&) quitter avec la /bcondition pour garder la fenêtre ouverte (la sortie est donc elle ne continue pas à parcourir votre script dans le contexte de la première instance de cmd, avec echo activé et retardé l'expansion désactivée).

dégrader
la source
Pour cela, exécuter des fichiers batch avec cmd /q /v on /c <filename>ne devrait compter que pour 2 octets car ce sont deux "drapeaux" similaires aux drapeaux Perl comme -pIqui ne compteraient que pour 2 octets supplémentaires.
Artyer
1

Chaînes répétitives

Définissez des blocs de code répétitifs dans les variables, où le nombre d'octets utilisés pour définir la variable + le nombre d'octets pour sortir la variable sont inférieurs au nombre d'octets pour simplement appeler le code directement.

Pour un exemple, voir: Dessiner les combinaisons qui totalisent jusqu'à 100

Vous économisez 1 octet par utilisation de la commande set, si vous créez une variable (nommée avec un caractère, comme "s") qui contient set<space>. Cela ne génère de la valeur que si vous utilisez la commande set plus de 12 fois. (Notez qu'il y a un caractère à la fin de la chaîne 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

Ce qui précède est 1 octet plus court que ..

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

C'est probablement un assez mauvais exemple - mais il fait passer le message.

dégrader
la source
1

Début d'une chaîne

La notation %var:~start,end%extrait une sous-chaîne de la variable var. Cependant, si startc'est le cas, 0vous pouvez l'omettre complètement. Nous savons déjà que vous pouvez omettre ,endsi vous voulez le reste de la chaîne, ce qui en fait %var:~%un synonyme presque inutile %var%, sauf qu'il renvoie ~quand %var%est vide. (Peut-être pourriez-vous l'utiliser dans un test if %var:~%==~:?)

Neil
la source
J'aime votre dernière phrase nous rappelant que cela économisera quelques citations :) +1 pour cela.
stevefestl
1

raccourcissant IF EQUdéclarations

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

Utiliser ==au lieu d' equ enregistrer 3 octets.


Raccourcir les citations dans les IFdéclarations

Il s'agit d'une ifcomparaison dite «plus sûre» traditionnelle .

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

Pour raccourcir cette instruction, procédez comme suit lorsque l'entrée ne peut être que alphanumérique / vide :

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

Enregistrement d'un total de 2 octets.


Défis nécessitant une sortie

Si la question dit quelque chose comme:

Génère au moins 1 caractère visible.

alors vous pouvez simplement faire ceci:

cd

Le cdaffiche le répertoire actuel vers STDOUT.


GOTOune étiquette

Voici quelques méthodes de gotocréation d'une étiquette, triées par ordre décroissant d'octets.

goto :l
goto l
goto:l

La méthode ci-dessus enregistre 1 octet.

stevefestl
la source
1
Alternativement, vous pouvez faire goto:lce qui enregistre le même 1 octet et a l'avantage supplémentaire de garder vos deux points intacts
Matheus Avellar
@MatheusAvellar: J'ai ajouté le contenu en conséquence à votre commentaire
stevefestl
1

Omettre l'espace entre la commande et les paramètres avec des barres obliques

Désolé pour le titre non informatif. Ce que j'essaie de comprendre, c'est que pour certaines commandes (pas toutes) de Windows, vous pouvez omettre l'espace entre le nom de la commande / du programme et le paramètre, tant que ce paramètre commence par une barre oblique. Par exemple:

for /f %%G in ...

devient

for/f %%G in ...

-1 octet!

Sortie de tuyauterie au lieu d'utiliser ERRORLEVEL

L'utilisation de ERRORLEVEL pour déterminer si une commande s'est exécutée correctement n'est pas la méthode la plus courte ou la plus élégante. Au lieu de cela, vous pouvez diriger la sortie. Cela fonctionne comme suit (rappelez-vous que toute commande après l' &&opérateur ne s'exécute que si la commande avant l'exécution &&s'est déroulée sans erreur. En ||revanche, toute commande après l' opérateur ne s'exécutera que si la commande avant son exécution n'a PAS été exécutée correctement. Mon exemple est :

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

Cela pourrait être remplacé par:

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

-26 octets, wow! Notez que cela ne fonctionne pas avec des commandes commechoice , où ERRORLEVEL a une valeur spéciale en fonction de certaines entrées.

Cordialement,
Gabe

Gabriel Mills
la source
1

Utiliser efficacement les parenthèses

Re-bonjour,

Désolé de poster une deuxième réponse mais j'ai senti que celle-ci le méritait. J'ai remarqué que les gens utilisent souvent l'une des méthodes suivantes pour afficher la sortie de commande sans afficher cette C:\Windows\System32>echo fooligne embêtante avant chaque commande.
La première méthode (en utilisant echo off):

@echo off
echo foo
echo bar
echo foobar
echo barfoo

La deuxième méthode:

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

Cependant, aucune de ces méthodes n'est aussi courte que les suivantes:

@(echo foo
echo bar
echo foobar
echo barfoo)

Assez pratique, non? Sur une autre note, cela peut être utilisé pour diriger facilement plusieurs lignes de sortie vers un fichier ou un périphérique. Par exemple, ce long code:

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

devient beaucoup plus court:

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

Merci d'avoir lu cette réponse assez longue, et j'espère que cela vous aidera. Cordialement,
Gabe

Gabriel Mills
la source
Publier plusieurs réponses aux questions des conseils n'est pas mauvais.
Erik the Outgolfer