Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
81
Task/Happy-numbers/Batch-File/happy-numbers.bat
Normal file
81
Task/Happy-numbers/Batch-File/happy-numbers.bat
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
@echo off
|
||||
setlocal enableDelayedExpansion
|
||||
::Define a list with 10 terms as a convenience for defining a loop
|
||||
set "L10=0 1 2 3 4 5 6 7 8 9"
|
||||
shift /1 & goto %1
|
||||
exit /b
|
||||
|
||||
|
||||
:list min count
|
||||
:: This routine prints all happy numbers > min (arg1)
|
||||
:: until it finds count (arg2) happy numbers.
|
||||
set /a "n=%~1, cnt=%~2"
|
||||
call :listInternal
|
||||
exit /b
|
||||
|
||||
|
||||
:test min [max]
|
||||
:: This routine sequentially tests numbers between min (arg1) and max (arg2)
|
||||
:: to see if they are happy. If max is not specified then it defaults to min.
|
||||
set /a "min=%~1"
|
||||
if "%~2" neq "" (set /a "max=%~2") else set max=%min%
|
||||
::The FOR /L loop does not detect integer overflow, so must protect against
|
||||
::an infinite loop when max=0x7FFFFFFFF
|
||||
set end=%max%
|
||||
if %end% equ 2147483647 set /a end-=1
|
||||
for /l %%N in (%min% 1 %end%) do (
|
||||
call :testInternal %%N && (echo %%N is happy :^)) || echo %%N is sad :(
|
||||
)
|
||||
if %end% neq %max% call :testInternal %max% && (echo %max% is happy :^)) || echo %max% is sad :(
|
||||
exit /b
|
||||
|
||||
|
||||
:listInternal
|
||||
:: This loop sequentially tests each number >= n. The loop conditionally
|
||||
:: breaks within the body once cnt happy numbers have been found, or if
|
||||
:: the max integer value is reached. Performance is improved by using a
|
||||
:: FOR loop to perform most of the looping, with a GOTO only needed once
|
||||
:: per 100 iterations.
|
||||
for %%. in (
|
||||
%L10% %L10% %L10% %L10% %L10% %L10% %L10% %L10% %L10% %L10%
|
||||
) do (
|
||||
call :testInternal !n! && (
|
||||
echo !n!
|
||||
set /a cnt-=1
|
||||
if !cnt! leq 0 exit /b 0
|
||||
)
|
||||
if !n! equ 2147483647 (
|
||||
>&2 echo ERROR: Maximum integer value reached
|
||||
exit /b 1
|
||||
)
|
||||
set /a n+=1
|
||||
)
|
||||
goto :listInternal
|
||||
|
||||
|
||||
:testInternal n
|
||||
:: This routine loops until the sum of squared digits converges on 1 (happy)
|
||||
:: or it detects a cycle (sad). It exits with errorlevel 0 for happy and 1 for sad.
|
||||
:: Performance is improved by using a FOR loop for the looping instead of a GOTO.
|
||||
:: Numbers less than 1000 never neeed more than 20 iterations, and any number
|
||||
:: with 4 or more digits shrinks by at least one digit each iteration.
|
||||
:: Since Windows batch can't handle more than 10 digits, allowance for 27
|
||||
:: iterations is enough, and 30 is more than adequate.
|
||||
setlocal
|
||||
set n=%1
|
||||
for %%. in (%L10% %L10% %L10%) do (
|
||||
if !n!==1 exit /b 0
|
||||
%= Only numbers < 1000 can cycle =%
|
||||
if !n! lss 1000 (
|
||||
if defined t.!n! exit /b 1
|
||||
set t.!n!=1
|
||||
)
|
||||
%= Sum the squared digits =%
|
||||
%= Batch can't handle numbers greater than 10 digits so we can use =%
|
||||
%= a constrained FOR loop and avoid a slow goto =%
|
||||
set sum=0
|
||||
for /l %%N in (1 1 10) do (
|
||||
if !n! gtr 0 set /a "sum+=(n%%10)*(n%%10), n/=10"
|
||||
)
|
||||
set /a n=sum
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue