Auto-BATCH-Golfer

25

Ich liebe BATCH, trotz des schockierenden Mangels an funktionalen Befehlen, trotz des Mangels an nicht ganzzahliger Unterstützung. Warum? Weil das funktioniert:

SET var=SET
%var% i=0

Dies würde zu folgenden Ergebnissen führen:

SET var=SET
SET i=0

Fantastisch, nicht wahr? Ich habe diese Technik schon in einem BATCH-Programm verwendet , weil es Bytes spart!

Ihre Herausforderung, sollten Sie dies akzeptieren, wäre es, BATCH-Programme auf diese Weise zu "golfen". Sie müssen die Bytegröße eines Eingabe-BATCH-Programms verringern, indem Sie SETAnweisungen einschließen , die Teile des Programms auswerten und das Programm auf keine andere Weise ändern. (Dies verbietet beispielsweise das Umbenennen eines Variablennamens in einen kürzeren Namen. Beachten Sie, dass bei BATCH außer bei Variablen die Groß- und Kleinschreibung nicht berücksichtigt wird.) Ihre Punktzahl wird wie folgt berechnet:

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

Ich behalte mir das Recht vor, weitere Testfälle hinzuzufügen, um nicht daran zu arbeiten, das Programm für die Testfälle zu optimieren.

Im Interesse dieser Herausforderung, Ihre SETAussagen können keine Steuerzeichen enthalten ( |, <, >, %) oder Zeilenumbrüche. Sie dürfen den Code nur ändern, um Teile des Codes in einer set-Anweisung zu verschieben. (Das heißt, dass Sie nicht unnötig Leerzeichen entfernen, ersetzen EQUmit ==, etc.) Wir gehen davon aus, dass die Linien am Ende mit \n.

Testfälle

Jeder Testfall befindet sich in einem separaten Codeblock, und jeder Testfall ist in sich abgeschlossen. Sie sollten also nur unter der Annahme spielen, was darin enthalten ist. (Wenn Sie also SET d=SETin einem Programm arbeiten, wird diese Anweisung nicht automatisch an ein anderes Programm weitergegeben.) Jedes Beispielergebnis kann nach jedem Testfall gefunden werden. Es gibt eine Linie zwischen Testfällen.

@ECHO AUS
SET Inkrement = 10
:Schleife
IF% increment% EQU 0 GOTO end
ECHO% increment%
SET / A% Inkrement% - = 1
GOTO-Schleife
:Ende
AUSFAHRT

@ECHO AUS
SET / p INPUT = Eingabe hier eingeben:
SET R =% 1
ECHO Letztes Zeichen der Eingabe hier:% R: ~ -1%

@ECHO AUS
SET Inkrement = 10
: e
GOTO f
ECHO f
: f
GOTO g
ECHO g
:G
GOTO h
ECHO h
: h
GOTO i
ECHO i
:ich
GOTO j
ECHO j
: j
IF 3 == 4 (ECHO 4) ELSE (ECHO 5)
IF 5 == 3 (GOTO l) ELSE (GOTO k)
: k
ECHO Fertig.
ECHO BATCH OUT !!
AUSFAHRT
: l
GOTO g

ECHO Hallo, hallo, hallo, hallo, hallo, hallo !, hallo, hallo !, hallo.

Beispielausgaben:

@ECHO AUS
SET Inkrement = 10
:Schleife
IF% increment% EQU 0 GOTO end
ECHO% increment%
SET / A% Inkrement% - = 1
GOTO-Schleife
:Ende
AUSFAHRT
(0 Bytes gespeichert)

@ECHO AUS
SET% i% = hier eingeben:
SET / p INPUT =% i% eingeben
SET R =% 1
ECHO Letztes Zeichen von% i %% R: ~ -1%
(3 Bytes gewonnen)

@ECHO AUS
SET Inkrement = 10
SET g = GOTO 
SET e = ECHO 
: e
% g% f
% e% f
: f
% g% g
%z.B
:G
% g% h
% e% h
: h
% g% i
% e% i
:ich
% g% j
% e% j
: j
IF 3 == 4 (% e% 4) ELSE (% e% 5)
IF 5 == 3 (% g% l) ELSE (% g% k)
: k
% e% Fertig
% e% BATCH OUT !!
AUSFAHRT
: l
% g% g
(10 Zeichen gespeichert)

SET% h% = ello,
ECHO H% h% h% h% h% h% h% h% h% h% h% h% Hallo !, h% h% ello !, Lello.
(1 Zeichen gespeichert)

Conor O'Brien
quelle
2
Chargenverkürzung für Spaß und Gewinn!
Alex Carlsen
Sie benötigen weitere Spezifikationen. Natürlich ist AAA %increment%set a=increment¶AAA %%a%%ungültig und AAA %1 BBB %2set a= BBB ¶AAA %1%a%%2gültig. (iirc) Also musst du es formalisieren. ( Stellt eine neue Zeile dar)
user202729
Müssen wir Code verarbeiten, für den eine verzögerte Erweiterung aktiviert, Prozentzeichen-Escapezeichen oder mehrzeilige for / if-Anweisungen aktiviert wurden? Wie laut dem letzten Testfall (der zusätzliche Ausgabe erzeugt, wenn das Echo eingeschaltet ist und es keine @vor dem gibt SET) ist die externe Ausgabe vom Golfprogramm akzeptabel?
Οurous
1
Tcl noch einmal
Ven
1
trotz auch wegen ?
Adám

Antworten:

4

Java 8, Java 10 , 3884 799/795 Programm + 484 Ausgabe = 4368 1283/1279 gesamt

Es gibt zwei Einschränkungen dieses Codes:

  • Es wird davon ausgegangen, dass Variablen von A bis Z frei sind. (Großbuchstaben)
  • Es wird davon ausgegangen, dass es nicht mehr als 27 Substitutionen gibt.
  • Oh, und weil Scanner es nicht ganz ausschneidet, werden leere Eingaben als Stacktrace ausgegeben.

Aber hey - da ist ein Profi!

  • Gibt den besten Code aus. Immer.

Der Code kann eine bessere Leistung erbringen als die vom Herausforderungsautor bereitgestellten Beispiele.

Diese Golfversion wurde von Kevin erstellt .

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

Probieren Sie es online!

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

Probieren Sie es online! .

Originalfassung

Es wird überhaupt nicht golfen, ich wollte nur ein bisschen Spaß haben, nicht leiden. Wenn Sie, verehrter Leser, diese Antwort Golf spielen möchten, tun Sie es bitte.

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

}

Beispielausgabe:

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

Probieren Sie es online!

Krzysztof Szewczyk
quelle
Ich denke all das "java.util". ist repetitiv. Möglicherweise möchten Sie Ihren Code zu vereinfachen import java.util.*.
A
Ich dachte jdk importe zählen nicht?
Mark Jeronimus
@ A_ Sie können meine Antwort ändern, wie Sie möchten (es sei denn, es ist gültig und behält den Geist)
Krzysztof Szewczyk
1
" Wenn Sie, lieber Leser, diese Antwort auf Golf spielen möchten, tun Sie es bitte. " 799 Bytes in Java 8 oder 795 Bytes in Java 10+ . Bitte. :) Kann auf jeden Fall noch ein bisschen mehr golfen, aber das reicht fürs Erste.
Kevin Cruijssen
2
@ KevinCruijssen Danke für den Beitrag. Ich habe deine Version zum Beitrag hinzugefügt. Fühlen Sie sich frei, es zu bearbeiten, ohne mich zu fragen, ob Sie etwas Besseres finden.
Krzysztof Szewczyk