Golfista de lote automático

25

Me encanta BATCH, a pesar de su sorprendente falta de comandos funcionales, a pesar de su falta de soporte no entero. ¿Por qué? Porque esto funciona:

SET var=SET
%var% i=0

Esto evaluaría para:

SET var=SET
SET i=0

Fantástico, ¿no es así? He usado esta técnica en un programa BATCH antes, ¡porque ahorra bytes!

Su desafío, si lo acepta, sería "jugar" a los programas BATCH de esta manera. Debe disminuir el tamaño de byte de un programa BATCH de entrada al incluir SETdeclaraciones que evaluarían partes del programa y de ninguna otra manera modificar el programa. (Esto no permite, por ejemplo, cambiar el nombre de una variable a algo más corto. Tenga en cuenta que BATCH, además de las variables, no distingue entre mayúsculas y minúsculas). Su puntaje se calcula de la siguiente manera:

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

Me reservo el derecho de agregar más casos de prueba, a fin de desalentar el trabajo para optimizar el programa para los casos de prueba.

En aras de este desafío, sus SETdeclaraciones no pueden contener caracteres de control ( |, <, >, %) o saltos de línea. No puede modificar el código que no sea para mover piezas de código dentro de una instrucción establecida. (Es decir, no puede eliminar espacios en blanco innecesarios, reemplazar EQUcon ==, etc.) Asumiremos que las líneas terminan con \n.

Casos de prueba

Cada caso de prueba está en un bloque de código separado, y cada caso de prueba es autónomo, lo que significa que debe jugar al golf solo asumiendo lo que se proporciona dentro de él. (Es decir, si está SET d=SETen un programa, esa declaración no se dará automáticamente a ningún otro programa). Cada resultado de ejemplo se puede encontrar después de cada caso de prueba. Hay una línea entre los casos de prueba.

@ECHO OFF
Incremento SET = 10
:lazo
SI% incremento% EQU 0 GOTO final
ECHO% incremento%
SET / A% de incremento% - = 1
GOTO loop
:fin
SALIDA

@ECHO OFF
SET / p INPUT = Ingrese la entrada aquí:
SET R =% 1
ECHO Último carácter de entrada aquí:% R: ~ -1%

@ECHO OFF
Incremento SET = 10
:mi
GOTO f
ECHO f
:F
GOTO g
ECHO g
:sol
GOTO h
ECHO h
: h
GOTO i
ECHO i
:yo
GOTO j
ECHO j
: j
SI 3 == 4 (ECHO 4) ELSE (ECHO 5)
SI 5 == 3 (GOTO l) ELSE (GOTO k)
: k
Eco hecho.
ECHO BATCH OUT !!
SALIDA
: l
GOTO g

ECHO Hola, hola, hola, hola, hola, hola, hola !, hola, ello !, Lello.

Salidas de ejemplo:

@ECHO OFF
Incremento SET = 10
:lazo
SI% incremento% EQU 0 GOTO final
ECHO% incremento%
SET / A% de incremento% - = 1
GOTO loop
:fin
SALIDA
(0 bytes guardados)

@ECHO OFF
SET% i% = ingrese aquí:
SET / p INPUT = Ingrese% i%
SET R =% 1
ECHO Último carácter de% i %% R: ~ -1%
(3 bytes ganados)

@ECHO OFF
Incremento SET = 10
SET g = GOTO 
SET e = ECHO 
:mi
% g% f
% e% f
:F
% g% g
%p.ej
:sol
% g% h
% e% h
: h
%soldado americano
% e% i
:yo
% g% j
% e% j
: j
SI 3 == 4 (% e% 4) ELSE (% e% 5)
SI 5 == 3 (% g% l) ELSE (% g% k)
: k
% e% Listo.
% e% LOTE !!
SALIDA
: l
% g% g
(10 caracteres guardados)

SET% h% = ello,
ECHO H% h% H% h% H% h% h% h% h% h% H% h% ¡Hola !, h% h% ello !, Lello.
(1 personaje guardado)

Conor O'Brien
fuente
2
¡Acortar lote para diversión y ganancias!
Alex Carlsen
Necesita algunas especificaciones más. Por supuesto, AAA %increment%set a=increment¶AAA %%a%%no es válido y AAA %1 BBB %2set a= BBB ¶AAA %1%a%%2es válido. (iirc) Entonces necesitas formalizarlo. ( representa una nueva línea)
usuario202729
¿Necesitamos manejar el código que ha retrasado la expansión habilitada, los escapes de signo de porcentaje o las declaraciones multilínea para / si? Según el último caso de prueba (que produce una salida adicional cuando el eco está activado y no hay @antes SET), ¿es aceptable una salida externa del programa de golf?
Precioso
1
Tcl de nuevo
Ven
1
a pesar de incluso debido a ?
Adám

Respuestas:

4

Java 8, Java 10 , 3884 799/795 programa + 484 salida = 4368 1283/1279 total

Hay dos limitaciones de este código:

  • Se supone que las variables de la A a la Z son libres. (mayúscula)
  • Se supone que no hay más de 27 sustituciones.
  • Ah, y debido a que Scanner no lo corta del todo, la entrada vacía elimina el seguimiento de la pila.

Pero bueno, ¡hay un profesional!

  • Salidas mejor código. Siempre.

El código logra un mejor desempeño que los ejemplos proporcionados por el autor del desafío.

Esta versión de golf ha sido realizada por 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;}

Pruébalo en línea!

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;}

Pruébalo en línea! .

Versión original

No es golf en absoluto, solo quería divertirme, no sufrir. Si usted, querido lector, desea responder esta respuesta, hágalo.

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);
		
		
	}

}

Salida de ejemplo:

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

Pruébalo en línea!

Krzysztof Szewczyk
fuente
Creo que todo eso "java.util". Es repetitivo. Puede intentar simplificar su código import java.util.*.
A̲̲
Pensé que las importaciones jdk no cuentan?
Mark Jeronimus
@A_ puede modificar mi respuesta como desee (a menos que sea válida y mantenga el espíritu)
Krzysztof Szewczyk
1
" Si usted, querido lector, desea obtener esta respuesta, hágalo " . 799 bytes en Java 8 o 795 bytes en Java 10+ . De nada. :) Definitivamente se puede jugar un poco más, pero esto lo hará por ahora.
Kevin Cruijssen
2
@KevinCruijssen Gracias por la contribución. He agregado tu versión a la publicación. Siéntase libre de editarlo sin preguntarme si encuentra algo mejor.
Krzysztof Szewczyk