Page 1 of 1

Manually compressing batch files

Posted: 08 Aug 2017 22:18
by SirJosh3917
Here, look at this.

Code: Select all

@echo off
set /a iteration=0
:S
echo                     #
echo                   #   #
echo                 #       #
echo               #           #
echo             #     DISCO!    #
echo               #           #
echo                 #       #
echo                   #   #
echo                     #
call :col %iteration%
set /a iteration=%iteration% + 1
cls
if %iteration% == 6 set iteration=0
goto s
:col
if %~1 == 0 color a
if %~1 == 1 color b
if %~1 == 2 color c
if %~1 == 3 color d
if %~1 == 4 color e
if %~1 == 5 color f
ping 127.0.0.1 -n 1 >nul
exit /b 0

It's simple, easy to read, and easy to understand what it's doing. However, it comes in at around 593 bytes!

My goal is to ask how you would potentially compress it down as much as possible.
Please compress the above batch file, and then share what you did to compress it down as much as possible, and the byte size. File must use \r\n as newlines, I'm considering removing \r as cheating.

Here's my take on it, and an example as to what your posts should be:

Code: Select all

@echo off
set "s= set/a i="&set n=^&echo&set "e= == "&set "c= color "&set "a=     "&set "p=%a%   "
%s%0
:s
echo%p%%a%   #%n%%p%%a% #   #%n%%p%    #%a%  #%n%%p%  #%a%%a% #%n%%p%#%a%DISCO!    #%n%%p%  #%a%%a% #%n%%p%    #  %a%#%n%%p%%a% #   #%n%%p%%a%   #
if %i%%e%0%c%a
if %i%%e%1%c%b
if %i%%e%2%c%c
if %i%%e%3%c%d
if %i%%e%4%c%e
if %i%%e%5%c%f
ping ::1 -n 1 >nul&%s%%i%+1
cls&if %i%%e%6%s%0
goto s


As you can see, I've declared at the top of the file, a large chunk of sets. These are to set variables to save on space, e.g. replacing 13 charecter spaces with 3 byte variables.

I've replaced the condition if statements, %e% to represent ' == ' and %c% to represent ' color '. This assists on saving some bytes. I set %s% to ' set/a i=' to assist with the last conditional if statement, as well as any other instances where setting the iteration would be useful. 'iteration' has been shortened down to 'i', and all the 'echo's are shoved into one line. I removed the call :col statement, however by doing that that increases the speed of the application, making the lights flash faster then needed. I suppose you could still have a :call though.

I don't remember what else I did though, but in total, it went from 593 bytes down to 410! I was almost able to get it down to 406 but the application didn't work at that point.
------------

So does anybody wanna try take on this 'challenge'? I'd like to see how you'd approach this problem.

Re: Manually compressing batch files

Posted: 09 Aug 2017 03:28
by mcnd
2017/08/09 As a first try

Code: Select all

@setlocal enabledelayedexpansion&set n=#^

&set c=fedcba&set f=&for /l %%a in (1 1 21) do @set f=!f! &set %%a=!f!
:s
@cls&echo!21!!n!!18!#!3!!n!!16!#!7!!n!!14!#!11!!n!!12!#!5!DISCO^^!!4!!n!!14!#!11!!n!!16!#!7!!n!!18!#!3!!n!!20!!n!&color !c:~-1!&set c=!c:~-1!!c:~0,-1!&>nul ping "" -n 1&goto:s


296 bytes without the ending \r\n in the last line (not needed)

  • As much commands as possible concatenated with &
  • All the space padding has been replaced with variables initialized to the needed lengths (more variables than needed) inside a for /l loop
  • All the line jumps in output changed to a variable containing the closing hash of each diamond's line and a line feed
  • Color handling changed to only a string. The values/characters are simply rotated

2017/08/10 - Second iteration, just a small reduction in size to 288 bytes

Code: Select all

@setlocal enabledelayedexpansion&set n=^

&set c=abcdef&set f=&for /l %%a in (1 1 21) do @set f=!f! &set %%a=!f!#
:s
@cls&echo!21!!n!!18!!3!!n!!16!!7!!n!!14!!11!!n!!12!     DISCO^^!!4!!n!!14!!11!!n!!16!!7!!n!!18!!3!!n!!20!!n!&color !c:~,1!&set c=!c:~1!!c:~,1!&>nul ping "" -n 1&goto:s


  • Changed hash position to end of padding variables and removed from echo command
  • Changed rotation code to omit non needed initial 0 in substring operations

Re: Manually compressing batch files

Posted: 10 Aug 2017 14:01
by pieh-ejdsch
Good evening.

The batches are not exactly good to read, if the variable names are badly interpreted.
A variable name should clearly describe what is generated or what is used.
In the sense of extremely short batches, the readability will always suffer.
Here is also my bad example with one-letter variable names, and crunched set / a, as well as setting the parenthesis directly at the following command.
I wanted to insert the echo command into a variable E but it does not use the readability four ... five characters against a non-tagging variable exchange where eh would be saved only one byte per echo.
I do not want to sell the code frankly. (351 Bytes)

Code: Select all

@echo off
setlocal
set "#=                    "
set "C=0123456789ABCDEF"
set for=For /l %%a in (-15 2 -15)do echo  !#:~,%%a!#!#:~%%a! !#:~%%a!#
setlocal enabledelayedexpansion
:print
set/aR=!random! %%16
color !C:~%R%,1!
(cls
echo !#!  #
%for:-15 =-1 -%
echo !#:~,-16!#!#:~-17,-3!Disco^^!!#:~-15!#
%for: -15= -1%
echo !#!  #
goto print)


A program should be written in such a way that redundancy is as little as possible. If this happens the code is readable and brief. Otherwise it was not considered correctly when writing the code.
It is also useful to set functions in variables, to use a variable when calling multiple times.

Over time, I've learned to write batches so that I can understand and maintain them after half a year - as well as others can use it - no matter how old the script is. I always have to think of Dave his acurately written batches, which are really exemplary for the programming.

PS
In this batch, the text does not have to be recreated every time, only the color is changed.

Phil

Re: Manually compressing batch files

Posted: 11 Aug 2017 09:12
by Aacini
This is my "standard" (readable) version of this code (291 bytes):

Code: Select all

%1cmd/v:on/q/c "%~F0" ::
set s=                     # &cls
for /L %%i in (1,2,7) do echo !s:~%%i,-1!!s:~-%%i,-2! !s:~-%%i!
echo !s:~9!    DISCO^^^!    #
for /L %%i in (7,-2,1) do echo !s:~%%i,-1!!s:~-%%i,-2! !s:~-%%i!
:s
for %%c in (a b c d e f) do>nul ping "" -n 1&color %%c
goto s

The only strange trick in this code is the first line that allows to replace both "setlocal EnableDelayedExpansion" and "@echo off" lines by a shorter one...

Antonio

Re: Manually compressing batch files

Posted: 16 Aug 2017 18:11
by thefeduke
Antonio, a first line of

Code: Select all

%1cmd/v/q/c"%~F0" ::
worked for me in four less bytes, making it 287 bytes.

John A

Re: Manually compressing batch files

Posted: 18 Aug 2017 03:11
by mcnd
Aacini wrote:The only strange trick...


Really nice trick 8).

Using that, following the basic compression idea of removing repeating sequences, most of the repeating elements inside the code can be move to the arguments for the second cmd instance

Code: Select all

%1@cmd/q/e/v/c"%~f0" : set .18.3.n .16.7.n .14.11.n
%2 c=abcdef&%2 e=.21.n%3%4%5.12.f:~-5.x.4.n%5%4%3.20.&%2 x=DISCO^^!&%2 n=^

&%2 f=&for /l %%a in (0 1 21)do %2 %%a=!f!#&%2 f= !f!
cls&echo%e:.=!!%
:s
color !c:~,1!&%2 c=!c:~1!!c:~,1!&>nul ping "" -n 1&goto:s


Not very "readable", but now it has 265 bytes