0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Project Euler vba イミディエイトウィンドウ

Posted at

目標

リンクーProject Euler
・イミディエイトウィンドウ上でPrjectEulerを解く(Q1~Q10)
・VBEのモジュール上にコードを転記しデバッグを行わないように書けるとなお良し(けれど10問やって2勝8敗くらい)
・イミディエイトウィンドウの可能性を探る

ちなみに

・pythonで一度解いている。
・今回はアルゴリズムよりもイミディエイトウィンドウの使い方に重きを置いたため、分からないところは過去の解答を見た。

イミディエイトウィンドウ上で出来ないこと

1行で完結しないIF構文
Forループの中でのIF構文
Exit Forコマンド、 Exit Doコマンド、つまりループの途中で抜けられない
Dim、Redimでの宣言。配列を用意できない?

解答

Proplem1
loopMax = 1000
sum=0: For i = 1 to loopMax - 1: sum=sum+iif(i mod 3 = 0 or i mod 5 = 0,i,0): next i
?sum
Proplem2
f=1:ff=2:loopMax=10000:Max=4000000:sum=2
For i = 3 to loopMax: fi = f + ff: f = ff: ff = fi: isEven = (fi mod 2 = 0):sum = sum + iif(isEven, fi, 0):exitFlag = (fi > max): select Case exitFlag: case True: i = loopMax: end select:next i
?sum
Proplem3
a=600851475143:set primeFactors = new Collection:loopMax = int(sqr(a)):
for i = 2 to loopMax:isFactor = a/i = int(a/i):do while isFactor:primeFactors.add i:a= a/i:isFactor = a/i =int(a/i):loop:next i
For Each pf in primefactors: ?pf : Next: 

Problem3ポイント

・600851475143はLong型(4byte整数)の範囲を超えているので、計算はDouble型で行う
・本当はisFacotr = (a mod i = 0)としたい
・Double型(8byte)の有効数字は2進数で52Bit、10進数で15-16桁くらい
・13桁未満の割り算で余りの有無を確認するのには大丈夫(projectEulerの優しさを感じる)

Proplem4
For i = 100 to 999: For j = 100 to 999: a = cstr(i * j): isPalindrome = True: For k = 1 to len(a) \ 2: Select Case mid(a,k,1) <> mid(a,len(a) + 1 - k, 1): Case True: isPalindrome = False: End Select: Next k: Select Case isPalindrome And i * j > maxPalindromeNumber:Case True: maxPalindromeNumber = i * j:End Select:next j:next i
?maxPalindromeNumber

Problem4ポイント

・maxPalindromeNumberのような長い変数名はVBEの支援機能(自動補完,typo防止の宣言チェック)無しに使ってはいけなかった

Proplem5
Ans = 6: For i = 4 to 20: a = Ans: b = i: Do while b <> 0: c = a mod b: a = b: b = c:Loop: Ans = Ans * i / a:Next i
?ans
Proplem6
Sum = 0:SquaredSum = 0: For i = 1 to 100: Sum = Sum + i: SquaredSum = SquaredSum + i ^ 2:Next i
SumSquared = Sum ^ 2
?SumSquared - SquaredSum

・SumSquaredとSquaredSumという変数名は分かりづらい

Proplem7
set a = excel.Workbooks.Add:msgbox "少し待つ": b = a.worksheets(1).range("A1:B1000000").value
?typename(b)
Variant()
For i = 1 to 1000000:b(i,1) = True:b(i,2) = i:next i
cnt = 0: For i = 2 to 1000000:select Case b(i,1):Case True:cnt = cnt + 1:For j = i*2 to 1000000 step i:b(j,1) =false:next j:end select:select case cnt >= 10001:case true: ans = i:i = 1000000:end select:next i
?ans
a.close 

Problem7ポイント

・Problem10を見据えて高速化の為、エラトステネスの篩のアルゴリズムを使う
・今回はセル配列をコピーすることで配列を用意する。
・10万-100万くらいの配列を用意する方法は他に思いつかなかった。
・コレクションは速度的に不利そう(特にProblem10はpythonの時に処理速度が問題になった)ので採用しなかった。
・2回に一回くらいaとbがEmptyになってる(謎)
・Problem10やってから気づいたけれど2列目が必要ない。

Proplem8
a="7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"
For i = 1 to 1000 - 12: b=1 :for j = 0 to 12: b = b * clng(mid(a,i+j,1)):next j:max = worksheetfunction.Max(b,max):next i
?max
Proplem9
For a = 1 to 333:For b = 1 to 500:c = 1000 - b - a:select case b > a and a^2 + b^2 = c^2 :case true:Ans=array(a,b,c):end select :next b:next a 
e=1:for each d in ans:?d:e=e*d:next:?"ans=" & e
Proplem10
set a = excel.Workbooks.Add:msgbox "少し待つ": b = a.worksheets(1).range("A1:B1000000").value
?typename(b)
Variant()
For i = 1 to 1000000:b(i,1) = True:b(i,2) = i*2+1:next i
sum = 2:For i = 1 to 1000000:select Case b(i,1):Case True:sum = sum +b(i,2):For j = i+b(i,2) to 1000000 step b(i,2):b(j,1) =false:next j:end select:next i
?sum
a.close

Problem10ポイント

・セルの最大値が1048576だったので200万の配列は用意出来なかった。

感想

・今回の挑戦によりいくつか再発見が出来た。
・イミディエイトウィンドウでさらさら書くにはアルゴリズムが頭の中で十分に整理出来ている必要がある。
・その上で文法ミス等なく一発でかけるには更に精進が必要
・Problem7とProblem10はコレクションを使っても現実的な処理時間になりそうな気がする。
・そうだとしたら無理に配列を使わなくても良かったかも

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?