2012年12月30日日曜日

開発環境

『初めてのプログラミング 第2版』(Chris Pine 著、長尾 高弘 訳、オライリー・ジャパン、2010年、ISBN978-4-87311-469-9)の 13章(新しいクラスのオブジェクト), 13.1(練習問題)組み込みクラスの拡張 を解いてみる。

その他参考書籍

組み込みクラスの拡張

コード(BBEdit)

sample.rb

#!/usr/bin/env ruby1.9
# -*- coding: utf-8 -*-

class Array
  def shuffle
    some_array = self
    shuffled_array = []
    a = Array.new(some_array)
    while a.length > 0
      r = rand a.length
      shuffled_array.push(a.slice(r))
      a = a.slice(0, r) + a.slice(r + 1, a.length)
    end
    shuffled_array
  end
end

class Integer
  ## メモ化
  @@facs = {}
  @@romans = {}
  def factorial
    n = self;
    return "0以上の整数を入力してください" unless n >= 0
    return @@facs[n] if @@facs[n]
    return @@facs[n] = 1 if n == 1
    return @@facs[n] = n * (n-1).factorial
  end
  def to_roman
    number =self
    return @@romans[number] if @@romans[number]
    roman = ""
    t = number / 1000
    number = number % 1000
    h = number / 100
    number = number % 100
    ten = number / 10
    number = number % 10
    o = number
    roman +='M' * t
    if h == 9
      roman += 'CM'
    elsif h == 4
      roman += 'CD'
    else
      roman += 'D' * (h / 5)
      roman += 'C' * (h % 5)
    end
    if ten == 9
      roman += 'XC'
    elsif ten == 4
      roman += 'XL'
    else
      roman += 'L' * (ten / 5)
      roman += 'X' * (ten % 5)
    end
    if o == 9
      roman += 'IX'
    elsif o == 4
      roman += 'IV'
    else
      roman += 'V' * (o / 5)
      roman += 'I' * (o % 5)
    end
    @@romans[self] = roman
  end
end

a = [1,2,3,4,5] + %w[A B C D E a b c d e]
shuffled_a = a.shuffle
puts "シャッフル前: #{a.join(" ")}"
puts "シャッフル後: #{shuffled_a.join(" ")}"
n = 10
puts "#{n}! = #{n.factorial}"
n = 1234
puts "#{n}: #{n.to_roman}"

入出力結果(Terminal)

$ ./sample.rb
シャッフル前: 1 2 3 4 5 A B C D E a b c d e
シャッフル後: c 5 d 1 b A e 2 3 a 4 C B D E
10! = 3628800
1234: MCCXXXIV
$

ちなみにJavaScriptの場合。

コード(BBEdit)

<label>配列(カンマ区切り文字列)または整数を入力<br />
<input id="t0" type="text" value="1,2,3,4,5,'A','B','C','D','E','a','b','c','d','e'" />
</label><br />
<input type="button" value="配列をシャッッフル" onclick="clicked1()" /><br />
<input type="button" value="階乗を求める" onclick="clicked2()" /><br />
<input type="button" value="数値をローマ数字に変換" onclick="clicked3()" />

<script>
Array.prototype.shuffle = function(){
  var some_array = this;
  var shuffled_array = [];
  var a = [];
  for(var i = 0; i < some_array.length; i++){
    a[i] = some_array[i];
  }
  while(a.length > 0){
    var r = Math.floor(Math.random() * a.length);
    var o = a.splice(r, 1);
    shuffled_array.push(o[0]);
  }
  return shuffled_array;
};
// メモ化
var facs = {};
Number.prototype.factorial = function(){
  var n = this.valueOf();
  if(facs[n]) return facs[n];
  if( n < 0) return "0以上の整数を指定してください";
  if(n === 0 || n === 1) return facs[n] = 1;
  return facs[n] = n * (n-1).factorial();
};
String.prototype.repeat = function(n){
  var result = "";
  for(var i = 0; i < n; i++){
    result += this;
  }
  return result;
};
// メモ化
var romans = {};
Number.prototype.to_roman = function(){
  var n = this.valueOf();
  if(romans[n]) return romans[n];
  var roman = "";
  var t = Math.floor(n / 1000);
  n %= 1000;
  var h = Math.floor(n / 100);
  n %= 100;
  var ten = Math.floor( n / 10);
  n %= 10;
  var o = n;
  roman += 'M'.repeat(t);
  switch(h){
    case 9: roman += 'CM'; break;
    case 4: roman += 'CD'; break;
    default: roman += 'D'.repeat(Math.floor(h / 5));
             roman += 'C'.repeat(Math.floor(h % 5));
  }
  switch(ten){
    case 9: roman += 'XC'; break;
    case 4: roman += 'CL'; break;
    default: roman += 'L'.repeat(Math.floor(ten / 5));
             roman += 'X'.repeat(Math.floor(ten % 5));
  }
  switch(o){
    case 9: roman += 'IX'; break;
    case 4: roman += 'IV'; break;
    default: roman += 'V'.repeat(Math.floor(o / 5));
             roman += 'I'.repeat(Math.floor(o % 5));
  }
  return romans[this.valueOf()] = roman;
};
function clicked1(){
  var o = $('#t0').val();
  var a = o.split(",");
  var shuffled_a = a.shuffle();
  $('#pre0').text("シャッフル前: " + a + "\n" +
    "シャッフル後: " + shuffled_a);
}
function clicked2(){
  var o = parseInt($('#t0').val());
  o = new Number(o);
  $('#pre0').text( o + "! = " + o.factorial());
}
function clicked3(){
  var o = $('#t0').val();
  o = new Number(o);
  $('#pre0').text(o.to_roman());
}
</script>





pythonの場合。

sample.py

コード(BBEdit)

#!/usr/bin/env python3.3
# -*- coding: utf-8 -*-

class MyList(list):
    def __init__(self, data):
        list.__init__(self,data)
        self.data = data
    
    def __getattr__(self, attrname):
        return getattr(self.data, attrname)

    def shuffle(self):
        l = MyList(self.data[:])
        shuffled_list = MyList([])
        
        import random
        
        while len(l) > 0:
            r = random.randint(0, len(l) - 1)
            shuffled_list.append(l.pop(r))
        
        return MyList(shuffled_list)

class MyInt(int):
    facs = {}
    romans = {}
    def __init__(self, data):
        self.data = data
    
    def __getattr__(self, attrname):
        return getattr(self.data, attrname)
    
    def factorial(self):
        if self.data in MyInt.facs:
            return MyInt.facs[self.data]
        if self.data < 0: 
            raise Exception("0以上の整数を指定してください")
        if self.data <= 1:
            MyInt.facs[self.data] = 1
            return 1
        MyInt.facs[self.data] = MyInt(self.data) * MyInt(self.data - 1).factorial()
        return MyInt.facs[self.data]
    
    def to_roman(self):
        number = self.data
        if number in MyInt.romans:
            return MyInt.romans[number]
        roman = ""
        t = number // 1000
        number %= 1000
        h = number // 100
        number %= 100
        ten = number // 10
        number %= 10
        o = number
        roman += 'M' * t
        if h == 9:
          roman += 'CM'
        elif h == 4:
          roman += 'CD'
        else:
          roman += 'D' * (h // 5)
          roman += 'C' * (h % 5)
        
        if ten == 9:
          roman += 'XC'
        elif ten == 4:
          roman += 'XL'
        else:
          roman += 'L' * (ten // 5)
          roman += 'X' * (ten % 5)
        
        if o == 9:
          roman += 'IX'
        elif o == 4:
          roman += 'IV'
        else:
          roman += 'V' * (o // 5)
          roman += 'I' * (o % 5)
        
        MyInt.romans[self.data] = roman
        return roman        

if __name__ == '__main__':
    l = MyList([1,2,3,4,5,'A','B','C','D','a','b','c','d','e'])
    shuffled_l = l.shuffle()
    print("シャッフル前: {0}".format(l))
    print("シャッフル後: {0}".format(shuffled_l))
    n = MyInt(10)
    print("{0}! = {1}".format(n, n.factorial()))
    n = MyInt(1234)
    print("{0}: {1}".format(n, n.to_roman()))
    

入出力結果(Terminal)

$ ./sample.py
シャッフル前: [1, 2, 3, 4, 5, 'A', 'B', 'C', 'D', 'a', 'b', 'c', 'd', 'e']
シャッフル後: ['a', 'd', 'A', 'b', 'c', 'C', 'B', 4, 1, 'D', 2, 3, 5, 'e']
10! = 3628800
1234: MCCXXXIV
$

0 コメント:

コメントを投稿