Авто BATCH гольфист

25

Я люблю BATCH, несмотря на шокирующее отсутствие функциональных команд, несмотря на то, что он не поддерживает целочисленные значения. Зачем? Потому что это работает:

SET var=SET
%var% i=0

Это оценило бы:

SET var=SET
SET i=0

Фантастика, не правда ли? Я использовал эту технику в программе BATCH раньше, потому что она экономит байты!

Ваша задача, если вы ее примете, заключаться в том, чтобы таким образом «разыгрывать» программы BATCH. Вы должны уменьшить размер байта входной программы BATCH, включив SETоператоры, которые будут оцениваться для отдельных частей программы, и никоим образом не изменять программу. (Это запрещает, скажем, переименование имени переменной во что-то более короткое. Имейте в виду, что BATCH, кроме переменных, нечувствителен к регистру.) Ваша оценка рассчитывается следующим образом:

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

Я оставляю за собой право добавлять больше тестовых случаев, чтобы не поощрять работу по оптимизации программы для тестовых случаев.

Ради этой проблемы, ваши SETзаявления не могут содержать управляющие символы ( |, <, >, %) или переносы строк. Вы не можете изменять код, кроме как для перемещения частей кода внутри оператора set. (То есть, вы не можете удалить ненужные пробелы, замените EQUс ==, и т.д.) Будем считать , что линии заканчиваются \n.

Контрольные примеры

Каждый тестовый пример находится в отдельном кодовом блоке, и каждый тестовый пример является автономным, что означает, что вы должны играть только в предположении того, что в нем содержится. (То есть, если вы участвуете SET d=SETв одной программе, эта инструкция не будет автоматически передана какой-либо другой программе). Результаты каждого примера можно найти после каждого теста. Существует грань между тестами.

@ECHO OFF
Приращение SET = 10
: петля
IF% приращение% EQU 0 GOTO конец
ECHO% прирост%
SET /% прироста% - = 1
GOTO loop
:конец
ВЫХОД

@ECHO OFF
SET / p INPUT = Введите здесь ввод:
SET R =% 1
ECHO Последний символ ввода здесь:% R: ~ -1%

@ECHO OFF
Приращение SET = 10
: е
GOTO f
ЭХО Ф
: е
GOTO г
ЭХО г
:г
Пойдем ч
ЭХО ч
:час
GOTO я
ЭХО я
:я
GOTO j
ЭХО j
: J
ЕСЛИ 3 == 4 (ЭХО 4), ДРУГОЕ (ЭХО 5)
ЕСЛИ 5 == 3 (ПОЛУЧИТЕ l) Иначе (ПОЛУЧИТЕ k)
: к
ЭХО Готово.
ЭХО ВЫПУСК !!
ВЫХОД
: л
GOTO г

ЭХО Привет, Привет, Привет, привет, привет, Привет, Привет! Привет, привет, привет !, Лелло.

Пример выходов:

@ECHO OFF
Приращение SET = 10
: петля
IF% приращение% EQU 0 GOTO конец
ECHO% прирост%
SET /% прироста% - = 1
GOTO loop
:конец
ВЫХОД
(0 байтов сохранено)

@ECHO OFF
SET% i% = введите здесь:
SET / p INPUT = Введите% i%
SET R =% 1
ECHO Последний символ% i %% R: ~ -1%
(Получено 3 байта)

@ECHO OFF
Приращение SET = 10
SET g = GOTO 
SET e = ECHO 
: е
% Г% е
% Е% е
: е
% Г% г
%например
:г
% Г% ч
% Е% ч
:час
% Г% я
% Е% я
:я
% Г% J
% Е% J
: J
IF 3 == 4 (% e% 4) ELSE (% e% 5)
ЕСЛИ 5 == 3 (% g% l) ИЛИ (% g% k)
: к
% Е% Готово.
% e% BATCH OUT !!
ВЫХОД
: л
% Г% г
(10 символов сохранены)

SET% h% = ello,
ЭХО H% h% H% h% H% h% h% h% h% h% H% h% Hello !, h% h% ello !, Lello.
(1 символ сохранен)

Конор О'Брайен
источник
2
Сокращение партии для удовольствия и прибыли!
Алекс Карлсен
Вам нужно больше спецификаций. Конечно, AAA %increment%set a=increment¶AAA %%a%%неверен, и AAA %1 BBB %2set a= BBB ¶AAA %1%a%%2действителен. (iirc) Так что вам нужно формализовать это. ( представляет новую
строку
Нужно ли обрабатывать код, для которого включено отложенное расширение, экранирование знака процента или многострочные операторы / if? Согласно последнему тестовому примеру (который производит дополнительный выход , как эхо не включено , и нет никакого @до SET) является посторонним выход приемлемым из golfed программы?
Οurous
1
Tcl снова и снова
Ven
1
несмотря даже из-за ?
Адам

Ответы:

4

Java 8, Java 10 , 3884 799/795 программа + 484 вывод = 4368 1283/1279 всего

Есть два ограничения этого кода:

  • Предполагается, что переменные от A до Z свободны. (верхний регистр)
  • Предполагается, что существует не более 27 замен.
  • Да, и поскольку Scanner не совсем обрезает его, пустой ввод сбрасывает трассировку стека.

Но эй - есть профессионал!

  • Выводит лучший код. Всегда.

Код удается выполнить лучше, чем примеры, предоставленные автором задачи.

Эта версия для гольфа была сделана Кевином .

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

Попробуйте онлайн!

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

Попробуйте онлайн! ,

Оригинальная версия

Это вовсе не игра в гольф, я просто хотел повеселиться, чтобы не страдать. Если вы, дорогой читатель, хотели бы ответить на этот вопрос, пожалуйста, сделайте это.

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

}

Пример вывода:

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

Попробуйте онлайн!

Кшиштоф Шевчик
источник
Я думаю, что все это "java.util." повторяется. Вы можете захотеть упростить свой код до import java.util.*.
Я думал, что импорт JDK не в счет?
Марк Иеронимус
@A_ Вы можете изменить мой ответ по своему усмотрению (если он не действителен и не поддерживает дух)
Кшиштоф Шевчик,
1
« Если вы, дорогой читатель, хотели бы гольф этого ответа, пожалуйста , сделайте это. » 799 байт в Java 8 или 795 байт в Java 10+ . Пожалуйста. :) Определенно можно играть в гольф еще немного, но это будет делать сейчас.
Кевин Круйссен
2
@KevinCruijssen Спасибо за вклад. Я добавил вашу версию в пост. Не стесняйтесь редактировать его, не спрашивая меня, если вы найдете что-то лучше.
Кшиштоф Шевчик