用 batch 解決小問題

個人博客:https://原子核.eu.org/
我在大同一中初中舉辦的所謂 “求知杯” 的競賽里,看到了一道很霸道的題。當時是第 6 題,題目內(nèi)容是:
將集合 {1, 2, ……, 19} 中每兩個互異的數(shù)作乘積,所有這種乘積的和為______.
很明顯這道題可以通過強攻硬算做出來,當時也的確有人這么做,那個人算出來的結(jié)果和電腦算出來的結(jié)果非常相近。于是我開始考慮用編程實現(xiàn)大量計算。學(xué)校電腦沒有 g++,所以我選了最基礎(chǔ)的 batch(批處理)來編寫。
根據(jù)題意,我們需要計算一些乘數(shù)有規(guī)律的乘法,它們分別是:(Bilibili沒有代碼塊,姑且用引用塊低配平替一下)
1×2=
1×3=
……
1×19=
……
2×3=
2×4=
……
2×19=
……
17×18=
18×19=
為了計算方便,我們假設(shè)兩個乘數(shù)分別是變量?t1
,t2
。建立這兩個變量:
set t1=
set t2=
set /a t1=1
set /a t2=%t1%+1
::定義t1=1,t2=2
這樣我們就得到了兩個變量,分別是?t1==1
,t2=2
。
之后,我們還需要一個用于存放每一步的結(jié)果的變量?tmp
?和用于累加結(jié)果的變量?num
。建立這兩個變量:
set num=
set /a num=0?
set tmp=0
我們需要兩個乘數(shù)依次滾動,在將每個【第一個乘數(shù)】所對應(yīng)的【第二個乘數(shù)】遍歷。為此我們需要兩層循環(huán)。小循環(huán)是【第二個乘數(shù)】的循環(huán),大循環(huán)是【第一個乘數(shù)】的循環(huán)。每個【第一個乘數(shù)】中,都需要將所有的【第二個乘數(shù)】的可能性都算完。由于在 batch 中循環(huán)的寫法太過于流氓,在不追求運行速度的情況下,我更愿意使用標簽和跳轉(zhuǎn)來實現(xiàn)循環(huán)。
具體寫法如下:
:loop
::內(nèi)容
goto loop
:bigloop
::內(nèi)容
goto loop
::對沒有寫錯,這里大循環(huán)結(jié)束后要進入小循環(huán)
而且,如你所見,這種寫法也不依賴于循環(huán)之間的包含關(guān)系,比較靈活,隨心所欲。
接著我們開始寫小循環(huán)。
在小循環(huán)中,我們要實現(xiàn)以下操作:
用已經(jīng)定義好的?
t1
?和?t2
?來計算乘積,寫入?tmp
;將?
tmp
?作為加數(shù)累加到?num
?中;判斷:若?
t2==19
,則跳轉(zhuǎn)到大循環(huán)進行新的【第一個乘數(shù)】;否則計算同一個【第一個乘數(shù)】的下一個【第二個乘數(shù)】。
即:
:loop
::小循環(huán)
set /a tmp=%t1%*%t2%?
::計算乘積
set /a num=%num%+%tmp%?
::寫入乘積
if /i %t2%==19 goto bigloop?
::若t2==19,跳轉(zhuǎn)大循環(huán)(t1自增,t2原始值自增)
set /a t2=%t2%+1?
::否則只有t2自增
goto loop
在大循環(huán)里,我們需要實現(xiàn):
t1
?自增;將?
t2
?賦值為?t1
?后的第一個互異數(shù);判斷窮舉是否完成。
即:
:bigloop
::大循環(huán)
set /a t1=%t1%+1
::t1自增
set /a t2=%t1%+1
::t1后第一個互異數(shù)賦值t2
if /i %t2%==20 if /i %t1%==19 goto result
::若窮舉完成則輸出結(jié)果
goto loop
::否則進入小循環(huán)
最后寫?result
?標簽用于輸出結(jié)果:
:result
echo 計算結(jié)果:%num%
整體框架出來以后,程序全文進行一些優(yōu)化,加上題目和日志輸出,加上結(jié)果暫留處理。完整代碼如下:
@echo off
title 求知杯第6題
color f0
cls
echo 題目:將集合{1,2,……,19}中每兩個互異的數(shù)作乘積,所有這種乘積的和為_.
echo 按下任意鍵開始計算
pause >nul
echo 題目:將集合{1,2,……,19}中每兩個互異的數(shù)作乘積,所有這種乘積的和為_. >求知杯第6題.txt
::刪除運行記錄
set num=
set /a num=0
set t1=
set t2=
set /a t1=1
set tmp=
set /a t2=%t1%+1
::定義t1=1,t2=2
:loop
::小循環(huán)
set /a tmp=%t1%*%t2%
::計算乘積
set /a num=%num%+%tmp%
::寫入乘積
set tmpecho=
set /a tmpecho=%num%-%tmp%
echo 計算過程:%tmpecho%+%t1%×%t2%=%num%
echo 計算過程:%tmpecho%+%t1%×%t2%=%num% >>求知杯第6題.txt
if /i %t2%==19 goto bigloop
::若t2==19,跳轉(zhuǎn)大循環(huán)(t1自增,t2原始值自增)
set /a t2=%t2%+1
::否則只有t2自增
goto loop
::回到小循環(huán)
:bigloop
::大循環(huán)
set /a t1=%t1%+1
::t1自增
set /a t2=%t1%+1
::t1后第一個互異數(shù)賦值t2
if /i %t2%==20 if /i %t1%==19 goto result
::若窮舉完成則輸出結(jié)果
goto loop
::否則進入小循環(huán)
:result
echo 計算結(jié)果:%num%
echo 計算結(jié)果:%num% >>求知杯第6題.txt
echo 按下任意鍵退出程序
pause >nul