성냥개비 방정식


16

이 도전에서 당신의 임무는 이와 같은 주어진 "매치 스틱 방정식"을 분석하는 것입니다 ...

여기에 이미지 설명을 입력하십시오

... 그리고 일치를 다시 정렬하여 유효한 방정식으로 변환 할 수 있는지 확인하십시오. 그렇다면 최소 이동 횟수와 결과 방정식을 출력해야합니다.

입력

입력은 STDIN에서 읽거나 함수 인수로 사용하거나 파일에 저장할 수있는 문자열입니다. 이것은 성냥개비 배열을 나타내는 방정식이며 다음 EBNF를 사용하여 설명 할 수 있습니다.

input = term, "=", term ;
term = number | (term, ("+" | "-"), term) ;
number = "0" | (numeralExceptZero , {numeral}) ;
numeralExceptZero = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
numeral = "0" | numeralExceptZero ;

유효한 입력의 예는입니다 3+6-201=0+0+8.

직무

각 성냥개비에 숫자가 할당되어있는 다음 그림을 고려하십시오.

성냥개비 위치

이제 각 입력 기호를 다음과 같이 해당하는 성냥개비 위치에 매핑합니다.

0 ↦ 1,2,3,4,5,6
1 ↦ 4,5
2 ↦ 2,3,5,6,8
3 ↦ 3,4,5,6,8
4 ↦ 1,4,5,8
5 ↦ 1,3,4,6,8
6 ↦ 1,2,3,4,6,8
7 ↦ 4,5,6
8 ↦ 1,2,3,4,5,6,8
9 ↦ 1,3,4,5,6,8
- ↦ 8
+ ↦ 8,10
= ↦ 7,9

각 입력 공식은 성냥개비 배열로 전환 할 수 있습니다. 예를 들어 방정식 "45 + 6 = 92"는

여기에 이미지 설명을 입력하십시오

사용하지 않는 성냥개비가 회색으로 표시됩니다. 당신의 임무는 방정식을 유효하게하기 위해 재배치 해야하는 가장 적은 수의 성냥개비를 찾는 것입니다.

산출

가능한 세 가지 경우를 구별합니다.

  • 입력이 유효하지 않은 경우 (즉, 위의 EBNF를 만족하지 않는 경우) 원하는 것을 출력하십시오.
  • 그렇지 않으면, 성냥개비를 재배치하여 방정식을 유효한 것으로 바꾸는 방법이 있다면 , 최소 재 배열 횟수 해당 방정식을 모두 출력해야합니다 . 입력과 마찬가지로 출력 방정식도 주어진 EBNF를 만족해야합니다. 위의 예에서 올바른 출력은 and 입니다. 결과 방정식에 여러 가능성이있는 경우 그 중 하나를 출력하십시오.146+6=52
  • 그렇지 않으면 (입력이 유효하지만 방정식을 참으로 만들 수있는 방법이 없다면)을 출력해야합니다 -1.

세부

  • 일치 항목을 제거하거나 추가 할 수 없습니다. 즉, 입력이 n성냥개비로 구성된 경우 출력도 정확히 n성냥개비 로 구성되어야합니다 .
  • "빈"matchstick-blocks는 중간이 아니라 방정식의 끝과 시작에서만 허용됩니다. 따라서, 예를 들어, 회전 7-1=67 =6-1간단하게 제거하여 -1왼쪽에서 단지 3 성냥 재 배열과 오른쪽에 추가는 허용되지 않습니다.
  • 나는 숫자에서 성냥개비 위치로의 매핑을이 도전의 흥미로운 부분으로 보지 않기 때문에 20 바이트 를 더할 수 있습니다.

    • (number/operation ↦ matchstick positions)적절한 방법으로 매핑 이 저장된 파일에 액세스 하거나
    • 프로그래밍 언어가 Map데이터 유형을 지원하는 경우 -mapping으로 사전 초기화 된 맵에 액세스 할 수 있다고 가정하십시오 (number/operation ↦ matchstick positions). 이지도는 예를 들면 다음과 같습니다.{(0,{1,2,3,4,5,6}),(1,{4,5}),(2,{2,3,5,6,8}),(3,{3,4,5,6,8}), ..., (-,{8}),(+,{8,10}),(=,{7,9})}

입력 : 1+1=3출력 : 11+1=2

입력 : 15+6=21출력 : 015+6=21

입력 : 1=7출력 : -1

입력 : 950-250=750출력 : 2990-240=750

입력 : 1-2=9출력 : 11+2=3

입력 : 20 + 3=04출력 : 무엇이든

우승자

이것은 이므로 가장 짧은 정답 (바이트)이 이깁니다. 당첨자는 첫 정답이 게시 된 지 1 주일 후에 선정됩니다.


1
추가 해주세요 0: 1, 2, 3, 4, 5, 6일관성을 위해
Charles

고마워요, 어떻게 든 잊어 버렸습니다!
vauge

@vauge Hey '2 = 1-1'-> '2-1 = 1'은 기술적으로 2를 왼쪽으로 이동해야하므로 3 또는 14 개의 동작을 반환해야합니까?
Cieric

@Cieric 3을 반환해야합니다. 단순히 =(2 개의 성냥개비)와 -(1 개의 성냥개비) 의 위치를 ​​전환하고 모든 숫자를 원래 자리에 그대로 둘 수 있기 때문입니다. 그러나 2를 왼쪽으로 이동해야하는 경우 필요한 이동도 계산해야합니다.
대담

작업 수에 제한이 있습니까? 입력은 같을 수 1+1+2=3-6+10있습니까? 그리고 출력에 대해서도 같은 질문입니다.
Qwertiy 2016 년

답변:


6

자바 스크립트, 1069 바이트

나는 꽤 많은 테스트 방정식으로 테스트했으며 지금은 항상 작동하는 것 같습니다 ...

function w(t){function B(c,f){d=(c.length>f.length?f:c).split("");e=(c.length>f.length?c:f).split("");longer=Math.max(d.length,e.length);if(0!==d.length&&0!==e.length){c=[];for(x in d)for(y in c[x]=[],e)c[x][y]=1<y-x?-1:function(c,n){r=0;for(j in n)-1<c.indexOf(n[j])&&r++;return c.length+n.length-2*r}(a[d[x]],a[e[y]]);return v=function(f,n){for(var h=f.length-2;0<=h;h--)c[n.length-1][h]+=c[n.length-1][h+1];for(h=f.length-2;0<=h;h--)for(var q=0;q<n.length-1;q++)1>=h-q&&(c[q][h]+=-1==c[q][h+1]?c[q+1][h+1]:Math.min(c[q+1][h+1],c[q][h+1]));return c[0][0]/2}(e,d)}return-1}a=[[1,2,3,4,5,6],[4,5],[2,3,5,6,8],[3,4,5,6,8],[1,4,5,8],[1,3,4,6,8],[1,2,3,4,6,8],[4,5,6],[1,2,3,4,5,6,8],[1,3,4,5,6,8]];a["+"]=[8,0];a["-"]=[8];a["="]=[7,9];a[" "]=[];l=0;p=[];u=[];r=/^([1-9]\d*|0)([+-]([1-9]\d*|0))*=([1-9]\d*|0)([+-]([1-9]\d*|0))*$/;b=/(=.*=|[+=-]{2,}|^[+=-])/;if(!t.match(r))return-1;g=function(c,f,t){if(0===t&&f.match(r)&&eval(f.replace("=","==")))c.push(f);else for(var n in a)t>=a[n].length&&" "!=n&&!(f+n).match(b)&&g(c,f+n,t-a[n].length)};g(p,"",function(c){m=0;for(var f in c)m+=a[c[f]].length;return m}(t.split("")));for(var z in p)k=B(t,p[z]),u[k]||(u[k]=[]),u[k].push(p[z]);for(var A in u)return[A,u[A]];return-1}

글쎄, 이것은 처음으로 답변을 제출 한 것이므로, 나는 내 자신이이기는 것을 보지 못한다. 이것은 기본적으로 모든 답을 알아 낸 다음 가장 작은 답을 배열로 반환하는 무차별 대입 방법입니다. 첫 번째 인수는 길이이고 두 번째 인수는 출력이있는 배열입니다.

입력이 "1-2 = 9"이면 출력은 [1, [ "1 + 2 = 3", "7-2 = 5"]]입니다.

압축되지 않은 코드는 다음과 같습니다.

function ms(s) {
a=[[1,2,3,4,5,6],[4,5],[2,3,5,6,8],[3,4,5,6,8],[1,4,5,8],[1,3,4,6,8],[1,2,3,4,6,8],[4,5,6],[1,2,3,4,5,6,8],[1,3,4,5,6,8]];
a["+"] = [8, 0];
a["-"] = [8];
a["="] = [7, 9];
a[" "] = [];
l = 0;
p = [];
u = [];
r = /^([1-9]\d*|0)([+-]([1-9]\d*|0))*=([1-9]\d*|0)([+-]([1-9]\d*|0))*$/;
b = /(=.*=|[+=-]{2,}|^[+=-])/;
if (!s.match(r)) return -1;
function f(g,h)
{
    d=(g.length>h.length?h:g).split('');
    e=(g.length>h.length?g:h).split('');
    longer=Math.max(d.length, e.length);
    if(0!==d.length&&0!==e.length)
    {
        g=[];
        for(x in d)
        {
            g[x]=[];
            for(y in e)
            {
                g[x][y]=(y-x>1)?-1:function(g, h){r=0;for(j in h)if(g.indexOf(h[j])>-1)r++;return g.length+h.length-2*r;}(a[d[x]],a[e[y]]);
            }
        }
        v=function(d,e)
        {
        for(var y=d.length-2;y>=0;y--) g[e.length-1][y]+=g[e.length-1][y+1];
        for(var y=d.length-2;y>=0;y--)
            for(var x=0;x<e.length-1;x++)
                if(y-x<=1)
                    g[x][y]+=g[x][y+1]==-1?g[x+1][y+1]:Math.min(g[x+1][y+1], g[x][y+1]);
        return g[0][0]/2}(e,d)
        return v
    }
    return -1;
}
g=function(n, s, i){if (i===0 && s.match(r) && eval(s.replace('=','=='))){n.push(s);return;}for (var c in a) if(i>=a[c].length && c!=" " && !(s+c).match(b)) g(n, s+c, i-a[c].length);};
g(p, "", function(q){m=0;for(var t in q)m+=a[q[t]].length;return m}(s.split('')));
for (var i in p)
{
    k=f(s, p[i]);
    if (!u[k]) u[k] = [];
    u[k].push(p[i]);
}
for (var q in u) return [q, u[q]];
return -1;
}

경고 : 950-250 = 750과 같은 방정식은 ~ 45 Matchsticks를 사용 하며이 코드는 무차별 대입을 사용하므로 자바 스크립트가 중단됩니다.


var k루프에서와 같이 사용하는 변수를 함수에 사용되지 않는 매개 변수로 선언하여 각 ​​선언마다 3 바이트를 절약 할 수 있다고 생각합니다 .
rorlork

나는 몇 가지 더 많은 프로그래밍 언어를 배우고 그 바이트 카운트를 실제로 쓰러 뜨릴 수있는 무차별 한 방법을 알아낼 것입니다.
Cieric

거리를 계산할 때 항상 등호 문자를 정렬하기 때문에 솔루션이 올바르지 않다고 생각합니다. 어떤 경우에는 최적의 방법이 아닙니다. 예를 들어 '2 = 1-1'은 3 번의 이동에서 '2-1 = 1'로 변환 될 수있는 반면, '='부호를 정렬하면 14 개의 이동이 발생합니다. 또한 나는 당신이 제로를 피하는 방법을 보지 못합니다. 예를 들어 08=8for 80=8가 올바르지 않습니다.
nutki

@nutki 그래, 나는 그것을 바꿀 수 있다고 생각한다. 기술적으로 2를 넘어서 -1
Cieric

@nutki 알았어. 지금 무슨 말인지 알 겠어요 글쎄, 정규식을 수정하고 편집 거리에 대한 코드를 변경할 수 있는지 확인합니다.
Cieric

1

펄, 334

한두 번의 이동으로 솔루션에 도달 할 수있는 한 상당히 빠릅니다. 해결책이 없으면 가장 작은 경우에도 오래 기다립니다.1=7 .

#!perl -p
@y=map{sprintf"%010b",$_}63,24,118,124,89,109,111,56,127,125,64,192,768;
$y{$z{$y[$c++]}=$_}=$y[$c]for 0..9,qw(- + =);
$"="|";$l=s/./$y{$&}/g;$x{$_}=1;for$m(0..y/1//){
last if$_=(map"$m $_",grep{s/@y/$z{$&}/g==$l&&/^\d.*\d$/&!/\D\D/&!/\b0\d/&y/=//==1&&eval s/=/==/r}keys%x)[0];
$_=-1;s/0/"$`1$'"=~s!1!$x{"$`0$'"}=1!ger/eg for keys%x}

예:

$ time perl ~/matchstick.pl <<<950-250=750
2 990-250=740

real    0m39.835s
user    0m39.414s
sys 0m0.380s

이것은 11=4-> 와 같이 적도의 길이를 변경하는 솔루션을 찾지 못하지만 2 11=11이것이 허용되는지는 확실하지 않습니다.


1
방정식의 길이를 변경하는 솔루션은 문제에서 언급 한 EBNF를 따르는 한 허용됩니다. 따라서 함수에서도 찾을 수 있습니다.
vauge

@vauge, 그렇습니다. 자세한 내용은 "빈 machsticks 블록"섹션에서 유추 할 수 있습니다. 작동 할 수는 있지만 더 느리게 만들지만이 솔루션에 추가하지는 않습니다.
nutki

@vauge 나는 무례하게 말하고 싶지 않지만 코드가 고정되어 있지 않으면 여전히 계산됩니까?
Cieric

@Cieric이 모든 경우를 처리하는 다른 솔루션이 없으면 그렇습니다. 그러나이 도전이 끝날 때까지 제대로 작동하는 답변 이 있으면 가장 짧은 답변을 받아들입니다.
vauge

@vauge 괜찮습니다. 지금까지 이동 횟수가 올바른지 확인하면됩니다. 항상 올바른 출력 방정식을 표시합니다.
Cieric
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.