質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

3回答

2880閲覧

rubyで小町算を解きたい

hahu333

総合スコア8

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

1クリップ

投稿2017/02/16 22:41

編集2022/01/12 10:55

【追記あり】小町算で、数字1.2.3.4.5.6.7.8.9が現れる順番を任意でよいとして答えが0になる式を全て求めるプログラムを作成する。解は何通りあるか?という問題です。色々関数を作ってみたのはいいですが、ここから先に進みません。どうしたら完成するでしょうか?

def subset(xs) return [[]] if xs.size<=0 mst=xs.dup lst=mst.pop mst=subset(mst) mst+mst.map{|e|e+[lst]} end def sum(xs) xs.inject{|r,a|r+=a} end def paste(xs) rss=[] make_perm(xs.size){|idx| rss<<xs.values_at(*idx.map{|e|e-1}) } rss end def make_perm(n, m = 0, perm = [], &blk) if n <= m yield perm else for x in 1 .. n next if perm.member? x perm.push x make_perm(n, m + 1, perm, &blk) perm.pop end end end def make_exprs(xs) n=xs.length ass=subset(Array(0..(n-1))) yss=[] for as in ass ys = [] for i in 0..(n-1) if as.index(i) != nil then ys.push(zs[i]) else ys.push(-zs[i]) end end yss.push(ys) end return yss end def komachi(xs, target) a = 0 zss = paste(xs) wss = [] for zs in zss wss = wss + make_exprs(zs) end for ws in wss if sum(ws) == target then a = a + 1 end end puts a end

追記
プログラムの質問です

追記2 18:24
足りなかった部分を追加、編集してみたのですが、数字を入力しても0としか表示されません。(たまに24とも表示される)

また、答えの表示ですが、解の個数だけ表示できればいいです

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

evalを使ったので参考になるかどうか分かりませんが、4つの数字から10を作る問題の解答として作ったものです。括弧有りなので、ちょっと複雑になってます。

Ruby

1X = %w{ 3 4 7 8 } # 数字 2 3OP = %w{ + - * / )+ )- )* )/ 4 +( -( *( /( )+( )-( )*( )/( } 5LL = %w{ - ( -( } << "" 6RR = %w{ ) } << "" 7 8class Fixnum 9 def /(other) 10 self.to_r / other.to_r 11 end 12end 13 14X.permutation(4) do |x| 15 OP.repeated_permutation(3) do |op| 16 LL.each do |ll| 17 RR.each do |rr| 18 expr = ll+x.zip(op).join+rr 19 next if /\(\d\)/ =~ expr 20 val = begin 21 eval expr 22 rescue SyntaxError, ZeroDivisionError 23 nil 24 end 25 puts "#{expr} = #{val}" if val==10 26 end 27 end 28 end 29end

投稿2017/02/17 00:56

otn

総合スコア84421

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hahu333

2017/02/17 09:33

回答ありがとうございます。ソースコードを少し修正、追加してみたのでよろしければまたご意見をお聞きしたいです。
otn

2017/02/17 12:29

初心者のコメント無しのこの量のコードを読むのは苦痛です。各行に付けなくて良いですが、何のためのメソッドなのか、メソッドごとに書いてください。また、メイン部分を書いてください。
guest

0

アルゴリズムが聞きたいのか、プログラムが聞きたいのか分かりませんが、小町算を知らなかったので、少し調べてみました。

小町算-Wikipedia

小町算(こまちざん)は数の遊びである数学パズルの一種。1□2□3□4□5□6□7□8□9 = 100 という数式の□の中に、+,-,×,÷,空白 のいずれかを一つずつ入れて正しい数式を完成させるというものである。方程式などは解法が研究されており、虫食い算、覆面算も繰り上がりなどを手がかりに答えを絞り込んでいけるが、小町算はそのような解法はなく、ひたすらトライ&エラーで答えを探すしかない。

こちらの変則型の質問(数字の並び方を固定せず(←指摘があり追記しました。)、解を0とする)と理解しました。

ひたすら トライ&エラー ということなので、全組み合わせをループで回すことになります。ただし、ループとしては、外側にある数字を使用してはイケない制限が発生するので、それをスキップする機構を組み込みます。
四則演算とは、そのまま4通りなので、ループで回せばイイです。

===追記===
*ルールを勘違いしていました。計算方法は四則演算だけでなく、空白を含むのですね^^;
回答を修正しました。

多分、再帰で全部記述することもできる気もしますが、ちょっと頭が追いつかなくなったので、大きく3部分に分けました。
otn さんの回答見ると、Ruby だと create_numberoperation_combination に似た内容が関数化されてるんですかね。羨ましい。。。

ざっくりと解説すると

create_number 与えられた配列に対して、重複のない組み合わせの数字を作成
すでに使用した数字はスキップし、それ以外は桁数になるまで再帰することで作成しています。
こんな数字が並びます。
123456789,
123456798,

operation_combination +-/空白 の組み合わせを与えられた桁数分用意
+-
/空白 を 1-5 の数字に置き換えて考えています。
1-5 を桁数分の組み合わせで作成します。
こんな数字が並びます。
111111111,
111111112,

意味は
+++++++++,
++++++++-,

です。

get_sum ぐるぐる計算するところ
create_number と operation_combination で作成した配列を空になるまで計算しています。
今回は、値の正当性を確認したかったので、0 のカウントとせず、式と合計値を表示するサンプルにしています。
結局、eval のお世話になってしまいました^^;
面白かったです。

php

1<?php 2class Komachi{ 3 private $base_array; 4 private $count_base_array; 5 private $result_array =[]; 6 private $base_op_array = [1,2,3,4,5]; //1:+,2:-,3:*,4:/,5:'' 7 private $count_base_op_array = 5; 8 private $combination_op_array = []; 9 10 public function __construct($base_array) { 11 $this->base_array = $base_array; 12 $this->count_base_array = count($base_array); 13 } 14 15 public function result() { 16 return ($this->result_array); 17 } 18 19 public function combination_op_array() { 20 return ($this->combination_op_array); 21 } 22 23 public function create_number($org_number,$count){ 24 for($i = 0 ; $i < $this->count_base_array ;$i++){ 25 $org_number_array = str_split($org_number,1); 26 if (in_array($this->base_array[$i],$org_number_array)) { 27 continue; 28 } 29 $new_number = $org_number * 10 + $this->base_array[$i]; 30 if ($count === $this->count_base_array){ 31 $this->result_array[] = $new_number; 32 continue; 33 } 34 $this->create_number($new_number,$count+1); 35 } 36 } 37 38 public function operation_combination($org_number,$count){ 39 for($i = 0 ; $i < $this->count_base_op_array ;$i++){ 40 $new_number = $org_number * 10 + $this->base_op_array[$i]; 41 if ($count === $this->count_base_array-1){ 42 $this->combination_op_array[] = $new_number; 43 continue; 44 } 45 $this->operation_combination($new_number,$count+1); 46 } 47 } 48 49 public function get_sum(){ 50 $this->create_number(0,1); 51 $this->operation_combination(0,1); 52 foreach($this->result_array as $num){ 53 $num_array = str_split($num,1); 54 foreach($this->combination_op_array as $combination_op){ 55 $op_array = str_split($combination_op,1); 56 for($i = 0 ; $i < $this->count_base_array ;$i++){ 57 if($i === 0){ 58 $sum = $num_array[$i]; 59 continue; 60 } 61 if ((int)$op_array[$i-1] === 1){ 62 $sum = $sum . '+'.$num_array[$i]; 63 } 64 if ((int)$op_array[$i-1] === 2){ 65 $sum = $sum . '-'.$num_array[$i]; 66 } 67 if ((int)$op_array[$i-1] === 3){ 68 $sum = $sum . '*'.$num_array[$i]; 69 } 70 if ((int)$op_array[$i-1] === 4){ 71 $sum = $sum . '/'. $num_array[$i]; 72 } 73 if ((int)$op_array[$i-1] === 5){ 74 $sum = $sum . $num_array[$i]; 75 } 76 } 77 $result= eval("return {$sum};"); 78 echo $sum . ' = ' . $result . PHP_EOL; 79 } 80 } 81 } 82} 83 84// $tmp = new Komachi([1,2,3,4,5,6,7,8,9]); 85$komachi = new Komachi([1,2,3]); 86$komachi->get_sum();

以下、[1,2,3] の結果です。

1+2+3 = 6 1+2-3 = 0 1+2*3 = 7 1+2/3 = 1.6666666666667 1+23 = 24 1-2+3 = 2 1-2-3 = -4 1-2*3 = -5 1-2/3 = 0.33333333333333 1-23 = -22 1*2+3 = 5 1*2-3 = -1 1*2*3 = 6 1*2/3 = 0.66666666666667 1*23 = 23 1/2+3 = 3.5 1/2-3 = -2.5 1/2*3 = 1.5 1/2/3 = 0.16666666666667 1/23 = 0.043478260869565 12+3 = 15 12-3 = 9 12*3 = 36 12/3 = 4 123 = 123 1+3+2 = 6 1+3-2 = 2 1+3*2 = 7 1+3/2 = 2.5 1+32 = 33 1-3+2 = 0 1-3-2 = -4 1-3*2 = -5 1-3/2 = -0.5 1-32 = -31 1*3+2 = 5 1*3-2 = 1 1*3*2 = 6 1*3/2 = 1.5 1*32 = 32 1/3+2 = 2.3333333333333 1/3-2 = -1.6666666666667 1/3*2 = 0.66666666666667 1/3/2 = 0.16666666666667 1/32 = 0.03125 13+2 = 15 13-2 = 11 13*2 = 26 13/2 = 6.5 132 = 132 2+1+3 = 6 2+1-3 = 0 2+1*3 = 5 2+1/3 = 2.3333333333333 2+13 = 15 2-1+3 = 4 2-1-3 = -2 2-1*3 = -1 2-1/3 = 1.6666666666667 2-13 = -11 2*1+3 = 5 2*1-3 = -1 2*1*3 = 6 2*1/3 = 0.66666666666667 2*13 = 26 2/1+3 = 5 2/1-3 = -1 2/1*3 = 6 2/1/3 = 0.66666666666667 2/13 = 0.15384615384615 21+3 = 24 21-3 = 18 21*3 = 63 21/3 = 7 213 = 213 2+3+1 = 6 2+3-1 = 4 2+3*1 = 5 2+3/1 = 5 2+31 = 33 2-3+1 = 0 2-3-1 = -2 2-3*1 = -1 2-3/1 = -1 2-31 = -29 2*3+1 = 7 2*3-1 = 5 2*3*1 = 6 2*3/1 = 6 2*31 = 62 2/3+1 = 1.6666666666667 2/3-1 = -0.33333333333333 2/3*1 = 0.66666666666667 2/3/1 = 0.66666666666667 2/31 = 0.064516129032258 23+1 = 24 23-1 = 22 23*1 = 23 23/1 = 23 231 = 231 3+1+2 = 6 3+1-2 = 2 3+1*2 = 5 3+1/2 = 3.5 3+12 = 15 3-1+2 = 4 3-1-2 = 0 3-1*2 = 1 3-1/2 = 2.5 3-12 = -9 3*1+2 = 5 3*1-2 = 1 3*1*2 = 6 3*1/2 = 1.5 3*12 = 36 3/1+2 = 5 3/1-2 = 1 3/1*2 = 6 3/1/2 = 1.5 3/12 = 0.25 31+2 = 33 31-2 = 29 31*2 = 62 31/2 = 15.5 312 = 312 3+2+1 = 6 3+2-1 = 4 3+2*1 = 5 3+2/1 = 5 3+21 = 24 3-2+1 = 2 3-2-1 = 0 3-2*1 = 1 3-2/1 = 1 3-21 = -18 3*2+1 = 7 3*2-1 = 5 3*2*1 = 6 3*2/1 = 6 3*21 = 63 3/2+1 = 2.5 3/2-1 = 0.5 3/2*1 = 1.5 3/2/1 = 1.5 3/21 = 0.14285714285714 32+1 = 33 32-1 = 31 32*1 = 32 32/1 = 32 321 = 321

投稿2017/02/16 23:05

編集2017/02/20 05:36
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/02/16 23:21 編集

ん?0を作るのか。。。ちょっとやり方違いますね^^; 組み合わせとして、0が出来た時点で終了で良いですね。 その組み合わせ X 残り が全て 0 となるので、カウントだけ上げればイイです。 でも、ループの中で都度計算させるのも、無駄が多いですね。悩ましい。。。 どれ位、0 になる組み合わせがあるかによりますが、最初の提案のほうがきれいでいいかも。
hahu333

2017/02/17 09:34

回答ありがとうございます。ソースコードを少し修正、追加してみたのでよろしければまたご意見をお聞きしたいです。
退会済みユーザー

退会済みユーザー

2017/02/17 09:46

ごめんなさい。Ruby はよくわからないんです。 あと、コメントで0がでれば~と書きましたが、()を使えないので、*0 を継続できないですね。ちょっと他のところで指摘していただいて気が付きました。 あまり役に立つ回答でなくてすみません^^;
guest

0

小町算を Ruby で解いてみようAdd Star
こちらのプログラムの
puts b if eval(eb) == 100を
count += 1 if eval(eb) == 0に変更したら
良いのでは。

投稿2017/02/17 23:03

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問