Mache Mathematik mit minimalen Streichhölzern

15

Meta-Hintergrund

Dies wurde als Frage zu Puzzling gestellt und die sofortige Reaktion lautete "Nun, jemand wird das einfach per Computer lösen". Es gab eine Debatte darüber, wie komplex ein Programm zur Lösung dieses Problems sein müsste. Nun, "wie komplex muss dieses Programm sein" ist so ziemlich die Definition von , also kann PPCG das Problem vielleicht lösen?

Hintergrund

Eine Matchstick-Gleichung ist im Grunde eine normale mathematische Gleichung, bei der jedoch die Ziffern und Operatoren physikalisch konstruiert werden, indem Matchsticks auf einen Tisch gelegt werden. (Das wichtigste relevante Merkmal von Streichhölzern ist, dass sie ziemlich steif sind und eine konstante Länge haben. Manchmal verwenden die Leute stattdessen andere Gegenstände, wie Wattestäbchen.)

Für diese Herausforderung müssen wir keine spezifischen Regeln für die Anordnung der Streichhölzer definieren (wie bei der verknüpften Herausforderung). Es geht uns nur darum, wie viele Streichhölzer wir benötigen, um einen Ausdruck darzustellen, der eine bestimmte Zahl ergibt.

Die Aufgabe

Hier ist ein Alphabet mit Ziffern und mathematischen Operatoren, die Sie verwenden können und die jeweils Kosten in Streichhölzern haben:

  • 0, kostet 6 Streichhölzer
  • 1, kostet 2 Streichhölzer
  • 2, kostet 5 Streichhölzer
  • 3, kostet 5 Streichhölzer
  • 4, kostet 4 Streichhölzer
  • 5, kostet 5 Streichhölzer
  • 6, kostet 6 Streichhölzer
  • 7, kostet 3 Streichhölzer
  • 8, kostet 7 Streichhölzer
  • 9, kostet 6 Streichhölzer
  • +, kostet 2 Streichhölzer
  • -, kostet 1 Streichholz
  • ×, kostet 2 Streichhölzer

(Sie können ×wie *in der Ausgabe Ihres Programms darstellen, wenn Sie möchten, um die Verwendung von Nicht-ASCII-Zeichen zu vermeiden. In den meisten Codierungen ×werden mehr Bytes als benötigt *, und daher kann ich mir vorstellen, dass die meisten Programme diesen Spielraum nutzen möchten .)

Sie müssen ein Programm schreiben, das eine nichtnegative Ganzzahl als Eingabe verwendet (mit vernünftigen Mitteln ) und einen Ausdruck erzeugt, der diese Ganzzahl als Ausgabe auswertet (wiederum mit vernünftigen Mitteln). Darüber hinaus muss der Ausdruck nicht trivial sein: es mindestens einen Operator enthalten muss +, -oder× . Schließlich muss der von Ihnen ausgegebene Ausdruck unter allen Ausgaben, die ansonsten der Spezifikation entsprechen, der billigste (oder der billigste) in Bezug auf die Gesamtkosten des Streichholzes sein.

Klarstellungen

  • Sie können mehrstellige Zahlen bilden, indem Sie mehrere Ziffern hintereinander ausgeben (z. B. 11-1ist eine gültige zu erzeugende Ausgabe 10). Um ganz genau zu sein, wird die resultierende Zahl dezimal interpretiert. Diese Art der Verkettung ist keine Operation, die mit Zwischenergebnissen arbeitet. Nur für Literalziffern, die im ursprünglichen Ausdruck enthalten sind.
  • Zum Zweck dieser Herausforderung. +, -Und ×sind Infixoperatoren; Sie brauchen einen Streit zu ihrer Linken und zu ihrer Rechten. Sie dürfen sie nicht in Präfixpositionen wie +5oder verwenden -8.
  • Sie haben keine Klammern (oder eine andere Möglichkeit, die Priorität zu steuern) zur Verfügung. Der Ausdruck wird gemäß den typischen Standardprioritätsregeln ausgewertet (Multiplikationen werden zuerst durchgeführt, und dann werden die Additionen und Subtraktionen von links nach rechts ausgewertet).
  • Sie haben keinen Zugriff auf andere mathematische Operatoren oder Konstanten als die oben aufgeführten. "Querdenken" -Lösungen werden bei Puzzling oft akzeptiert, aber es ist nicht sinnvoll, einen Computer zu fordern, der sie selbst entwickelt, und hier bei PPCG möchten wir, dass es objektiv ist, ob eine Lösung richtig ist oder nicht.
  • Es gelten die üblichen Überlaufregeln für Ganzzahlen: Ihre Lösung muss in der Lage sein, für beliebig große Ganzzahlen in einer hypothetischen (oder möglicherweise realen) Version Ihrer Sprache zu arbeiten, in der standardmäßig alle Ganzzahlen unbegrenzt sind, Ihr Programm jedoch aufgrund der Implementierung in der Praxis fehlschlägt Ganzzahlen, die so groß sind, werden nicht unterstützt, was die Lösung nicht ungültig macht.
  • Wenn Sie dieselbe Ziffer oder denselben Operator mehrmals verwenden, müssen Sie die Matchstick-Kosten bei jeder Verwendung bezahlen (da Sie natürlich nicht dieselben physischen Matchsticks an zwei verschiedenen Stellen auf dem Tisch wiederverwenden können).
  • Es gibt keine zeitliche Begrenzung. Brute-Force-Lösungen sind akzeptabel. (Auch wenn Sie eine Lösung haben, die schneller als Brute Force ist, können Sie sie gerne veröffentlichen, auch wenn sie länger ist. Es ist immer interessant zu sehen, wie sich alternative Ansätze vergleichen lassen.)
  • Obwohl es niemals erforderlich ist , eine Erklärung für Ihren Code zu schreiben , ist dies wahrscheinlich eine gute Idee. Lösungen sind oft sehr schwer zu lesen (insbesondere für Leute, die mit der Sprache, in der sie geschrieben sind, nicht vertraut sind), und es kann schwierig sein, eine Lösung zu bewerten (und somit darüber abzustimmen), es sei denn, Sie verstehen, wie sie funktioniert.

Siegbedingung

Als Herausforderung werden Antworten mit weniger Bytes als besser angesehen. Sie können jedoch wie gewohnt Antworten mit unterschiedlichen Ansätzen oder in bestimmten Sprachen veröffentlichen, auch wenn diese ausführlicher sind als bestimmte andere Sprachen. Das Ziel des Golfsports ist es wirklich zu sehen, inwieweit Sie ein bestimmtes Programm optimieren können, und diese Vorgehensweise bietet uns viele potenzielle Optimierungsprogramme. Lassen Sie sich also nicht entmutigen, wenn jemand eine Lösung mit einem völlig anderen Ansatz oder einer völlig anderen Sprache vorlegt und eine viel kürzere Antwort erhält. Es ist gut möglich, dass Ihre Antwort besser optimiert ist und mehr Fähigkeiten zeigt, und die Wähler von PPCG wissen das oft zu schätzen.

Gemeinschaft
quelle
Meine Güte, was ist die höchste Zahl, die wir behandeln müssen? Mein aktueller Versuch würde nicht jenseits von ... vielleicht 20 auf TIO laufen.
Magic Octopus Urn
@carusocomputing: Willkürlich hoch in der Theorie , aber wenn Sie nicht über 20 innerhalb einer angemessenen Frist in der Praxis bekommen, das ist völlig akzeptabel.
4
Haben Sie Testfälle?
Luke
Ich wünschte wirklich, dies wäre eine einzige Operation, die gegen mehrere Wettbewerbe ausgetragen wird. Die Multiplikation ist ein Divisorproblem, aber das Addieren von Addition und Subtraktion erschwert die Sache wirklich. Ich habe eine Lösung, die funktioniert, aber nicht für die Addition und Subtraktion; es wird mühsam sein, das perfekt zu machen.
Magic Octopus Urn
@carusocomputing: Diese Herausforderung könnte Sie also interessieren . Ich vermute, dass die Herausforderung bei der Multiplikation nur erheblich anders ist und ziemlich unterschiedliche Lösungstechniken erfordern würde, um eine gute Punktzahl zu erzielen.

Antworten:

1

Python2, 1̶9̶8̶ ̶b̶y̶t̶e̶s̶ 182 Bytes dank math_junkie

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]

Dieser Algorithmus schließt Präfixversionen von +und nicht aus -, aber sie sind entweder schlechter als ihre infix-Gegenstücke oder gleich und erscheinen später in der Suche. Da das Schlüsselwortargument everänderlich verwendet wird, gibt es ungültige Ergebnisse, wenn es mehrmals pro Sitzung aufgerufen wird. Um dies zu beheben, verwenden Sie f(n, e=[(0,'')])statt nur f(n). Beachten Sie, dass die vier Einrückungen Registerkarten darstellen, sodass dies nur mit Python 2 funktioniert.

Ich habe auch eine ungolfed und optimierte Version, die auch bei größeren Stückzahlen schnell läuft:

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)
user1502040
quelle
Einige kleinere Golfvorschläge: TIO (182 Bytes)
Math Junkie
1

PHP, 241 Bytes

Online Version

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]);

Nervenzusammenbruch

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

Weg mit etwas besserer Leistung

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

Unterstützung negativer Ganzzahlen

Version mit negativen ganzen Zahlen

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
Jörg Hülsermann
quelle
Oh nein, das funktioniert auch mit negativen Zahlen!
Magic Octopus Urn
@carusocomputing Eigentlich konnte es nicht sein, dass eine Lösung mit weniger Streichhölzern existiert, da negative Zahlen nur durch Subtraktion addiert werden. In diesem Fall sollten Sie auch den absoluten Wert überprüfen und einen hinzufügen
Jörg Hülsermann
Ich denke nicht, dass das Literal 333 hier akzeptabel wäre, obwohl Sie es wahrscheinlich beheben könnten, indem Sie es in eine Funktion der Eingabe umwandeln. (Das Programm läuft möglicherweise viel langsamer, sodass Sie die fest codierte Version zum Testen behalten können.)
1
@ ais523 getan 333 wird durch 2 * Eingabe ersetzt
Jörg Hülsermann
1
Sie können Index - Strings: $e+="6255456376"[$i[$s++]];.
Manatwork