Project Eueler: problem21
問題
Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).
If d(a) = b and d(b) = a, where a b, then a and b are an amicable pair and each of a and b are called amicable numbers.For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.
Evaluate the sum of all the amicable numbers under 10000.
回答
def calc_dev(n) y = [1] i = 2 while i <= n/2 y << i if n % i == 0 i += 1 end return y end def chk_ami(n) sum1 = calc_dev(n).inject(0){|sum,x| sum + x} sum2 = calc_dev(sum1).inject(0){|sum,x| sum + x} if n == sum2 && n != sum1 return true else return false end end def find_total_ami(n) total = 0 1.upto(n).each do |v| total += v if chk_ami(v) end return total end p find_total_ami(10000)
備考
遅い。
Finished in 45.48 seconds
Project Eueler: problem20
問題
n! means n (n 1) ... 3 2 1
For example, 10! = 10 9 ... 3 2 1 = 3628800,
and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.Find the sum of the digits in the number 100!
回答
def kai(n) return n if n == 1 return n * kai(n-1) end def kai_sum(n) t = kai(n).to_s.split(//).map{|x| x} return t.inject(0){|sum,x| sum + x.to_i} end p kai_sum(100)
Android: 別パッケージのActivityを起動する
問題
別パッケージのActivityを起動する
Intent intent = new Intent(this,jp.leontec.coresaap.CSFrameBrowser.class); intent.setClassName("jp.ex", "jp.ex.myactivity"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
という書き方で、ActivityNotFoundExceptionが出てはまる
解決
Intent intent= new Intent(this, AlarmGui.class); startActivity(intent);
参考URLのサイトにも記載されていますが、何故かintent.setClassName("com.x.y", "className");のようにsetClassNameを利用するとActivityNotFoundExceptionになります。
とのこと。
かなり時間使った。。
Project Eueler: problem18
問題
By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.
3
7 4
2 4 6
8 5 9 3That is, 3 + 7 + 4 + 9 = 23.
Find the maximum total from top to bottom of the triangle below:
75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23NOTE: As there are only 16384 routes, it is possible to solve this problem by trying every route. However, Problem 67, is the same challenge with a triangle containing one-hundred rows; it cannot be solved by brute force, and requires a clever method! ;o)
テスト
require "p18.rb" pil4 = <<"PIL4" 3 7 4 2 4 6 8 5 9 3 PIL4 pil15 = <<"PIL15" 75 95 64 17 47 82 18 35 87 10 20 04 82 47 65 19 01 23 75 03 34 88 02 77 73 07 63 67 99 65 04 28 06 16 70 92 41 41 26 56 83 40 80 70 33 41 48 72 33 47 32 37 16 94 29 53 71 44 65 25 43 91 52 97 51 14 70 11 33 28 77 73 17 78 39 68 17 57 91 71 52 38 17 14 91 43 58 50 27 29 48 63 66 04 68 89 53 67 30 73 16 69 87 40 31 04 62 98 27 23 09 70 98 73 93 38 53 60 04 23 PIL15 describe "max" do it "pil4" do calcMax(pil4) == 23 end it "pil15" do calcMax(pil15) == 1074 end end
回答
$ar = Array.new def sum(col,row,cache) return cache[col][row] if cache[col][row] if $ar.size-1 <= col return cache[col][row] = $ar[col][row] end lnode, rnode = sum(col+1,row,cache), sum(col+1,row+1,cache) if lnode >= rnode return cache[col][row] = lnode + $ar[col][row] else return cache[col][row] = rnode + $ar[col][row] end end def calcMax(pil) cnt = 0 pil.each do |line| $ar[cnt] = line.chomp!.split(/ /).map{|x| x.to_i} cnt += 1 end cache = Array.new(cnt) 0.upto(cnt-1){|x| cache[x] = Array.new(x+1)} p rslt = sum(0,0,cache) return rslt end
Project Eueler: problem19
問題
You are given the following information, but you may prefer to do some research for yourself.
1 Jan 1900 was a Monday.
Thirty days has September,
April, June and November.
All the rest have thirty-one,
Saving February alone,
Which has twenty-eight, rain or shine.
And on leap years, twenty-nine.
A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
回答
$nor = [31,28,31,30,31,30,31,31,30,31,30,31] $nor_s = [1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335] $nor_d = 365 $leap = [31,29,31,30,31,30,31,31,30,31,30,31] $leap_s = [1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336] $leap_d = 366 $sum = 0 def chk_leap(year) if year % 4 == 0 && year % 100 != 0 return true elsif year % 400 == 0 return true else return false end end def calc_leap(st) while st <= $leap_d do $sum += 1 if $leap_s.include?(st) st += 7 end return st - $leap_d end def calc_nor(st) while st <= $nor_d do $sum += 1 if $nor_s.include?(st) st += 7 end return st - $nor_d end dp = 6 1901.upto(2000).each do |x| if chk_leap(x) then dp = calc_leap(dp) else dp = calc_nor(dp) end end p $sum
備考
無理矢理。
Dateモジュールを使ったり、
http://d.hatena.ne.jp/tmr_kohei/20110704/p1
ツェラーの公式を使うとスマートにできるのね。。
http://d.hatena.ne.jp/htz/20090303/1236048043
Project Eueler: problem16
問題
215 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
What is the sum of the digits of the number 21000?
回答
def calc(num) 2**num end def do_sum(num) sum = 0 str = num.to_s 0.upto(str.size.to_i-1) do |n| sum += str[n,1].to_i end sum end n = 15 p "sum = #{do_sum(calc(n))}" n = 1000 p "sum = #{do_sum(calc(n))}"
Project Eueler: problem17
問題
If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.
If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?
NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of "and" when writing out numbers is in compliance with British usage.
回答
ここを参考にまずRSpecでテストを作ってみた
http://d.hatena.ne.jp/myokoym/20100919/1284887970
require "p17.rb" describe "#toEng" do it "1 to one" do toEng(1).should == "one" end it "14 to fourteen" do toEng(14).should == "fourteen" end #略 it "999" do toEng(999).should == "nine hundred and ninety-nine" end it "1000" do toEng(1000).should == "one thousand" end end describe "#sumLetters" do it "342" do sumLetters(toEng(342)) == 23 end it "115" do sumLetters(toEng(115)) == 20 end it "999" do sumLetters(toEng(999)) == 25 end end describe "#sumTotal" do it "5" do sumTotal(5).should == 19 end it "1000" do sumTotal(1000).should == 21124 end end
回答はこうなった。
$data = <<"NUMDATA" 0,zero 1,one 2,two 3,three 4,four 5,five 6,six 7,seven 8,eight 9,nine 10,ten 11,eleven 12,twelve 13,thirteen 14,fourteen 15,fifteen 16,sixteen 17,seventeen 18,eighteen 19,nineteen 20,twenty 30,thirty 40,forty 50,fifty 60,sixty 70,seventy 80,eighty 90,ninety NUMDATA $dic = Hash.new def makedic() $data.each do |line| ar = line.split(/,/) $dic[ar[0].to_i] = ar[1].chomp! end end def toEng(num) tar = num.to_s.split(//) str = "" if tar[-4] != nil return "one thousand" end if tar[-3] != nil str += $dic[tar[-3].to_i] str += " hundred" str += " and " unless num % 100 == 0 end if tar[-2] == "0" || tar[-2] == nil unless tar[-1] == "0" str += $dic[tar[-1].to_i] end elsif tar[-2] == "1" str += $dic[(tar[-2]+tar[-1]).to_i] else str += $dic[(tar[-2]+"0").to_i] unless tar[-1] == "0" str += "-" + $dic[tar[-1].to_i] end end return str end def sumLetters(str) str.gsub("-"," ").split(/ /).inject(0){|sum,s| sum + s.size} end def sumTotal(upper) makedic() 1.upto(upper).inject(0){|sum,x| sum + sumLetters(toEng(x))} end p sumTotal(1000)
備考
リファクタリングにはテスト有効。
テスト駆動で書く習慣をつけよう。