Integer to RomanNumeral in Erlang 2

Posted by okkez Wed, 06 Jun 2007 13:52:00 GMT

Haskell で書いたのを参考に書き直してみた。 なんとなく Haskell っぽくなった?

convert.erl
-module(convert).
-compile(export_all).
-import(lib_misc,[p/1]).

old_roman_unit(1000) -> "M";
old_roman_unit( 500) -> "D";
old_roman_unit( 100) -> "C";
old_roman_unit(  50) -> "L";
old_roman_unit(  10) -> "X";
old_roman_unit(   5) -> "V";
old_roman_unit(   1) -> "I".

i2r(Num) ->
    lists:flatten(i2r(Num, [1000, 500, 100, 50, 10, 5, 1])).
i2r(_,[]) ->
    [];
i2r(Num, [H|T]) ->
    lists:duplicate(Num div H, old_roman_unit(H)) ++ i2r(Num rem H, T).

参考

Ruby で同じロジックで書いてみた。

convert.rb
class  Numeric
  OLD_ROMAN_UNIT = {
    1000 => 'M',
     500 => 'D',
     100 => 'C',
      50 => 'L',
      10 => 'X',
       5 => 'V',
       1 => 'I'
  }

  def to_old_roman
    i2r(self, [1000,500,100,50,10,5,1])
  end

  def i2r(num, units)
    return '' if units.empty?
    digits, mod = num.divmod(h = units.shift)
    OLD_ROMAN_UNIT[h] * digits + i2r(mod, units)
  end
end

やっと再帰の使い方が理解できたかも?

Posted in , |

RomanNumeral to Integer in Erlang

Posted by okkez Sun, 03 Jun 2007 00:22:00 GMT

昨日、帰宅後に書いた奴の逆バージョン。

D(500), L(50), V(5) が複数ある場合のチェックは抜けてるけど大体できたので書いておく。

to_integer
r2i(Str) ->
    [H|T] = [1000, 500, 100, 50, 10, 5, 1],
    {Matched, Unmatched} = 
    lists:partition(fun(X) ->
                [X] =:= old_roman_unit(H) end, Str),
    check(Str, Matched),
    lists:sum(lists:map(fun({Num, L}) ->
              Num * length(L) end,
              r2i(T, Unmatched, [{H, Matched}]))).
r2i([], _, L) ->
    L;
r2i([H|T], Str, L) ->
    {Matched, Unmatched} =
    lists:partition(fun(X) ->
                [X] =:= old_roman_unit(H) end, Str),
    check(Str, Matched),
    r2i(T, Unmatched, [{H, Matched}|L]).

check(Orig, L) ->
    if length(Orig) < length(L) ->
        false;
       true ->
        case lists:all(fun({X,Y}) -> X =:= Y end,
               lists:zip(lists:sublist(Orig,1,length(L)),L)) of
        true -> true;
        false -> throw('ArgumentError')
        end
    end.

自分で作った lib_misc:p/1 がかなり便利。Ruby の Kernel#p というか Ruby1.9 の Kernel#tap ぽく使える。

Erlang勉強会#1

Posted in |

Integer to RomanNumeral in Erlang

Posted by okkez Sat, 02 Jun 2007 16:50:00 GMT

Erlang 勉強会#1の宿題ができたので公開。

to_roman_numeral
-module(math).
-export([i2r/1,to_s/2]).
-import(lib_misc,[p/1]).

old_roman_unit(N) when N =:= 1000 -> "M";
old_roman_unit(N) when N =:= 500  -> "D";
old_roman_unit(N) when N =:= 100  -> "C";
old_roman_unit(N) when N =:= 50   -> "L";
old_roman_unit(N) when N =:= 10   -> "X";
old_roman_unit(N) when N =:= 5    -> "V";
old_roman_unit(N) when N =:= 1    -> "I".

i2r(Num) ->
    [H|T] = [1000, 500, 100, 50, 10, 5, 1],
    {Div, Mod} = {Num div H, Num rem H},
    lists:flatten(i2r(Mod, T, to_s(old_roman_unit(H),Div))).
i2r(_,[],Str) ->
    Str;
i2r(Num, [H|T], Str) ->
    {Div, Mod} = {Num div H, Num rem H},
    if
    Div > 0 ->
        i2r(Mod, T, Str ++ to_s(old_roman_unit(H), Div));
    true ->
        i2r(Mod, T, Str)
    end.



to_s(C, Num) ->
    if Num > 0 ->
        lists:map(fun(_) -> C end,lists:seq(1,Num));
       true ->
        []
    end.

ダサい部分はたくさんあるけど自力で書いたのが偉いと思ったので公開。エラーメッセージの読み方がなんとなくわかってきたような気がする。

ついでに。

lib_misc
-module(lib_misc).
-export([p/1]).

p(X) ->
    io:format("~p~n",[X]),
    X.

こんな感じで使う。 関数の途中の値を知りたいときに使うと便利かも?

sample
to_s(C, Num) ->
    if Num > 0 ->
        lib_misc:p(lists:map(fun(_) -> C end,lists:seq(1,Num)));
       true ->
        []
    end.

Posted in | no comments |

FizzBuzz

Posted by okkez Sat, 26 May 2007 02:03:00 GMT
Haskell
import System

main = putStr $ unlines [fb(x) | x <- [1..100]]

fb n | n `mod` 15 == 0 = "FizzBuzz"
     | n `mod` 5 == 0 = "Buzz"
     | n `mod` 3 == 0 = "Fizz"
     | otherwise = show n
Erlang
-module(fizzbuzz).
-export([fizzbuzz/0,fb/1]).

fizzbuzz() -> [ fb(X) || X <- lists:seq(1,100)].

fb(N) when N rem 15 =:= 0 -> "FizzBuzz";
fb(N) when N rem 5  =:= 0 -> "Buzz";
fb(N) when N rem 3  =:= 0 -> "Fizz";
fb(N) -> N.

Erlang の方の動かし方。(インストールは略)

  • erl シェルを起動
1> c(fizzbuzz.erl). %=> コンパイル
{ok,fizzbuzz}
2> fizzbuzz:fizzbuzz. %=> 関数呼び出しの括弧は必要
** 1: illegal expression **
3> fizzbuzz:fizzbuzz().
[1,
 2,
 "Fizz",
 4,
 "Buzz",
 "Fizz",
 7,
 8,
 "Fizz",
 "Buzz",
 11,
 "Fizz",
 13,
 14,
 "FizzBuzz",
 16,
 17,
 "Fizz",
 19,
 "Buzz",
 "Fizz",
 22,
 23,
 "Fizz",
 "Buzz",
 26,
 "Fizz",
 28,
 29|...] %=> リストの出力は省略される
4>

Posted in | no comments |

Erlang勉強会#0

Posted by okkez Wed, 23 May 2007 13:53:00 GMT

を氏久くんが明日やるらしい。

突然過ぎ。

一応、行けるっぽい感じの予定ですがどうしようかな。

Posted in | no comments |