Java 8, Java 10, 3884 799/795 program + 484 output = 4368 1283/1279 total
There are two limitations of this code:
- It assumes that variables from A to Z are free. (uppercase)
- It assumes that there are no more than 27 substitutions.
- Oh, and because Scanner doesn't quite cut it, empty input dumps out stacktrace.
But hey - there is a pro!
- Outputs best code. Always.
The code manages to perform better than examples provided by challenge author.
This golfed version has been made by 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;}
Try it 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;}
Try it online!.
Original version
It's not golfed at all, I just wanted to have some fun, not to suffer. If you, dear reader, would like to golf this answer, please do it.
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); } }
Example 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
Try it online!
AAA %increment%→set a=increment¶AAA %%a%%is invalid, andAAA %1 BBB %2→set a= BBB ¶AAA %1%a%%2is valid. (iirc) So you need to formalize it. (¶represents a newline) \$\endgroup\$@before theSET) is extraneous output acceptable from the golfed program? \$\endgroup\$