2012年12月28日金曜日

開発環境

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

その他参考書籍

roman_to_integer 'mcmxcix'!

コード(BBEdit)

sample.rb

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

def roman_to_integer roman
  num = 0
  r_i = {
    'M' => 1000,
    'D' => 500,
    'C' => 100,
    'L' => 50,
    'X' => 10,
    'V' => 5,
    'I' => 1}
  pre = 0
  (roman.length-1).downto(0) do |i|
    n = r_i[roman[i].upcase]
    return "有効なローマ数字になっていません!" unless n
    if n >= pre
      num += n
      pre = n
    else
      num -= n
    end
  end
  num
end

def roman_numeral 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
  roman
end

puts roman_to_integer 'mcmxcix'

(1..1000).each do |num|
  if num != roman_to_integer(roman_numeral num)
    puts "間違え有り"
  end
end

入出力結果(Terminal)

$ ./sample.rb
1999
$

ちなみにJavaScriptの場合。

コード(BBEdit)

function roman_to_integer(roman){
  var num = 0;
  var r_i = {
    'M':1000,
    'D':500,
    'C':100,
    'L':50,
    'X':10,
    'V':5,
    'I':1}
  var pre = 0;
  for(var i = roman.length - 1; i >= 0; i--){
    var n = r_i[roman[i].toUpperCase()];
    if(!n) throw "有効なローマ数字になっていません!";
    if(n >= pre){
      num += n;
      pre = n;
    } else {
      num -= n;
    }
  }
  return num;
}
var roman = $('#t0').val();
$('#pre0').text(roman_to_integer(roman));




pythonの場合。

sample.py

コード(BBEdit)

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

class Error(Exception):pass
def roman_to_integer(roman):
    num = 0
    r_i = r_i = {
      'M':1000,
      'D':500,
      'C':100,
      'L':50,
      'X':10,
      'V':5,
      'I':1}
    pre = 0
    for i in range(len(roman) - 1, -1, -1):
        if not roman[i].upper() in r_i.keys():
            # 何となく例外を発生させるようにしてみた
            raise Error("有効なローマ数字になっていない!")
        n = r_i[roman[i].upper()]
        if n >= pre:
            num += n
            pre = n
        else:
            num -= n
    return num
def roman_numeral(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)
    
    return roman

try:
    print(roman_to_integer('mcmxcix'))
    for num in range(1, 1001):pass
except Error as err:
    print(err)
    

入出力結果(Terminal)

$ ./sample.py
1999
$

perlの場合。

sample.pl

コード(BBEdit)

#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use 5.016;
binmode STDIN, ":utf8";
binmode STDOUT, ":utf8";
use POSIX; # 浮動小数点数の切り捨てのためfloor関数を使いたいのでPOSIXモジュールを使用

sub roman_to_integer{
  my $roman = shift;
  my @a = split "", $roman;
  my $num = 0;
  my %r_i = (
    'M' => 1000,
    'D' => 500,
    'C' => 100,
    'L' => 50,
    'X' => 10,
    'V' => 5,
    'I' => 1);
  my $pre = 0;
  for(reverse(0..(@a - 1))){
    my $n = $r_i{uc $a[$_]};
    return "有効なローマ数字になっていない!" unless $n;
    if($n >= $pre){
      $num += $n;
      $pre = $n;
    } else {
      $num -= $n;
    }
  }
  $num;
}

sub roman_numeral{
  my $n = shift;
  my $roman = "";
  my $t = floor($n / 1000);
  $n %= 1000;
  my $h = floor($n / 100);
  $n %= 100;
  my $ten = floor($n / 10);
  $n %= 10;
  my $o = $n;
  $roman .= 'M' x $t;
  given($h){
    when(9){ $roman .= 'CM';}
    when(4){ $roman .= 'CD';}
    default{
      $roman .= 'D' x floor($h / 5);
      $roman .= 'C' x ($h % 5);
    }
  }
  given($ten){
    when(9){ $roman .= 'XC';}
    when(4){ $roman .= 'XL';}
    default{
      $roman .= 'L' x floor($ten / 5);
      $roman .= 'X' x ($ten % 5);
    }
  }
  given($o){
    when(9){ $roman .= 'IX';}
    when(4){ $roman .= 'IV';}
    default{
      $roman .= 'V' x floor($o / 5);
      $roman .= 'I' x ($o % 5);
    }
  }
  $roman;
}

print roman_to_integer('mcmxcix') . "\n";
for(1..1000){
  if($_ != roman_to_integer(roman_numeral $_)){
    print "間違え有り\n";
  }
}

入出力結果(Terminal)

$ ./sample.pl
1999
$

0 コメント:

コメントを投稿