最小限のマッチ棒で数学を作る


15

メタバックグラウンド

これはPuzzlingの質問として設定されており、即座の反応は「まあ、誰かがそれをコンピューターで解決するだけです」でした。これを解決するプログラムがどれほど複雑であるかについての議論がありました。「このプログラムの複雑さ」は定義であるため、PPCGで問題を解決できるかもしれません。

バックグラウンド

マッチ棒の方程式は、基本的に通常の数学的方程式であるが、数字や演算子は、テーブルの上にマッチ棒を配置することによって物理的に構築されます。(ここでのマッチスティックの主な関連機能は、かなり堅く、一定の長さを持っていることです。時々、綿棒など、他のオブジェクトを代わりに使用します。)

このチャレンジでは、マッチスティックの配置方法に関する特定のルールを定義する必要はありません(リンクされたチャレンジのように)。むしろ、指定された数に評価される式を表すために必要なマッチスティックの数に注意するだけです。

タスク

使用できる数字のアルファベットと数学演算子は次のとおりです。それぞれにマッチスティックのコストがあります。

  • 0、6本のマッチ棒
  • 1、2本のマッチ棒
  • 2、5本のマッチ棒
  • 3、5本のマッチ棒
  • 4、4本のマッチ棒
  • 5、5本のマッチ棒
  • 6、6本のマッチ棒
  • 7、マッチ棒3本がかかる
  • 8、7本のマッチ棒
  • 9、6本のマッチ棒
  • +、2本のマッチ棒
  • -、マッチ棒1本
  • ×、2本のマッチ棒

(あなたは表すことができる×よう*必要に応じて、ほとんどのエンコーディングでは、非ASCII文字を使用する必要がないようにするために、あなたのプログラムの出力に×占める以上のバイト*、と私はほとんどのプログラムは、この余裕を利用したいということを想像して)

(負の整数を入力として(任意の妥当な手段を介して)受け取り、その整数を出力として(再び任意の妥当な手段を介して)評価する式を生成するプログラムを作成する必要があります。また、式は自明である必要があります。それは、少なくとも一つのオペレータが含まれている必要があり+-または×。最後に、出力する式は、そうでなければ仕様に準拠するすべての出力の中で、マッチ棒の総コストの観点から最も安価(または最も安価に結び付けられる)でなければなりません。

明確化

  • 行に複数の数字を出力することで、複数の数字を作成できます(たとえば11-1、有効な出力です10)。正確に言うと、結果の数値は10進数で解釈されます。この種の連結は、中間結果に対して機能する操作ではありません。元の式に現れるリテラル数字のみ。
  • この課題のために。+-×中置演算子です。彼らは左と右への議論が必要です。+5またはのようなプレフィックス位置でそれらを使用することはできません-8
  • 括弧(または優先順位を制御する他の方法)がありません。式は、一般的なデフォルトの優先順位規則に従って評価されます(乗算が最初に発生し、次に加算と減算が左から右に評価されます)。
  • 上記以外の数学演算子や定数にはアクセスできません。「ラテラル思考」ソリューションは、Puzzlingでしばしば受け入れられますが、コンピューターにそれ自体を考え出すことを要求することは意味がありません。PPCGでは、ソリューションが正しいかどうかを客観的にすることが望ましいです。
  • 通常の整数オーバーフロールールが適用されます。ソリューションは、すべての整数がデフォルトで制限されていない仮想バージョン(または実際のバージョン)の任意の大きな整数で動作できる必要がありますが、実装によりプログラムが実際に失敗する場合それほど大きな整数をサポートしていなくても、ソリューションは無効になりません。
  • 同じ数字または演算子を複数回使用する場合、使用するたびにマッチスティックコストを支払う必要があります(明らかに、テーブル上の2つの異なる場所で同じ物理的なマッチスティックを再利用できないためです)。
  • 時間制限はありません。ブルートフォースソリューションは許容されます。(ブルートフォースよりも高速なソリューションがある場合は、それが長くても自由に投稿してください。代替アプローチがどのように比較されるかを見るのは常に興味深いです。)
  • コードの説明を書く必要はありません、それは良い考えです。ソリューションは、読むのが非常に難しい場合があります(特に、記述されている言語に精通していない人にとっては)、そしてその仕組みを理解しない限り、ソリューションを評価する(したがって投票する)のは難しい場合があります。

勝利条件

挑戦として、より少ないバイトでの答えはより良いと考えられます。ただし、いつものように、さまざまなアプローチで回答を投稿したり、特定の言語で回答を投稿したりしても、特定の他の言語よりも冗長である場合があります。ゴルフの目標は、特定のプログラムを最適化できる範囲を実際に確認することであり、この方法で物事を行うと、最適化する多くの潜在的なプログラムが得られます。だから誰かが完全に異なるアプローチまたはまったく異なる言語を使用してソリューションを提出し、はるかに短い答えを得たとしても、落胆しないでください。あなたの答えがより最適化されており、より多くのスキルを示しているのかもしれません。PPCGの投票者はしばしばそれを高く評価しています。


うん、私たちが処理する必要がある最高の数は何ですか?私の現在の試みは、TIOでおそらく20を超えることはありません。
魔法のタコUr

@carusocomputing:理論上は任意ですが、実際に合理的な時間内に20を超えることができない場合、それは完全に受け入れられます。

4
テストケースはありますか?
ルーク

これが単一の操作であり、複数のコンペティションに対して広まったことを本当に望みます。乗算は除数の問題ですが、足し算と引き算を足すと事態は本当に複雑になります。動作するソリューションがありますが、加算と減算には使用できません。その作業を完全に行うのは退屈です。
魔法のタコUr

@carusocomputing:このチャレンジに興味があるかもしれません。乗算のみの課題は大きく異なり、良いスコアを得るにはかなり異なる解法が必要だと思います。

回答:


1

Python2、1̶9̶8̶̶b̶y̶t̶e̶s̶math_junkieにより182バイト

def f(n,c=dict(zip('0123456789+-*',map(int,'6255456376212'))),e=[(0,'')]):
 while 1:
    v=(m,s)=min(e);e.remove(v)
    try:
     if eval(s)==n:return s
    except:0
    e+=[(m+c[x],s+x)for x in c]

このアルゴリズムは、+およびの接頭辞バージョンを除外するために何も行いません-が、それらは、中置の対応するものよりも悪いか、等しいか、検索の後半に表示されます。キーワード引数をe変更可能に使用するため、セッションごとに複数回呼び出された場合、無効な結果が返されます。これを修正するには、のf(n, e=[(0,'')])代わりにを使用してくださいf(n)。4スペースのインデントはタブを表すため、これはPython 2でのみ機能することに注意してください。

また、非常に多くの数でも迅速に実行される、最適化されていないバージョンがあります。

from heapq import heappop, heappush

def f(n):
    digits = list('0123456789')
    ops =['+','-','*','']
    costs = dict(zip(digits + ops, [6,2,5,5,4,5,6,3,7,6,2,1,2,0]))
    expressions = [(costs[d], abs(n - int(d)), int(d), d) for d in digits[1:]]
    seen = set()
    while 1:
        cost, d, k, expression = heappop(expressions)
        if d == 0:
            return expression
        for op in ops:
            if op in '+-' and k in seen:
                continue
            for digit in digits:
                if op and digit == '0':
                    continue
                expression1 = expression + op + digit
                k1 = eval(expression1)
                d1 = abs(n - k1)
                if d1 == 0:
                    return expression1
                heappush(expressions, (cost+costs[op]+costs[digit], d1, k1, expression1))
        seen.add(k)

いくつかのマイナーな提案ゴルフ:TIO(182バイト)
数学中毒

1

PHP、241バイト

オンライン版

function m($i){for(;$s<strlen($i);)$e+="6255456376"[$i[$s++]];return$e;}foreach($r=range(0,2*$a=$argv[1])as$v)foreach($r as$w)$x[$v+$w]["$v+$w"]=$x[$v*$w]["$v*$w"]=1+$x[$v-$w]["$v-$w"]=m("$v")+m("$w")+1;echo array_search(min($x[$a]),$x[$a]);

壊す

function m($i){
    for(;$s<strlen($i);)$e+="6255456376"[$i[$s++]];return$e; #return the count of the matchstick for an integer
}

foreach($r=range(0,2*$a=$argv[1])as$v) # limit to an input to 300 in the online version
foreach($r as$w)
       $x[$v+$w]["$v+$w"]=  #fill the 2D array in the form [result][expression] = count matchsticks
       $x[$v*$w]["$v*$w"]=
       1+$x[$v-$w]["$v-$w"]=
       m("$v")+m("$w")+1;
echo $k=array_search(min($x[$a]),$x[$a]); # Output expression with a minium of matchsticks
echo"\t".$x[$a][$k]; #optional Output of the count of the matchsticks

パフォーマンスが少し向上した方法

function m($i){
for(;$s<strlen($i);)
$e+="6255456376"[$i[$s++]];return$e;} #return the count of the matchstick for an integer
foreach($r=range(0,2*$a=$argv[1])as$v)
foreach($r as$w){$c=m("$v")+m("$w")+1;
if($a==$v+$w)$x["$v+$w"]=1+$c; # fill array if value equal input
if($a==$v*$w)$x["$v*$w"]=1+$c;
if($a==$v-$w)$x["$v-$w"]=$c;}
echo $k=array_search(min($x),$x); # Output expression with a minium of matchsticks
    echo"\t".$x[$k]; #optional Output of the count of the matchsticks

負の整数のサポート

負の整数を持つバージョン

function m($i){
    $e=$i<0?1:0; # raise count for negative integers
    for($s=0;$s<strlen($i);)$e+=[6,2,5,5,4,5,6,3,7,6][$i[$s++]];return$e; #return the count of the matchstick for an integer
}
$q=sqrt(abs($argv[1]));
$l=max(177,$q);
$j=range(-$l,$l); # for second loop for better performance
foreach($r=range(min(0,($a=$argv[1])-177),177+$a)as$v) 
foreach($j as$w){$c=m("$v")+m("$w")+1;  
    if($a==$v+$w)$x["$v+$w"]=1+$c; # fill array if value equal input
    if($a==$v*$w)$x["$v*$w"]=1+$c;
    if($a==$v-$w)$x["$v-$w"]=$c;
    if($a==$w-$v)$x["$w-$v"]=$c; # added for integers <0
}
echo $k=array_search(min($x),$x); # Output expression with a minium of matchsticks
echo"\t".$x[$k]; #optional Output of the count of the matchsticks

ああ、これは負の数でも機能します!
魔法のタコUr

@carusocomputingは、マッチスティックの少ないソリューションが存在する可能性がありますが、負の数は減算によってのみ加算されます。この場合、絶対値もチェックして、1を追加する必要があります
ヨルグヒュルサーマン

リテラル333はここでは受け入れられないと思いますが、おそらく入力の何らかの機能にすることで修正できます。(プログラムの実行速度はかなり遅くなる可能性があるため、テスト用にハードコードされたバージョンを保持できます。)

1
@ ais523 done 333は2 * inputに置き換えられました
ヨルグヒュルサーマン

1
文字列にインデックスを付けることができます$e+="6255456376"[$i[$s++]];
マナトワーク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.