Giocatore di golf automatico di BATCH


25

Adoro BATCH, nonostante la sua scioccante mancanza di comandi funzionali, nonostante la mancanza di supporto non intero. Perché? Perché funziona:

SET var=SET
%var% i=0

Ciò valuterebbe a:

SET var=SET
SET i=0

Fantastico, vero? Ho usato questa tecnica in un programma BATCH prima, perché salva byte!

La tua sfida, se la accettassi, sarebbe quella di "golfare" i programmi BATCH in questo modo. Devi ridurre la dimensione dei byte di un programma BATCH di input includendo SETistruzioni che valuterebbero parti del programma e in nessun altro modo modificare il programma. (Ciò non consente, per esempio, di rinominare un nome di variabile in qualcosa di più breve. Tieni presente che BATCH, a parte le variabili, non distingue tra maiuscole e minuscole.) Il tuo punteggio viene calcolato come segue:

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

Mi riservo il diritto di aggiungere altri casi di test, in modo da scoraggiare il lavoro per ottimizzare il programma per i casi di test.

Per il bene di questa sfida, le vostre SETaffermazioni non possono contenere caratteri di controllo ( |, <, >, %) o le interruzioni di linea. Non è possibile modificare il codice se non per spostare parti di codice all'interno di un'istruzione set. (Cioè, non puoi rimuovere spazi bianchi non necessari, sostituirli EQUcon ==, ecc.) Assumeremo che le linee finiscano con \n.

Casi test

Ogni caso di test si trova in un blocco di codice separato e ogni caso di test è autonomo, il che significa che dovresti giocare a golf solo assumendo ciò che viene dato al suo interno. (Vale a dire, se sei SET d=SETin un programma, quella dichiarazione non sarà data automaticamente a nessun altro programma). Ogni risultato di esempio può essere trovato dopo ogni caso di test. C'è una linea tra i casi di test.

@ECHO OFF
Incremento SET = 10
:ciclo continuo
IF% incremento% EQU 0 Fine GOTO
ECHO% incremento%
SET / A% incremento% - = 1
Ciclo GOTO
:fine
USCITA

@ECHO OFF
SET / p INPUT = Immettere qui l'ingresso:
SET R =% 1
ECHO Ultimo carattere di input qui:% R: ~ -1%

@ECHO OFF
Incremento SET = 10
: e
GOTO f
ECHO f
: f
GOTO g
ECHO g
: g
GOTO h
ECHO h
: h
GOTO i
ECHO i
:io
GOTO j
ECHO j
: j
IF 3 == 4 (ECHO 4) ELSE (ECHO 5)
IF 5 == 3 (GOTO l) ELSE (GOTO k)
:K
ECHO Fatto.
ECHO BATCH OUT !!
USCITA
: l
GOTO g

ECHO Ciao, Ciao, Ciao, ciao, ciao, ciao, ciao !, ciao, ciao !, Lello.

Esempi di output:

@ECHO OFF
Incremento SET = 10
:ciclo continuo
IF% incremento% EQU 0 Fine GOTO
ECHO% incremento%
SET / A% incremento% - = 1
Ciclo GOTO
:fine
USCITA
(0 byte salvati)

@ECHO OFF
SET% i% = inserisci qui:
SET / p INPUT = Inserisci% i%
SET R =% 1
ECHO Ultimo carattere di% i %% R: ~ -1%
(3 byte acquisiti)

@ECHO OFF
Incremento SET = 10
SET g = GOTO 
SET e = ECHO 
: e
% G% f
% E% f
: f
% G g%
%per esempio
: g
% G% h
% E% h
: h
% G% i
%% I E
:io
% G j%
% E% j
: j
IF 3 == 4 (% e% 4) ELSE (% e% 5)
IF 5 == 3 (% g% l) ELSE (% g% k)
:K
% E% Fatto.
% e% FUORI BATCH !!
USCITA
: l
% G g%
(10 caratteri salvati)

SET% h% = ciao,
ECHO H% h% H% h% H% h% h% h% h% h% H% h% Ciao !, h% h% ciao !, Lello.
(1 carattere salvato)


2
Accorciamento batch per divertimento e profitto!
Alex Carlsen,

Hai bisogno di ulteriori specifiche. Naturalmente AAA %increment%set a=increment¶AAA %%a%%non è valido e AAA %1 BBB %2set a= BBB ¶AAA %1%a%%2è valido. (iirc) Quindi devi formalizzarlo. ( rappresenta una nuova riga)
user202729

Dobbiamo gestire il codice che ha abilitato l'espansione ritardata, le escape con segno di percentuale o le istruzioni multi-line for / if? Come per l'ultimo caso di test (che produce un output aggiuntivo quando l'eco è attivo e non c'è @prima che SET) l'output estraneo sia accettabile dal programma golf?
Οuroso

1
Tcl ancora una volta
Ven

1
nonostante anche a causa di ?
Adám,

Risposte:


4

Programma Java 8, Java 10 , 3884 799/795 + 484 output = 4368 1283/1279 totale

Esistono due limitazioni di questo codice:

  • Presuppone che le variabili dalla A alla Z siano libere. (maiuscolo)
  • Presuppone che non vi siano più di 27 sostituzioni.
  • Oh, e poiché lo scanner non lo taglia completamente, l'input vuoto scarica lo stacktrace.

Ma hey - c'è un professionista!

  • Emette il miglior codice. Sempre.

Il codice riesce a funzionare meglio degli esempi forniti dall'autore della sfida.

Questa versione da golf è stata realizzata da 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;}

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

Provalo online! .

Versione originale

Non è affatto golf, volevo solo divertirmi, non soffrire. Se tu, caro lettore, vorresti giocare a golf con questa risposta, per favore fallo.

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

}

Esempio di output:

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

Provalo online!


Penso a tutto ciò che "java.util". è ripetitivo. Potresti voler semplificare il tuo codice import java.util.*.
A̲̲

Pensavo che le importazioni jdk non contassero?
Mark Jeronimus,

@A_ puoi modificare la mia risposta come desideri (a meno che non sia valida e mantenga lo spirito)
Krzysztof Szewczyk

1
" Se tu, caro lettore, desideri giocare a golf questa risposta, per favore fallo. " 799 byte in Java 8 o 795 byte in Java 10+ . Prego. :) Si può sicuramente giocare ancora un po 'a golf, ma per ora lo farà.
Kevin Cruijssen,

2
@KevinCruijssen Grazie per il contributo. Ho aggiunto la tua versione al post. Sentiti libero di modificarlo senza chiedermi se trovi qualcosa di meglio.
Krzysztof Szewczyk,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.