Thursday, 28 January 2010

CMD/BAT: Repeat a string multiple times

If you want to get a string repeated multiple times -- you can use this routine. I have realised this as an attempt to implement this optimal algorithm using CMD/BAT only. It accepts three arguments: the name of a variable to store the resulting string, the multiplier (number of time the input string should be repeated), and the input string.

From the point of view of the computational complexity theory this algorithm is optimal (O(n) = log2(n), where n is a string's multiplier) because it duplicates an interim result until n. Let's consider this algorithm closer:
Given:
S - the input string
N - multiplier

// Handle non-empty strings and at least one time
if N <= 0 or S == ''
    return ''
end if

// Initialize -- estimate the length of the string
R = S
K = strlen(R)

// Initialize -- counters
L = 1
N = N - 1

// Repeat for the positive N
while N > 0
    // Remainder -- Find a substring, append to the resulting string and stop the loop
    if N <= L then
        M = N * K
        Q = substr(R, -M)
        R = R + Q
        break
    end if

    // Duplicate a string
    N = N - L
    R = R + R
end while

return R
And there is implementation of this algorithm using CMD/BAT features only. The actual version of this routine can be found by the following link -- libs::strings at cmd-bat.
:: Repeats the INPUT string MULTIPLIER times
::
:: @usage  call :str_repeat NAME MULTIPLIER INPUT
::
:: @param  name
:: @param  number
:: @param  string
:str_repeat
setlocal enabledelayedexpansion

set R=
set N=

set /a N=%~2 2>nul

if not defined N goto str_repeat_break
if %N% leq 0 goto str_repeat_break

set R=%~3

if not defined R goto str_repeat_break

call :str_len K "%R%"

set /a L=1
set /a N=%N%-1

:str_repeat_continue
if %N% leq 0 goto str_repeat_break

if %N% leq %L% (
    set /a M=%N% * %K%
    call :str_repeat_remainder
    set R=%R%!Q!
    goto str_repeat_break
)

set /a N=%N% - %L%
set R=%R%%R%
set /a L*=2
goto str_repeat_continue

:str_repeat_break
endlocal && set %~1=%R%
exit /b 0

:str_repeat_remainder
set Q=!R:~-%M%!
goto :EOF

No comments:

Post a Comment