Reputation: 54
(sorry that everything is in code form, stack overflow wouldn't let me submit for reason)
I have recently been interested in computer sorting, and attempted to write a simple batch numerical sorter. It uses very basic math and is extremely inefficient, but was mostly a learning experience. The program almost works with certain number sets. I am relatively new to batch, so as far as I can tell, there is nothing specifically wrong with my sorting and checking, yet I've experiencing quite a few anomalies after sorts. In a set of 10 values, it sorts perfectly, except the largest number ends up being put first. And in larger sets of numbers, for example:
> Values:10
>
> Random Maximum:10
>
> UNSORTED: 8 5 0 0 5 4 7 1 5 1
>
> SORTED: 8 0 1 1 4 5 5 5 7
The following are the anomalies I have so far experienced while debugging:
Highest number put first
Numbers of lower places(tens, hundreds, etc) placed randomly in sets with a majority of numbers with a higher case
Some numbers removed from unsorted-sorted
Sorting restarts at various points in some cases in sorted.txt
Likely many more to be discovered
Here is my batch script so far:
@echo off
color b
title sorting
if exist sortedlist.txt del sortedlist.txt
if exist unsortedlist.txt del unsortedlist.txt
if exist log.txt del log.txt
setlocal enabledelayedexpansion
set ar=0
set num=0
set check=0
set checknum=0
set checks=0
set /P totalnumber="Values:"
set /P randmax="Max Random Value:"
cls
::set totalnumber=200
::set randmax=500
echo %date% : %time%
echo PROGRAM INITIATED
echo VALUES:%totalnumber%
echo RANDMAX:%randmax%
echo %date% : %time% >> log.txt
echo PROGRAM INITIATED >> log.txt
echo VALUES:%totalnumber% >> log.txt
echo RANDMAX:%randmax% >> log.txt
:array
if %num% LSS %totalnumber% (
set /A a[%num%]=%random% %% %randmax%
set /A num=%num%+1
goto array
)
if %num% EQU %totalnumber% (
echo %DATE%:%TIME%
echo VALUE GEN COMPLETE
echo %date%:%time% >> log.txt
echo VALUE GEN COMPLETE >> log.txt
goto echo1
)
:echo1
for /F "tokens=2 delims==" %%s in ('set a[') do echo %%s
for /F "tokens=2 delims==" %%s in ('set a[') do echo %%s >> unsortedlist.txt
echo sort initialized
goto sort
)
:sort
set sorts=0
set n=0
:sortloop
set /A m=%n%+1
if %n% EQU %totalnumber% (
echo %date% : %time%
echo SORT COMPLETED
echo SORTS : %sorts%
echo %date% : %time% >> log.txt
echo SORT COMPLETED >> log.txt
echo SORTS : %sorts% >> log.txt
goto check
)
if !a[%n%]! GTR !a[%m%]! (
set hold=!a[%m%]!
set a[%m%]=!a[%n%]!
set a[%n%]=%hold%
set /A n=%n%+1
set /A sorts=%sorts%+1
goto sortloop
)
if !a[%n%]! LSS !a[%m%]! (
set /A n=%n%+1
goto sortloop
)
if !a[%n%]! EQU !a[%m%]! (
set /A n=%n%+1
goto sortloop
)
pause
:check
set check=0
set checknum=0
set checks=0
:checkloop
set /A checknumplus=%checknum%+1
if %check% EQU %totalnumber% (
goto complete
)
if %checknum% EQU %totalnumber% (
set /A checks=%checks%+1
echo %date% : %time%
echo CORRECT PAIRS : %check%
echo CHECKS : %checks%
echo %date% : %time% >> log.txt
echo CORRECT PAIRS : %check% >> log.txt
echo CHECKS : %checks% >> log.txt
goto sort
)
if !a[%checknum%]! LSS !a[%checknumplus%]! (
set /A check=%check%+1
set /A checknum=%checknum%+1
goto checkloop
)
if !a[%checknum%]! GTR !a[%checknumplus%]! (
set /A checknum=%checknum%+1
goto checkloop
)
if !a[%checknum%]! EQU !a[%checknumplus%]! (
set /A check=%check%+1
set /A checknum=%checknum%+1
goto checkloop
)
pause
:complete
set a[%totalnumber%+1]=%a[0]%
set %a[0]%=0
echo %date% : %time%
echo PROGRAM COMPLETE
echo %date% : %time% >> log.txt
echo PROGRAM COMPLETE >> log.txt
for /F "tokens=2 delims==" %%s in ('set a[') do echo %%s
for /F "tokens=2 delims==" %%s in ('set a[') do echo %%s >> sortedlist.txt
Any help cleaning up code, adding code, or resolving any of the issues I have will be greatly appreciated.
Upvotes: 0
Views: 82
Reputation:
AS aacini mentioned set will order environment vars alphabetically, to have the numbers sorted stuff them with leading zeroes and put the random numbers into the var name, to be able to store the same number multiple times append the index.
EDIT Modified the batch to output lists to unsorted.txt
and sorted.txt
@echo off
setlocal EnableDelayedExpansion
set /P "totalNumber=Number of Values:"
set /P "randMax=Max Random Value:"
echo %date% : %time% PROGRAM INITIATED VALUES:%totalNumber% randMax:%randMax%
(echo %date% : %time% PROGRAM INITIATED VALUES:%totalNumber% randMax:%randMax%) > log.txt
:array
(for /L %%i in (1,1,%totalNumber%) do (
set /A "Rno=!random! %% randMax + 10*randMax"
Set a_!Rno!_%%i=0
Echo:!Rno!
))> unsorted.txt
echo/
echo %date% : %time% Generated %totalNumber% numbers
(echo %date% : %time% Generated %totalNumber% numbers) >> log.txt
(for /F "tokens=2 delims=_" %%i in ('set a_') do (
Set /A No=%%i - 10*randMax,Diff=No-Prev,Prev=No
Echo:!No!
))> sorted.txt
:complete
echo %date% : %time% PROGRAM COMPLETE
(echo %date% : %time% PROGRAM COMPLETE) >> log.txt
Upvotes: 0
Reputation: 67216
This question in "interesting". Independently of your low knowledge in Batch files, you have not asked a single definite question about the posted code! You basically have invited us to do whatever we want with it, so that is what I did. Also, it is important to note that the supposed "output example" show in the question have no relation with the posted code...
EDIT: The method used to show the list of numbers in a single line use a variable, so the maximum number of results is limited by the maximum variable length. For example, with numbers of 4 digits each the list can contain a maximum of 1637 numbers that, IMHO, was enough for a "simple batch numerical sorter" program.
I modified the method used to show the results, so it now supports 10,000 random numbers or more. However, you should note that this sorting method is slow, so I suggest to insert an echo
command in the sortLoop in order to know that the program is still running.
@echo off
setlocal EnableDelayedExpansion
color b
title sorting
set /P "totalNumber=Values:"
set /P "randMax=Max Random Value:"
echo %date% : %time%
echo PROGRAM INITIATED
echo VALUES:%totalNumber%
echo randMax:%randMax%
(
echo %date% : %time%
echo PROGRAM INITIATED
echo VALUES:%totalNumber%
echo randMax:%randMax%
) > log.txt
:array
for /L %%i in (1,1,%totalNumber%) do set /A a[%%i]=!random! %% randMax
echo %DATE%:%TIME%
echo VALUE GEN COMPLETE
(
echo %date%:%time%
echo VALUE GEN COMPLETE
) >> log.txt
echo/
< NUL (
set /P "=UNSORTED: "
for /L %%i in (1,1,%totalNumber%) do set /P "=!a[%%i]! "
)
echo/
echo/
echo sort initialized
set "sorts=0"
:sortLoop
set "hold="
for /L %%m in (2,1,%totalNumber%) do (
set /A n=%%m-1
for %%n in (!n!) do if !a[%%n]! GTR !a[%%m]! (
set /A hold=a[%%m], a[%%m]=a[%%n], a[%%n]=hold, sorts+=1
)
)
REM ECHO Sorts: %sorts%
if defined hold goto sortLoop
echo %date% : %time%
echo SORT COMPLETED
echo SORTS : %sorts%
(
echo %date% : %time%
echo SORT COMPLETED
echo SORTS : %sorts%
) >> log.txt
:complete
echo %date% : %time%
echo PROGRAM COMPLETE
(
echo %date% : %time%
echo PROGRAM COMPLETE
) >> log.txt
echo/
< NUL (
set /P "=SORTED: "
for /L %%i in (1,1,%totalNumber%) do set /P "=!a[%%i]! "
)
echo/
EDIT: New sorting method added
I originally thought that this program represents to you "mostly a learning experience in computer sorting". However, if you are interested in create two files with random numbers named sorted.txt
and unsorted.txt
in an efficient way, you may use this code instead:
@echo off
setlocal EnableDelayedExpansion
set /P "totalNumber=Values:"
set /P "randMax=Max Random Value:"
echo/
set /P "=UNSORTED: " < NUL
< NUL (for /L %%i in (1,1,%totalNumber%) do (
set /A a=!random! %% randMax
set /P "=!a! " > CON
set "a= !a!"
echo !a:~-5!
)) > unsorted.txt
echo/
sort unsorted.txt /O sorted.txt
echo/
< NUL (
set /P "=SORTED: "
for /F %%a in (sorted.txt) do set /P "=%%a "
)
echo/
Remember that the maximum random number is 32767, but the amount of numbers have no limit.
Upvotes: 1