Project Euler (74 ã 80) ãã¿ã´ã©ã¹æ°ãäºè§æ°å®çããããã¸ã«ã«ã½ã¼ããªã©
ä»æ¥ã¯80ã¾ã§ããã®ã¨ãããæ°å¦ã使ãåé¡ã沢山ã§é¢ç½ãã§ããã
ãã¿ã´ã©ã¹æ°ã¨ããã³ããæ¨ Problem75
ç°¡åã«ã¯
1,500,000以ä¸ã®Lã§
a^2 + b^2 = c^2 ã㤠a + b + c = L
ãæºããèªç¶æ°a,b,cã®çµãã¡ããã©ä¸çµã¨ãªããããªLã®åæ°ãæ±ãã
ã¨ããåé¡ã§ããa^2 + b^2 = c^2ãæºããèªç¶æ°(a,b,c)ããã¿ã´ã©ã¹æ°ã¨è¨ãã¾ããã¾ãããã®æ¹ç¨å¼ããã¿ã´ã©ã¹æ¹ç¨å¼ã¨è¨ãã¾ããããã«æ¹ç¨å¼ãªã©ã¨åãããã£ãªãã¡ã³ãã¹æ¹ç¨å¼ã®ä¸ç¨®ã§ãã
(a,b,c)ããã¿ã´ã©ã¹æ°ã®ækãèªç¶æ°ã¨ãã¦(ka,kb,kc)ããã¿ã´ã©ã¹æ°ãªã®ã§ã(a,b,c)ãäºãã«ç´ ã§ãããã®ã«ã¤ãã¦èããã°è¯ãã§ãããããåå§ãã¿ã´ã©ã¹æ°ã¨ããã¾ãã
ãã¦ãåå§ãã¿ã´ã©ã¹æ°ã¯ãã®çææ¹æ³ãç¥ããã¦ãã¦
m > n ã㤠m,nã¯äºãã«ç´ ã㤠çæ¹ãå¶æ°ã®ã¨ã(m^2-n^2,2mn,m^2+n^2)ã¯åå§ãã¿ã´ã©ã¹æ°
ã¨ãªãã¾ãã
ãããåæããæã«åä»ãªã®ããm,nãäºãã«ç´ ãã®æ¡ä»¶ã§ãããããã§Problem 71, 73ã§ã使ã£ãブロコット木ãå½¹ã«ç«ã¡ã¾ãã
ããã³ããæ¨ã使ãã¨æ¢ç´åæ°ãé«éã«åæããäºãã§ããããã§ããããã®ã¨ãååã¨åæ¯ãå¿
ãäºãã«ç´ ã«ãªã£ã¦ããæ§è³ªã使ãã¾ãã
L = 1500000 $count = {} # 解ã®åæ° def dfs(la,lb,ra,rb) # naã¨nbã¯äºãã«ç´ na = la + ra nb = lb + rb c = 0 if (na+nb)%2 == 1 l = 2*(na+nb)*nb return if l > L # åå§ãã¿ã´ã©ã¹æ°ã®åæ°ãã«ã¦ã³ã (1..L/l).each do |k| $count[k*l] || $count[k*l] = 0 $count[k*l] += 1 end end dfs(la,lb,na,nb) dfs(na,nb,ra,rb) end dfs(0,1,1,1) count = 0 $count.each_value {|v| count += 1 if v == 1} puts count
å®è¡æéã¯1.11sã§ããã
æ´æ°åå²ãäºè§æ°å®ç(Problem 76, 77, 78)
ãã®3åã¯整数分割ã«é¢ããåé¡ã§ããæ´æ°åå²ã¨ã¯æ´æ°nãèªç¶æ°ã®åã§è¡¨ãå ´åã®æ°ã§ããä¾ãã°n=5ã®å ´åã¯ä»¥ä¸ã®7éããããã¾ãã
5
4 + 1
3 + 2
3 + 1 + 1
2 + 2 + 1
2 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1
ã¨ã©ã®ã¤ã¾ãããã¯ã硬貨æ¯æãåé¡ã¨åãã§ãã5åã1åçã2åçã3åçã4åçã5åçã®çµã¿åããã§æ¯æãæ¹æ³ã¯7éãã¨ãã訳ã§ããå¾ã£ã¦以前書いた方法ã¨å ¨ãåãã¢ã«ã´ãªãºã ã§è¨ç®ã§ãã¾ãã
Problem 76: 100ã2ã¤ä»¥ä¸ã®èªç¶æ°ã®åã§è¡¨ãæ¹æ³ã®æ°ãæ±ãã
100åã1,2,...,99åçã§è¡¨ãæ¹æ³ãçãã§ãããã£ã¦ç¡¬è²¨æ¯æãåé¡ã¨åã漸åå¼ã使ãã¨ä»¥ä¸ã®ããã«ãªãã¾ããa[k][n]ã¯nãk以ä¸ã®åã§è¡¨ãæ¹æ³ã®æ°ã§ãã
class Array def [](i) i < 0 ? 0 : at(i) end end N = 100 a = (0..N).collect { [] } (0..N).each do |n| t = a[1][n] = a[1][n-1] + ((n == 0) ? 1 : 0) (2..N).each do |k| t = a[k][n] = a[k][n-k] + t end end puts a[99][100]
å®è¡æéã¯0.01sãããã§ãã
Problem 77: ç´ æ°ã®ã¿ã®åã§è¡¨ãæ¹æ³ã5000éã以ä¸ã¨ãªãæåã®æ°ã¯ä½ãï¼
2,3,5,7,11,13,..å硬貨ã§æ¯æãæ¹æ³ã®æ°ã¨èããã°å ¨ãåãã§ããéé¡ã®ä¸éã¯é©å½ã«æ±ºããå¿ è¦ãããã¾ãã
class Array def [](i) i < 0 ? 0 : at(i) end end #ä¸éãé©å½ã«æ±ºãã N = 100 # ç´ æ°ã®ãµãããã¤ãã£ã¦ãã sieve = [] 2.upto(N) do |p| next if sieve[p] (2*p).step(N,p) {|k| sieve[k] = true} end a = (0..N).collect { [] } (0..N).each do |n| t = a[2][n] = a[2][n-2] + ((n == 0) ? 1 : 0) (3..N).each do |k| next if sieve[k] # kãåææ°ã®æãã¹ããã t = a[k][n] = a[k][n-k] + t if a[k][n] > 5000 puts n exit end end end
å®è¡æéã¯0.01sã§ãã
ãã®èãæ¹ã¯åãããããã¦è¯ãã®ã§ãããã¡ã¢ãªãå¤ã使ç¨ããã¨ããæ¬ ç¹ãããã¾ããããã§å½¹ã«ç«ã¤ã®ãオイラーの五角数定理ã§ããããã¯
ã¨ãããã®ã§ãã
nã®æ´æ°åå²ã®æ°p(n)ã®æ¯é¢æ°ã¯
ã¨ãªãã®ã§ãäºè§æ°å®çã使ãã°
ã¨ãªãã¾ãããããå±éãã¦ä¿æ°æ¯è¼ãããã°ãåå²æ°ã®æ¼¸åå¼ãä½ãã¾ãã
Problem 78ã¯ãã®æ¹æ³ã§è§£ãã¾ãããã¾ã è¨ç®æéãæãã£ã¦ããã®ã§ãã£ã¨è¯ãæ¹æ³ãããããããã¾ããã
Problem 78: åå²æ°ãåãã¦1,000,000ã®åæ°ã¨ãªãæ´æ°ãæ±ãã
p = [1] 1.upto(1/0.0) do |n| p[n] = 0 1.upto(1/0.0) do |k| if (m = n - k*(3*k+1)/2) >= 0 p[n] += p[m] * (2*(k%2)-1) end if (m = n - k*(3*k-1)/2) >= 0 p[n] += p[m] * (2*(k%2)-1) else break end end if p[n] % 1000_000 == 0 puts n exit end end
å®è¡æéã¯41.5sã§ããã
ãããã¸ã«ã«ã½ã¼ã(Problem 79)
ããé·ãä¸æã®æ°åãããããã®é·ã3ã®é¨åæ°åã
319
680
180
690
129
...(ç¥)
ã¨ãªãã¨ãããã¨ã®æ°åã¨ãã¦å¯è½ãªç©ã§æãçãç©ãæ±ãã
ããã¯ä»®ã«ãã¨ã®æ°åã«åãæ°ãè¤æ°ååºç¾ããªããªããトポロジカルソートã®åé¡ã§ãã
ããã§ãã¾ãGraphvizã§ã°ã©ããæãã¦ã¿ã¾ãããDOTè¨èªã§è¨è¿°ãã¾ãã
digraph problem79 { 3 -> 1 -> 9 6 -> 8 -> 0 1 -> 8 -> 0 6 -> 9 -> 0 1 -> 2 -> 9 ... }
ãã®çµµããçãã¯ä¸ç®çç¶ã§ããã
ä¸å¿Rubyã§ãããã¸ã«ã«ã½ã¼ããè¡ãã³ã¼ããè¼ãã¦ããã¾ãããããã°ã©ãã«ã«ã¼ããããã°ç¡éã«ã¼ãã«ãªã£ã¦ãã¾ãé常ã«éãªã³ã¼ãã§ãã..ã
file = open("problem79-keylog.txt") # ã°ã©ããä½ã $graph = (0..9).collect {Array.new(10,false)} $used = [] while line = file.gets x, y, z = line.split(//).map {|v| v.to_i} $used[x] = $used[y] = $used[z] = true $graph[x][y] = $graph[y][z] = true end # ãããã¸ã«ã«ã½ã¼ã $visited = [] def visit(v) return if $visited[v] $visited[v] = true 0.upto(9).each do |s| next if not $used[s] or not $graph[s][v] visit(s) end puts v end 0.upto(9).each {|v| $used[v] && visit(v)}
å®è¡æéã¯0.01sã
æ´æ°æ¢ç´¢ã«ç´ã(Problem 80)
å¹³æ¹æ°ã§ãªã100æªæºã®nã«ã¤ãã¦
ânã®æå100æ¡ã®æ°ã®å
ã®åãæ±ãã
開平法ã¨ããæãããã¾ããå®è£
ãé¢åã§ããä»åã¯100æ¡ã¨åãã£ã¦ããã®ã§ããã£ã¨ç°¡åãªæ´æ°ã®æ¢ç´¢åé¡ã«ç´ãã¡ããäºãã§ãã¾ããã¤ã¾ãnã100æªæºãªãã°
ãæºããæ´æ°kããã®æåã®100æ¡åã§ããã¨ãããã¨ã§ã以ä¸ã®æ§ã«è§£ãã¦ã¿ã¾ããã
sum = 0 2.upto(99) do |a| next if Math.sqrt(a).ceil**2 == a # äºåæ¢ç´¢ n = a*10**198 l = 10**99 r = (a+1)*10**99 while r - l > 1 t = (r+l)/2 t**2 - n > 0 ? r = t : l = t end # æ¡ã®åãåã while l > 0 sum += l%10 l /= 10 end end puts sum
å®è¡æéã¯0.26sã§ããã