Last active
June 8, 2020 20:29
-
-
Save ababup1192/3dbd77cba18d2dd0f5d6bb79bfb97709 to your computer and use it in GitHub Desktop.
RPN(逆ポーランド記法)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main exposing (main) | |
import Browser | |
import Html exposing (Html, input, main_, p, text) | |
import Html.Attributes exposing (class, placeholder, value) | |
import Html.Events exposing (onInput) | |
-- MAIN | |
main : Program () Model Msg | |
main = | |
Browser.element | |
{ init = init | |
, update = update | |
, view = view | |
, subscriptions = subscriptions | |
} | |
-- MODEL | |
type alias Model = | |
String | |
init : () -> ( Model, Cmd Msg ) | |
init _ = | |
( "", Cmd.none ) | |
-- UPDATE | |
type Msg | |
= Change String | |
update : Msg -> Model -> ( Model, Cmd Msg ) | |
update msg _ = | |
case msg of | |
Change poland -> | |
( poland, Cmd.none ) | |
-- ポーランド記法: "3 4 + 1 2 - *" を Floatに変換。ただし、計算が失敗する可能性も踏まえて Maybe Float とする。 | |
-- 勝手に例外を吐かずに、計算失敗性も考慮するのがElm流(そのため最初は少し面倒で難しいかもだが・・・) | |
calc : String -> Maybe Float | |
calc poland = | |
-- stackの最後に数値が一つだけ残ったら、その先頭を取得。 [ 3.0 ] -> Just 3.0, [] -> Nothing | |
List.head <| | |
-- 逆ポーランド記法から1つずつトークンを読み込み、計算用stackに積み上げていく(畳み込み) | |
List.foldl | |
(\token stack -> | |
case ( stack, token ) of | |
-- トークンが演算子(+, -, *, /)だったら、stackの先頭2つの数字を取り出し(pop, pop)、計算結果をstackに積む | |
( x :: y :: ys, "+" ) -> | |
(y + x) :: ys | |
( x :: y :: ys, "-" ) -> | |
(y - x) :: ys | |
( x :: y :: ys, "*" ) -> | |
(y * x) :: ys | |
( x :: y :: ys, "/" ) -> | |
(y / x) :: ys | |
( xs, numString ) -> | |
-- tokenが数値(文字列) であれば、変換する | |
case String.toFloat numString of | |
Just num -> | |
num :: xs | |
-- 変換に失敗したら(数値以外の文字列であれば)、stackは空にして計算を失敗させる | |
Nothing -> | |
[] | |
) | |
-- 計算用stack, 最初は空 | |
[] | |
-- ポーランド記法: "3 4 + 1 2 - *" を トークン列: ["3", "4", "+", "1", "2", "-", "*"] に変換 | |
(String.split " " poland) | |
view : Model -> Html Msg | |
view model = | |
main_ [ class "ly_cont" ] | |
[ input [ value model, onInput Change, placeholder "10 4 3 + 2 * -" ] [] | |
-- ポーランド記法(model)の計算し、FloatからStringへ変換。ただし計算に失敗していたら"error"と表示する。 | |
, p [] [ text <| Maybe.withDefault "error" <| Maybe.map String.fromFloat <| calc model ] | |
] | |
subscriptions : Model -> Sub Msg | |
subscriptions _ = | |
Sub.none |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment