2014年7月24日木曜日

140724

Ruby


条件演算子(式が複雑な場合)

「VisualC++2013パーフェクトマスター」で次のコードと出会う。

#include <iostream>
using namespace std;

struct dt1 {
int a;
double b;
};

int main()
{
int a = 1, b;

if (a < 5)
b = 10;
else
b = 50;

b = a<5 ? 10 : 50;

if (a < 10)
b = 1;
else if (a < 100)
b = 2;
else if (a < 500)
b = 3;
else
b = 4;

b = (a < 10) ? 1 : (a < 100) ? 2 : (a < 500) ? 1 : 4;

getchar();
return 0;

}

要するに、赤の部分が条件演算子を使って青の部分のように
1行で書けるということなのだが、
Rubyでも同じようにしてみる。

a = 3
if a < 10
  b = 1
elsif a < 100
  b = 2
elsif a < 500
  b = 3
else
  b = 4
end
puts b

a = 33
if a < 10
  b = 1
elsif a < 100
  b = 2
elsif a < 500
  b = 3
else
  b = 4
end
puts b

a = 333
if a < 10
  b = 1
elsif a < 100
  b = 2
elsif a < 500
  b = 3
else
  b = 4
end
puts b

a = 3333
if a < 10
  b = 1
elsif a < 100
  b = 2
elsif a < 500
  b = 3
else
  b = 4
end
puts b

a = 3
puts b = (a < 10)? 1 : (a < 100)? 2 :(a < 500)? 3 : 4

a = 33
puts b = (a < 10)? 1 : (a < 100)? 2 :(a < 500)? 3 : 4

a = 333
puts b = (a < 10)? 1 : (a < 100)? 2 :(a < 500)? 3 : 4

a = 3333
puts b = (a < 10)? 1 : (a < 100)? 2 :(a < 500)? 3 : 4

出力結果
1
2
3
4
1
2
3
4

2014年7月20日日曜日

140720

Ruby


Hashクラスのsortメソッド?

Ruby 1.9では、Hashクラスのsortメソッドは廃止され、
Hashのキーと値をソートした配列を作成して返す。

i_ary = [4, 1, 3, 2] 
w_ary = ["GABLES", "ANNE", "GREEN", "OF"]
hash = Hash[i_ary.zip(w_ary)]
p hash
p hash.sort
p hash.sort.map{|i| i[1]}.join(" ")

出力結果
{4=>"GABLES", 1=>"ANNE", 3=>"GREEN", 2=>"OF"}
[[1, "ANNE"], [2, "OF"], [3, "GREEN"], [4, "GABLES"]]   ←配列
"ANNE OF GREEN GABLES"

2014年7月13日日曜日

140713(2)

Ruby


Hashのキーや値をまとめて取り出す。

w = 'a1bxkk3k'
h = w.scan(/[a-z]/).join.chars.group_by(&:to_sym)
p h
p h.keys
p h.map{|f| f.first}                 ←これでもOK
p h.values
p h.map{|f| f.last}                 ←これでもOK

出力結果
{:a=>["a"], :b=>["b"], :x=>["x"], :k=>["k", "k", "k"]}
[:a, :b, :x, :k]
[:a, :b, :x, :k]
[["a"], ["b"], ["x"], ["k", "k", "k"]]
[["a"], ["b"], ["x"], ["k", "k", "k"]]

140713

Ruby


each_charメソッドは、charsメソッドと同じだが、今のところ後者の方が好きだ。

w = 'a1bxkk3k'
p w.scan(/[a-z]/).join.chars.group_by(&:to_sym)
p w.scan(/[a-z]/).join.each_char.group_by(&:to_sym)
# 途中で切ると…
p w.scan(/[a-z]/).join.chars
p w.scan(/[a-z]/).join.each_char

出力結果
{:a=>["a"], :b=>["b"], :x=>["x"], :k=>["k", "k", "k"]}
{:a=>["a"], :b=>["b"], :x=>["x"], :k=>["k", "k", "k"]}
["a", "b", "x", "k", "k", "k"]
#<Enumerator: "abxkkk":each_char>           ←何か汚い。

2014年6月15日日曜日

140615

Ruby


Hashの値の設定

既にあるキーに対して値を設定すれば格納されていた値が上書きされる。
例
maps1 = {1010 => false}
maps1[1100] = false
p maps1

maps2 = {1010 => false}
maps2[1100] = false
maps2[1010] = false  # 再度同じ値を指定
p maps2

maps3 = {1010 => false}
maps3[1100] = false
maps3[1010] = true  # 異なる値を指定
p maps3

出力結果
{1010=>false, 1100=>false}
{1010=>false, 1100=>false}
{1010=>true, 1100=>false}

この性質を使うと
状態 {101000=>false, 110000=>false} から
状態 {111000=>false, 101010=>false, 101100=>false, 110100=>false} へ
移行するプログラムを作ることは容易なことがわかる。

2014年6月2日月曜日

140602

誤差について


140315(2)について、数学的には正しいが、プログラミングのうえでは不完全な部分があった。

z = Math.sqrt(x**2+y**2)
  if z == z.to_i && z < 101 then

上記はzが整数になるときについて考えようとしているわけだが、
x**2+y**2が平方数に非常に近い場合、(数学的にz == z.to_i が偽であっても)
z == z.to_i が真となりうる。
よって、
z = Math.sqrt(x**2+y**2)
  if x**2+y**2 == (z.to_i)**2 && z < 101 then
とすべきである。

このことは、次のフェルマーが出した問題を解いているときに気づいた。
x^2 - 61y^2 = 1 の自然数解を求めよ。

y = 1
num = Math.sqrt(61*y**2+1)
while !(num == num.to_i)
  y += 1
  num = Math.sqrt(61*y**2+1)
end
p num
p y

とすると、誤った最小の自然数解
335159612.0
42912791
が出力される。
正しくは次のとおりである。

y = 1
num = Math.sqrt(61*y**2+1)
while !((num.to_i)**2 - 61*y**2 == 1)
  y += 1
  num = Math.sqrt(61*y**2+1)
end
p num
p y

出力結果
1766319049.0
226153980

2014年5月17日土曜日

140517

Excelのシートにおいて、数式を含んでいるか調べる。


セル(1,1)からセル(100,100)までのシートの保護のかかっていない
セルについて、数式を含んでいるかを調べ、
数式を含んでいるセルは数式と表示する。

Sub 数式()
For i = 1 To 100
For j = 1 To 100
  If Cells(i, j).Locked = False Then
    If Cells(i, j).HasFormula Then
      Cells(i, j).Value = "数式"
    End If
  End If
Next
Next
End Sub

2014年5月11日日曜日

140511(2)

複数のファイルの名前を変更する方法


マクロを組む以外に単純な方法に今更ながら気づいたので記しておく。
①複数のファイルを選択。
②名前を変更。
すると、自動的に複数のファイルの名前が〇〇(1)、〇〇(2)、…に変更される。

きっかけ
同じものをダウンロードしたときや、複数のファイルを同じフォルダ内に保存するとき
に自動的に名前が付けられるのはなぜか不思議に思ったことから。

140511

証明もプログラムも簡潔な方がよい。

簡潔
=美しい+短い+わかりやすい
 質    量

わかりやすさを加えたのは、とりわけプログラミングにおいて、
「美しいまたは短い」からといっても「わかりやすい」とも限らないからだ。

2014年5月5日月曜日

140505

Ruby


140306でもArray#permutationを用いたが、また別の問題を解いてみよう。

1〜8を下のa〜hに「右にいくほど大きくなり、下にいくほど大きくなる」ように
書き込む方法は何通りあるか?

a,b,c,d
e,f,g
h

i = 0
(1..8).to_a.permutation do |a, b, c, d, e, f, g, h|
  if a<b and b<c and c<d and e<f and f<g and a<e and e<h and b<f and c<g then
    i += 1
    puts i
    puts "[#{a},#{b},#{c},#{d}],[#{e},#{f},#{g}],[#{h}]"
  end
end

これを実行すると、70通りであることがわかる。

ちなみに、(Frame-Robinson-Thrall による鉤公式を用いれば)
λ=(4,3,1)のとき、
dim Sλ = 8!/(6*4*3*1*4*2*1*1) = 70
となり、
#STab(λ) = dim Sλ = 70