t.anonymous
t.anonymous

Reputation: 54

Sorting Program getting weird anomalies

(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:

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

Answers (2)

user6811411
user6811411

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

Aacini
Aacini

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

Related Questions