challenge 小町算

古典的なパズルである小町算を解くプログラムを作成してください。

小町算とは:

1□2□3□4□5□6□7□8□9=100

四角の中に、空白、+、-、×、÷のいずれかを一つ入れ、等式が成り立つようにするパズルです。

解答例:

1-2-3+4×56÷7+8×9=100

1+234×5÷6-7-89=100

参考: http://ja.wikipedia.org/wiki/%E5%B0%8F%E7%94%BA%E7%AE%97

  • evalやそれに類するものを使うか否かは自由です。
  • 割り算の際には小数点以下の切捨てが起こらないのが望ましいです。(必須ではない)
    • 切捨てが起こる場合の解答例:1÷2÷3+4+5÷6+7+89=100
  • 余裕があれば括弧を含むようにしてもいいかもしれません。

手元で20数行ほどのPythonスクリプトを書いてみたところ、101個の解答が得られました。

Posted feedbacks - OCaml

ocamlyaccとかストリームパーサーとか色々な道具を試した結果、LL(1) 再帰下降パーサーを手書きしました。

計算途中の値はint*int型の分数で持っています。

結果は101件で実行時間は0.23秒でした。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
type token = Int of int | Mul | Div | Add | Sub

let add (a1, b1) (a2, b2) = (a1 * b2 + a2 * b1), (b1 * b2)
let sub (a1, b1) (a2, b2) = (a1 * b2 - a2 * b1), (b1 * b2)
let mul (a1, b1) n        = (a1 * n), b1
let div (a1, b1) n        = a1, (b1 * n)

let factor list =
  let rec factor' n = function
    | Int x :: tl -> factor' (n * 10 + x) tl
    | x           -> n, x in
  factor' 0 list

let term input =
  let rec term' (f,input)  = match input with
    | Mul :: tl -> let f2, tl2 = factor tl in term' ((mul f f2), tl2)
    | Div :: tl -> let f2, tl2 = factor tl in term' ((div f f2), tl2)
    | x         -> f, x in
  let n, input = factor input in term' ((n,1), input)

let expr input =
  let rec expr' (f,input) = match input with
    | Add :: tl -> let f2, tl2 = term tl in expr' ((add f f2), tl2)
    | Sub :: tl -> let f2, tl2 = term tl in expr' ((sub f f2), tl2)
    | _         -> f in
  expr' (term input)

let op = [| Add; Sub; Mul; Div |]

let rec makeexpr list o n =
  if n = 0 then list else match (o mod 5) with
    | 4 -> makeexpr (Int n           :: list) (o / 5) (n - 1)
    | x -> makeexpr (Int n :: op.(x) :: list) (o / 5) (n - 1)

let rec makestr s = function
  | []       -> s
  | hd :: tl -> makestr (s ^ (match hd with
    | Int x -> string_of_int x | Mul->"*" | Div->"/" | Add->"+" | Sub->"-")) tl

let rec main n = if n >= 0 then
    let ex = makeexpr [ Int 9 ] n 8 in
    let a, b = expr ex in
    let _ = if b * 100 = a then Printf.printf "%s\n" (makestr "" ex) in
    main (n - 1)

let _ = main 390624

Index

Feed

Other

Link

Pathtraq

loading...