ユーザー指定の数値を使用して有効な方程式を生成します


10

これは、中学校で数学の先生がプレイしていたゲームに基づいています。彼はボードに5つのランダムな1桁の数字を書き、次にランダムな2桁の数字を書きます。5桁の1桁の数値すべてを使用して2桁の数値を求める方程式を作成しようとします。これをよりよく説明するためのソリューションの例をいくつか示します。

Input:           Solution:
7 5 4 8 4 34     5*8-7+4/4 = 34
3 1 5 7 6 54     (7+3)*6-5-1 = 54
3 9 2 1 6 87     9*(2+1)*3+6 = 87
2 1 6 9 7 16     (9-7+6*1)*2 = 16
2 4 5 8 6 96     8*(5+6)+2*4 = 96
3 8 4 5 4 49     8*(4+4)-3*5 = 49

この課題は、特定の入力に対してそのような方程式を生成できるプログラムを作成することです。入力は、コマンドラインまたはプロンプトを介して提供できます。5つの1桁の数字は常に最初に(順不同で)入力され、その後に2桁の数字が続きます。次に、プログラムは見つけた解の方程式を出力します。解決策がない状況を処理する必要はありません。関数は、方程式で次の演算を使用できる必要があります:加算、減算、乗算、および除算。追加の基本的な操作を許可したい場合は、それらが課題の精神にとどまっている限り問題ありません(否定、指数、およびモジュラスは良い追加です)。演算の順序は標準の数学規則に従うため、グループ化には括弧が必要になります。

プログラムは、コード長(必要な空白を含む)に基づいて採点されます。注:除算は正確で、最も近い整数に丸められたり、切り捨てられたりしてはなりません。



これは非常によく似たタスクですが、式をグループ化する方法に制限を加えずに追加することで、問題が大きく異なって興味深いものになると思います。さらに、これはコードチャレンジではなくゴルフチャレンジであり、さまざまなソリューションが必要になります。
Sir_Lagsalot

連結についてはどうですか?たとえば、7 5 4 8 4 34を指定すると、出力7 + 54/8 * 4が許可されますか?
Patrick Roberts

回答:


7

Python 2.7(284)、Python 3.x(253)

from __future__ import division #(Remove for Python 3.x)
from itertools import *
a=raw_input().split()
for i in permutations(a[:-1],5):
 for j in product('+-*/',repeat=5):
  for k,l in combinations(range(1,12,2),2):
   d=''.join(sum(zip(i,j),()))[:-1];d='('+d[:l]+')'+d[l:]
   if eval(d)==int(a[-1]):print d;b

bソリューションでエラー(不明な関数の呼び出し)が発生します。

基本的に、それは巨大な総当たりです。入力を受け取り、スペース(1 2 -> [1,2])で分割し、そのリストを並べ替えます。すべての順列で、文字を使用して長さ5のすべての可能な文字列を反復処理します+-*/。これらの各反復で、リストの長さ2の組み合わせを生成し[1,3,5,7,9,11]、順列と文字列を織り交ぜて(12345 *-/+- -> 1*2-3/4+5-)、かっこを付けます。最後にそれを評価し、答えと方程式が真であれば、方程式を出力して停止します。

これは恐ろしく非効率O(n!/(n-5)!)=O(n^5)的ですが、テスト入力に対して妥当な時間で実行されます。


1
除算を使用すると、整数演算により誤った出力が発生する可能性があります。たとえば、「3 6 8 7 1 29」と入力すると、「(3 + 8/6)* 7 + 1」が生成されます。これは、29ではなく31 1/3になります。これを明示的にするために、説明を更新します。
Sir_Lagsalot

それは(3/6)*8*7+1私に与えます。
beary605 2012年

わかりました、私が使用した通訳の問題としてそれを書き直します。
Sir_Lagsalot

3

Scala 368:

2番目のg = -Lineはテストがより簡単で、最初のコマンドはコマンド引数をとるのに柔軟性があり、どちらも同じ長さなので、2番目のものから数えるだけです-引数を渡すために削除します。

val g=(args.map(_.toDouble))
val g=Array(3,9,2, 1, 6, 87)
val k="+*/-DQ"
val i=(0 to 5)
val f:Seq[(Double,Double)=>Double]=Seq(_+_,_*_,_/_,_-_,(a,b)=>b-a,(a,b)=>b/a)
val h=g.init.permutations;
for(j<-h;o<-i;p<-i;q<-i;r<-i;z=try{f(r)(f(q)(f(p)(f(o)(j(0),j(1)),j(2)),j(3)),j(4))}catch{case _ => 0}
if(z==g(5)))printf("(((%d%c%d)%c%d)%c%d)%c%d=%d\n",j(0),k(o),j(1),k(p),j(2),k(q),j(3),k(r),j(4),g(5))

出力例(今質問があるかもしれません-少しの間):

(((5+7)/1)+6)*3=54
(((5-7)D1)*6)*3=54
(((5D7)+1)*6)*3=54
(((5+7)+6)Q1)Q3=54

この5D7のことはどうですか?D1?16進数ですか?Q1、Q3があります-それは何ですか。

Sir_Lagsalotはチャレンジの精神で新しい基本操作を許可しました。そうです、これらは基本操作であるDeltaとQuotientです。

これらは、aQbがb / aを意味し、aDbがbaを意味するという点で、a / bおよびabとは異なります。それをウクライナ語表記と呼びましょう。

そう

(((5-7)D1)*6)*3=54

手段

((1-(5-7))*6)*3=54
 (1-(-2))*6*3
   3*6*3 = 18*3=54

方法と理由に関するより興味深い質問へ:最初に、括弧を配置する可能性、および(a + b)-c = a + bc =(a + bc)=((a + b )-c)=(b + a)-cなど。あなたはこの質問に腹を立てることができますが、可能な括弧の組み合わせを書き留めると、スクラッチシートを捨てて事実に直面することがあります。パターンが常に(((_x_)x_)x_)x_ ?= _(xは4つの演算子の1つ)であり、反対方向(xb)と(bxa)を許可する場合、すべての可能性に対処しました。

a + bとa * bの場合、反対方向は必要ありません。交換可能です。そこで、方向を切り替えるだけのDおよびQ演算子を発明しました。オペレーターが2人増えましたが、方向を切り替える必要はありません。まあ-それは関数シーケンスで行われます:

 (a,b)=>b-a,(a,b)=>b/a

私の理解のために、配列gから値を取得し、それらをaからeに分散します。次に、4つのインデックスを選択して関数を選択し、後で(インデックスのみで)関連する演算子記号を選択します。サンプルの入力データには0が含まれていませんが、減算によってゼロになる可能性があるため、div / 0エラーをキャッチする必要があります。


DeltaおよびQuotientオペレーターは問題ありません。ただし、ゴルフを計画している場合は、出力に括弧を追加する必要があります。
Sir_Lagsalot 2012年

出力に括弧が表示されます。
ユーザー不明。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.