최소한의 성냥개비로 수학 만들기


15

메타 배경

이것은 Puzzling에 대한 질문 으로 설정되었으며 즉각적인 반응은 "글쎄, 누군가는 컴퓨터로 그것을 해결할 것입니다". 이를 해결하기위한 프로그램이 얼마나 복잡해야하는지에 대한 논쟁이있었습니다. "이 프로그램은 얼마나 복잡해야 합니까? "는 의 정의와 거의 비슷 하므로 PPCG가 문제를 해결할 수 있을까요?

배경

성냥 방정식 의 숫자 및 작업자가 테이블 상에 배치하여 성냥개비 물리적으로 구성되는 경우, 기본적으로 통상의 수학 식이지만. (여기에서 성냥개비의 주요 관련 기능은 상당히 단단하고 길이가 일정하다는 것입니다. 사람들은 면봉과 같은 다른 물체를 대신 사용하기도합니다.)

이 도전을 위해, 우리는 성냥개비가 어떻게 배열되는지에 대한 특정 규칙을 정의 할 필요가 없습니다 (링크 된 도전과 같이); 오히려, 우리는 주어진 숫자로 평가되는 표현식을 나타 내기 위해 몇 개의 성냥개비가 필요한지에 관심이 있습니다.

작업

다음은 사용할 수있는 숫자와 수학 연산자이며 각각은 성냥개비입니다.

  • 0, 6 성냥개비 비용
  • 1, 성냥개비 2 개
  • 2, 5 성냥개비 비용
  • 3, 5 성냥개비 비용
  • 4, 성냥개비 4 개
  • 5, 5 성냥개비 비용
  • 6, 6 성냥개비 비용
  • 73 개의 성냥개비
  • 8, 7 성냥개비 비용
  • 9, 6 성냥개비 비용
  • +, 성냥개비 2 개
  • -, 성냥개비 1 개
  • ×, 성냥개비 2 개

( ASCII 이외의 문자를 사용할 필요가 없도록하기 위해 원하는 경우 프로그램의 출력에서 ×와 같이 표현할 수 있습니다 *. 대부분의 인코딩에서 ×보다 많은 바이트를 차지 *하므로 대부분의 프로그램이이 여유를 활용하려고합니다. .)

음수가 아닌 정수를 입력으로 사용하고 ( 합리적인 방법을 통해 ) 해당 정수를 출력으로 평가하는 식 ( 합리적인 방법을 통해)을 작성하는 프로그램을 작성해야합니다 . 또한, 표현은 사소해야합니다 : 그것은 적어도 하나의 연산자를 포함해야합니다 +, -또는 ×. 마지막으로, 출력하는 표현식은 사양을 준수하는 모든 출력 중에서 총 성냥개비 비용 측면에서 가장 저렴하거나 가장 저렴한 묶음이어야합니다.

설명

  • 행에 여러 자릿수를 출력하여 여러 자릿수를 형성 할 수 있습니다 (예 : 11-1유효한 출력 10). 정확히 말하면 결과 숫자는 10 진수로 해석됩니다. 이러한 종류의 연결은 중간 결과에서 작동하는 작업이 아닙니다. 원래 표현식에 나타나는 리터럴 숫자에만 해당됩니다.
  • 이 도전의 목적을 위해. +, -×중위 연산자입니다. 그들은 왼쪽과 오른쪽에 대한 논쟁이 필요합니다. +5또는 과 같은 접두사 위치에서 사용할 수 없습니다 -8.
  • 사용할 수있는 괄호 (또는 우선 순위를 제어하는 ​​다른 방법)가 없습니다. 이 표현은 일반적인 기본 우선 순위 규칙에 따라 평가됩니다 (곱셈이 먼저 발생한 다음 더하기와 빼기가 왼쪽에서 오른쪽으로 평가됨).
  • 위에 나열된 것 이외의 수학 연산자 나 상수에 액세스 할 수 없습니다. "측면 적 사고"솔루션은 종종 퍼즐 링 (Puzzling)에서 받아 들여지지 만, 컴퓨터가 그들 스스로를 제시하도록 요구하는 것은 이치에 맞지 않으며, 여기 PPCG에서는 해결책이 정확한지 아닌지 객관적인 것이 좋습니다.
  • 일반적인 정수 오버플로 규칙이 적용됩니다. 솔루션은 기본적으로 모든 정수가 바인딩되지 않은 가상의 (또는 아마도 실제) 버전의 언어에서 임의로 큰 정수를 사용할 수 있어야하지만 구현으로 인해 프로그램이 실제로 실패하는 경우 큰 정수를 지원하지 않으면 솔루션이 무효화되지 않습니다.
  • 동일한 숫자 또는 연산자를 두 번 이상 사용하는 경우 매번 사용할 때마다 해당 성냥개비를 지불해야합니다 (표의 두 위치에서 동일한 물리적 성냥개비를 재사용 할 수 없기 때문입니다).
  • 시간 제한이 없습니다. 무차별 대입 솔루션이 허용됩니다. (무차별적인 해결책보다 빠른 솔루션을 가지고 있더라도 더 길더라도 자유롭게 게시하십시오. 다른 방법이 어떻게 비교되는지는 항상 흥미 롭습니다.)
  • 코드에 대한 설명을 작성하지 않아도 되지만 좋은 생각 일 수 있습니다. 솔루션은 읽기가 매우 어렵고 (특히 작성된 언어에 익숙하지 않은 사람들에게), 작동 방식을 이해하지 않으면 솔루션을 평가 (투표)하기가 어려울 수 있습니다.

승리 조건

A와 도전, 더 적은 바이트 답변이 더 나은 것으로 간주됩니다. 그러나 평소와 같이 다른 접근 방식이나 특정 언어가 다른 언어보다 더 장황한 경우에도 특정 언어로 답변을 게시 할 수 있습니다. 골프의 목표는 실제로 특정 프로그램을 얼마나 멀리 최적화 할 수 있는지 확인하는 것입니다. 이런 식으로 작업하면 많은 잠재적 인 프로그램을 최적화 할 수 있습니다. 따라서 누군가가 완전히 다른 접근법이나 완전히 다른 언어를 사용하여 솔루션을 제출하고 훨씬 짧은 답변을 얻는다면 실망하지 마십시오. 귀하의 답변이 더 잘 최적화되고 더 많은 기술을 보여 주었을 수도 있으며 PPCG 유권자들은 종종 그 점을 높이 평가합니다.


Jeez, 처리해야 할 가장 높은 숫자는 무엇입니까? 내 현재 시도는 TIO에서 20 정도를 넘지 않을 것입니다.
Magic Octopus Urn

@ carusocomputing : 이론상 임의로는 높지만 , 실제로 합리적인 시간 내에 20 세 이상을 얻을 수 없다면, 그것은 전적으로 허용됩니다.

4
테스트 사례가 있습니까?
Luke

나는 이것이 여러 번의 경쟁에서 펼쳐지는 단일 작업 이었으면 좋겠다. 곱셈은 ​​제수 문제이지만 더하기와 빼기를 더하면 문제가 복잡해집니다. 나는 효과가 있지만 덧셈과 뺄셈에는 해결책이 없습니다. 그 작업을 완벽하게하는 것은 지루할 것입니다.
Magic Octopus Urn

@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]

이 알고리즘은 +and의 접두사 버전을 배제 할 수는 없지만 검색에서 접두사 -보다 나쁘거나 같거나 나중에 나타납니다. 키워드 인수를 e가변적으로 사용하기 때문에 세션 당 여러 번 호출되면 유효하지 않은 결과가 나타납니다. 이 문제를 해결하려면 f(n, e=[(0,'')])just 대신 사용하십시오 f(n). 4 칸 간격의 들여 쓰기는 탭을 나타내므로 Python 2에서만 작동합니다.

또한 상당히 많은 수의 경우에도 빠르게 실행되는 ungolfed 및 최적화 된 버전이 있습니다.

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 bytes)
수학 중독자

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

오, 이건 음수에서도 작동합니다!
Magic Octopus Urn

@carusocomputing 실제로는 성냥 개가 적은 솔루션이 존재하기 때문에 뺄셈만으로 음수가 추가됩니다. 이 경우 절대 값도 확인하고 값을 추가해야합니다.
Jörg Hülsermann

리터럴 333은 여기에서 수용 가능하다고 생각하지는 않지만 입력 기능을 통해 해결할 수는 있습니다. (프로그램이 훨씬 느리게 실행될 수 있으므로 테스트를 위해 하드 코드 된 버전을 유지할 수 있습니다.)

1
333 일 @ ais523 2 * 입력으로 대체됩니다
요 르그 Hülsermann을

1
문자열을 색인 할 수 있습니다 : $e+="6255456376"[$i[$s++]];.
manatwork
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.