Golfeur Auto BATCH

25

J'adore BATCH, malgré son manque choquant de commandes fonctionnelles, malgré même en raison de son manque de support non entier. Pourquoi? Parce que cela fonctionne:

SET var=SET
%var% i=0

Cela permettrait d'évaluer:

SET var=SET
SET i=0

Fantastique, non? J'ai déjà utilisé cette technique dans un programme BATCH , car elle économise des octets!

Votre défi, si vous l'acceptez, serait de "jouer" aux programmes BATCH de cette manière. Vous devez diminuer la taille en octets d'un programme BATCH d'entrée en incluant des SETinstructions qui évalueraient des parties du programme et en aucun cas modifier le programme. (Cela interdit, par exemple, de renommer un nom de variable en quelque chose de plus court. Gardez à l'esprit que BATCH, à part les variables, est insensible à la casse.) Votre score est calculé comme suit:

score = # of characters in your program + 5*(net result bytes in test cases below)

Je me réserve le droit d'ajouter plus de cas de test, afin de décourager de travailler pour optimiser le programme pour les cas de test.

Par souci de ce défi, vos SETdéclarations ne peuvent pas contenir des caractères de contrôle ( |, <, >, %) ou linebreaks. Vous ne pouvez pas modifier le code autrement que pour déplacer des morceaux de code à l'intérieur d'une instruction set. (Autrement dit, vous ne pouvez pas supprimer les espaces inutiles, les remplacer EQUpar ==, etc.) Nous supposerons que les lignes se terminent par \n.

Cas de test

Chaque scénario de test est dans un bloc de code distinct et chaque scénario de test est autonome, ce qui signifie que vous ne devez jouer au golf qu'en supposant ce qui y est contenu. (C'est-à-dire, si vous SET d=SETdans un programme, cette déclaration ne sera pas automatiquement donnée à un autre programme). Chaque exemple de résultat peut être trouvé après chaque test élémentaire. Il y a une ligne entre les cas de test.

@ÉCHO OFF
Incrément SET = 10
:boucle
IF% increment% EQU 0 GOTO end
ECHO% increment%
SET / A% increment% - = 1
Boucle GOTO
:fin
SORTIE

@ÉCHO OFF
SET / p INPUT = Entrez l'entrée ici:
SET R =% 1
ECHO Dernier caractère d'entrée ici:% R: ~ -1%

@ÉCHO OFF
Incrément SET = 10
: e
GOTO f
ECHO f
:F
GOTO g
ECHO g
:g
GOTO h
ECHO h
: h
GOTO i
ECHO i
:je
GOTO j
ECHO j
: j
SI 3 == 4 (ECHO 4) AUTRE (ECHO 5)
SI 5 == 3 (GOTO l) AUTRE (GOTO k)
: k
ECHO Terminé.
ECHO BATCH OUT !!
SORTIE
: l
GOTO g

ECHO Bonjour, bonjour, bonjour, bonjour, bonjour, bonjour, bonjour !, bonjour, bonjour !, Lello.

Exemples de sorties:

@ÉCHO OFF
Incrément SET = 10
:boucle
IF% increment% EQU 0 GOTO end
ECHO% increment%
SET / A% increment% - = 1
Boucle GOTO
:fin
SORTIE
(0 octets enregistrés)

@ÉCHO OFF
SET% i% = entrez ici:
SET / p INPUT = Entrez% i%
SET R =% 1
ECHO Dernier caractère de% i %% R: ~ -1%
(3 octets gagnés)

@ÉCHO OFF
Incrément SET = 10
SET g = GOTO 
SET e = ECHO 
: e
% g% f
% e% f
:F
% g% g
%par exemple
:g
% g% h
% e% h
: h
% g% i
% e% i
:je
% g% j
% e% j
: j
SI 3 == 4 (% e% 4) AUTRE (% e% 5)
SI 5 == 3 (% g% l) AUTRE (% g% k)
: k
% e% Terminé.
% e% BATCH OUT !!
SORTIE
: l
% g% g
(10 caractères enregistrés)

SET% h% = bonjour,
ECHO H% h% H% h% H% h% h% h% h% h% H% h% Bonjour !, h% h% ello !, Lello.
(1 caractère enregistré)

Conor O'Brien
la source
2
Raccourcir le lot pour le plaisir et le profit!
Alex Carlsen
Vous avez besoin de plus de spécifications. Bien sûr, AAA %increment%set a=increment¶AAA %%a%%n'est pas valide et AAA %1 BBB %2set a= BBB ¶AAA %1%a%%2est valide. (iirc) Vous devez donc le formaliser. ( représente une nouvelle ligne)
user202729
Avons-nous besoin de gérer du code dont l'expansion retardée est activée, les échappements à signe de pourcentage ou les instructions multi-lignes pour / si? Selon le dernier cas de test (qui produit une sortie supplémentaire lorsque l'écho est activé et qu'il n'y en a pas @avant SET), la sortie étrangère est-elle acceptable du programme joué?
aturous
1
Tcl encore une fois
Ven
1
malgré même à cause de ?
Adám

Réponses:

4

Java 8, Java 10 , programme 3884 799/795 + sortie 484 = 4368 1283/1279 au total

Il y a deux limites à ce code:

  • Il suppose que les variables de A à Z sont libres. (majuscule)
  • Il suppose qu'il n'y a pas plus de 27 substitutions.
  • Oh, et parce que Scanner ne le coupe pas tout à fait, une entrée vide vide la trace de pile.

Mais bon - il y a un pro!

  • Génère le meilleur code. Toujours.

Le code réussit mieux que les exemples fournis par l'auteur du défi.

Cette version golfée a été réalisée par Kevin .

Java 8

c->{List<String>S=new Stack();HashMap<String,Integer>h=new HashMap(),s=new HashMap();int v=65,l=c.length(),b,e;do{for(b=0,l=c.length(),s.clear();b!=l;b++)for(e=b;++e<=l;)S.add(c.substring(b,e));S.removeIf(t->t.length()<5|t.matches(".*[\n|<%>].*"));S.forEach(t->h.merge(t,1,Integer::sum));S.clear();h.entrySet().removeIf(t->t.getValue()==1);String Y=c;int L=l;char V=(char)v;h.forEach((k,x)->{String i=Y,t;for(int j,I,q;i.contains(k);i=t+"%"+V+"%"+i.substring(j+k.length(),i.length())){for(I=-1,t=i.substring(q=0,j=i.indexOf(k));(I=t.indexOf("%",++I))>=0;q++);if(q%2>0)return;}i="SET "+V+"="+k+"\n"+i;if(i.length()<L)s.put(i,L-i.length());});h.clear();v++;c=s.isEmpty()?c:s.entrySet().stream().max((x,y)->x.getValue()>y.getValue()?1:-1).get().getKey();}while(l>c.length());return c;}

Essayez-le en ligne!

Java 10

c->{var S=new Stack<String>();HashMap<String,Integer>h=new HashMap(),s=new HashMap();int v=65,l=c.length(),b,e;do{for(b=0,l=c.length(),s.clear();b!=l;b++)for(e=b;++e<=l;)S.add(c.substring(b,e));S.removeIf(t->t.length()<5|t.matches(".*[\n|<%>].*"));S.forEach(t->h.merge(t,1,(x,y)->x+y));S.clear();h.entrySet().removeIf(t->t.getValue()==1);var Y=c;int L=l;var V=(char)v;h.forEach((k,x)->{String i=Y,t;for(int j,I,q;i.contains(k);i=t+"%"+V+"%"+i.substring(j+k.length(),i.length())){for(I=-1,t=i.substring(q=0,j=i.indexOf(k));(I=t.indexOf("%",++I))>=0;q++);if(q%2>0)return;}i="SET "+V+"="+k+"\n"+i;if(i.length()<L)s.put(i,L-i.length());});h.clear();v++;c=s.isEmpty()?c:s.entrySet().stream().max((x,y)->x.getValue()>y.getValue()?1:-1).get().getKey();}while(l>c.length());return c;}

Essayez-le en ligne! .

Version originale

Ce n'est pas du tout du golf, je voulais juste m'amuser, ne pas souffrir. Si vous, cher lecteur, souhaitez jouer cette réponse, n'hésitez pas.

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class Main {
	List<String> substrings = new ArrayList<String>();
	HashMap<String, Integer> hm = new HashMap<String, Integer>();
	HashMap<String, Integer> scores = new HashMap<String, Integer>();
	
	private int v1 = 65;
	
	public static String rfos(String inputString, String stringToReplace,
	        String stringToReplaceWith) {

	    int length = stringToReplace.length();
	    int inputLength = inputString.length();

	    int startingIndexofTheStringToReplace = inputString.indexOf(stringToReplace);

	    if(count(inputString.substring(0, startingIndexofTheStringToReplace), "%") % 2 == 1)
	    	return null;
	    
	    String finalString = inputString.substring(0, startingIndexofTheStringToReplace) + stringToReplaceWith
	            + inputString.substring(startingIndexofTheStringToReplace + length, inputLength);

	    return finalString;

	}
	
	public static int count(String text, String find) {
        int index = 0, count = 0, length = find.length();
        while( (index = text.indexOf(find, index)) != -1 ) {                
                index += length; count++;
        }
        return count;
	}
	
	private String process(String program) {
		int begin = 0, end, il = program.length();
		
		scores.clear();
		
		while(begin != program.length()) {
			for(end = begin + 1; end < program.length() + 1; end++)
				substrings.add(program.substring(begin, end));
			begin++;
		}
		
		substrings.removeIf(new Predicate<String>() {
			@Override
			public boolean test(String arg0) {
				return arg0.length() <= 4 || arg0.contains("\n")
						|| arg0.contains("|")
						|| arg0.contains("<")
						|| arg0.contains("%")
						|| arg0.contains(">");
			}
		});
		
		substrings.forEach(new Consumer<String>() {

			@Override
			public void accept(String t) {
				if(hm.containsKey(t)) {
					hm.replace(t, hm.get(t) + 1);
				} else {
					hm.put(t, 1);
				}
			}
			
		});
		
		substrings.clear();
		
		hm.entrySet().removeIf(new Predicate<Map.Entry<String, Integer>>() {

			@Override
			public boolean test(Map.Entry<String, Integer> t) {
				return t.getValue() == 1;
			}
			
		});
		
		hm.forEach(new BiConsumer<String, Integer>() {
			
			@Override
			public void accept(String arg0, Integer arg1) {
				String iteration = program;
				boolean between = false;
				while(iteration.contains(arg0)) {
					iteration = rfos(iteration, arg0, "%" + Character.toString((char) v1) + "%");
					if(iteration == null)
						return;
				}
				iteration = "SET " + Character.toString((char) v1) + "=" + arg0 + "\n" + iteration;
				if(iteration.length() < program.length())
					scores.put(iteration, program.length() - iteration.length());
			}
			
		});
		
		hm.clear();
		v1++;
		
		if(scores.isEmpty())
			return program;
		else
			return scores.entrySet().stream().max((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? 1 : -1).get().getKey();
	}

	public static void main(String[] args) {
		Main processor = new Main();
		int genid = 0, before = 0, after = 0;
		String currentCode = new Scanner(System.in).useDelimiter("\\Z").next();
		
		System.out.println("Calculating first generation...");
		
		do {
			String cc = processor.process(currentCode);
			before = currentCode.length();
			after = cc.length();
			
			currentCode = cc;
			
			if(before > after) {
				System.out.println("Generation " + genid++);
				System.out.println(before + " -> " + after);
				System.out.println("***\n" + cc + "\n***");
			} else {
				System.out.println("Generation FAIL " + genid++);
				System.out.println(before + " -> " + after);
				System.out.println("***\n" + cc + "\n***");
			}
		} while(before > after);
		
		
	}

}

Exemple de sortie:

SET B=GOTO 
SET A=ECHO 
@%A%OFF
SET increment=10
:e
%B%f
%A%f
:f
%B%g
%A%g
:g
%B%h
%A%h
:h
%B%i
%A%i
:i
%B%j
%A%j
:j
IF 3==4 ( %A%4 ) ELSE ( %A%5 )
IF 5==3 ( %B%l ) ELSE ( %B%k )
:k
%A%Done.
%A%BATCH OUT!!
EXIT
:l
%B%g

Essayez-le en ligne!

Krzysztof Szewczyk
la source
Je pense que tout cela "java.util." est répétitif. Vous pouvez vouloir simplifier votre code import java.util.*.
Un
Je pensais que les importations JDK ne comptent pas?
Mark Jeronimus
@A_ vous pouvez modifier ma réponse comme vous le souhaitez (sauf si elle est valide et garde l'esprit)
Krzysztof Szewczyk
1
" Si vous, cher lecteur, souhaitez jouer cette réponse, faites-le. " 799 octets en Java 8 ou 795 octets en Java 10+ . De rien. :) Peut certainement être joué au golf un peu plus, mais cela fera l'affaire pour l'instant.
Kevin Cruijssen
2
@KevinCruijssen Merci pour la contribution. J'ai ajouté votre version au message. N'hésitez pas à le modifier sans me demander si vous trouvez quelque chose de mieux.
Krzysztof Szewczyk