Phương trình que diêm


16

Nhiệm vụ của bạn trong thử thách này là phân tích một "Phương trình que diêm" đã cho như thế này ...

nhập mô tả hình ảnh ở đây

... Và để tìm hiểu xem liệu nó có thể được biến thành một phương trình hợp lệ hay không bằng cách sắp xếp lại các trận đấu. Nếu vậy, bạn phải xuất ra số lượng di chuyển ít nhất để làm như vậy và phương trình kết quả.

Đầu vào

Đầu vào là một Chuỗi có thể được đọc từ STDIN, được lấy làm đối số chức năng hoặc thậm chí được lưu trữ trong một tệp. Đây là một phương trình đại diện cho sự sắp xếp que diêm và có thể được mô tả bằng EBNF sau:

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

Một ví dụ cho một đầu vào hợp lệ sẽ là 3+6-201=0+0+8.

Bài tập

Hãy xem xét hình minh họa sau đây trong đó mỗi que diêm có một số được gán:

vị trí que diêm

Bây giờ chúng ta ánh xạ từng ký hiệu đầu vào vào các vị trí que diêm tương ứng như sau:

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

Mỗi công thức đầu vào có thể được biến thành một sự sắp xếp que diêm. Ví dụ: phương trình "45 + 6 = 92" trở thành

nhập mô tả hình ảnh ở đây

nơi que diêm không sử dụng được tô màu xám. Nhiệm vụ của bạn là tìm ra số lượng que diêm ít nhất phải được sắp xếp lại để làm cho phương trình hợp lệ.

Đầu ra

Chúng tôi phân biệt giữa ba trường hợp có thể:

  • Nếu đầu vào không hợp lệ (nghĩa là nó không thỏa mãn EBNF ở trên), hãy xuất bất cứ thứ gì bạn muốn.
  • Mặt khác, nếu có nhiều cách để biến phương trình thành phương trình hợp lệ bằng cách sắp xếp lại các que diêm, bạn phải xuất cả số lượng sắp xếp lại tối thiểu phương trình tương ứng. Giống như đầu vào, phương trình xuất ra cũng phải thỏa mãn EBNF đã cho. Trong ví dụ trên, đầu ra chính xác sẽ là 146+6=52. Nếu có nhiều khả năng cho phương trình kết quả, xuất bất kỳ trong số chúng.
  • Mặt khác (vì vậy nếu đầu vào hợp lệ nhưng không có cách nào để biến phương trình thành đúng), bạn phải xuất -1.

Chi tiết

  • Bạn không được phép loại bỏ hoặc thêm các trận đấu. Điều đó có nghĩa là, nếu đầu vào được xây dựng bằng nque diêm, đầu ra cũng phải bao gồm chính xác các nque diêm.
  • Các khối que diêm "rỗng" chỉ được phép ở cuối và đầu của một phương trình, không phải ở giữa. Vì vậy, ví dụ, chuyển 7-1=6vào 7 =6-1bằng cách đơn giản là loại bỏ -1từ bên trái và thêm nó vào bên phải chỉ với 3 sắp xếp lại que diêm là không được phép.
  • Vì tôi thực sự không thấy ánh xạ từ các số đến các vị trí của que diêm là một phần thú vị của thử thách này, cộng thêm 20 byte , bạn có thể

    • truy cập một tệp trong đó ánh xạ (number/operation ↦ matchstick positions)được lưu trữ theo bất kỳ cách hợp lý nào, hoặc
    • nếu ngôn ngữ lập trình của bạn hỗ trợ Mapkiểu dữ liệu, giả sử rằng bạn có quyền truy cập vào bản đồ được xác định trước bằng cách lập bản đồ (number/operation ↦ matchstick positions). Bản đồ này có thể ví dụ như thế:{(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})}

Ví dụ

Input: 1+1=3Output: 11+1=2

Input: 15+6=21Output: 015+6=21

Input: 1=7Output: -1

Input: 950-250=750Output: 2990-240=750

Input: 1-2=9Output: 11+2=3

Input: 20 + 3=04Output: bất cứ điều gì

Người chiến thắng

Đây là , vì vậy câu trả lời đúng ngắn nhất (tính bằng byte) sẽ thắng. Người chiến thắng sẽ được chọn một tuần sau khi câu trả lời đúng đầu tiên được đăng.


1
Vui lòng thêm 0: 1, 2, 3, 4, 5, 6để thống nhất
Không phải Charles

Oh cảm ơn, hoàn toàn quên mất điều đó bằng cách nào đó!
vauge

@vauge Hey nên '2 = 1-1' -> '2-1 = 1' trả lại 3 hoặc 14 di chuyển vì 2 kỹ thuật phải được di chuyển sang trái?
Cieric

@Cieric nó sẽ trả về 3, đơn giản vì bạn có thể chuyển đổi vị trí của =(2 que diêm) và -(1 que diêm) và để lại tất cả các số mà chúng đang ở. Tuy nhiên, nếu 2 phải được di chuyển sang trái, bạn cũng sẽ phải tính các bước di chuyển cần thiết.
vauge

Có giới hạn về số lượng hoạt động? Đầu vào có thể như thế 1+1+2=3-6+10nào? Và câu hỏi tương tự về đầu ra.
Qwertiy

Câu trả lời:


6

Javascript, 1069 byte

Tôi đã thử nghiệm nó với một vài phương trình thử nghiệm và dường như nó hoạt động mọi lúc ...

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}

Chà, đây là lần đầu tiên tôi gửi câu trả lời, vì vậy tôi không thấy mình chiến thắng. Về cơ bản, đây là một phương pháp vũ phu để tìm ra tất cả các câu trả lời và sau đó nó lấy và trả về những câu nhỏ nhất trong một mảng. với đối số đầu tiên là độ dài và đối số thứ hai là một mảng với các đầu ra.

nếu đầu vào là "1-2 = 9" thì đầu ra là [1, ["1 + 2 = 3", "7-2 = 5"]]

và đây là mã không nén:

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;
}

Cảnh báo: Không thực hiện các phương trình như 950-250 = 750, nó sử dụng ~ 45 que diêm và vì mã này sử dụng vũ lực, nó sẽ khiến javascript bị treo.


Tôi tin rằng bạn có thể khai báo các biến bạn sử dụng, chẳng hạn như var ktrong các vòng lặp dưới dạng tham số không sử dụng cho hàm, tiết kiệm 3 byte cho mỗi khai báo.
rorlork

Tôi nghĩ rằng tôi sẽ đi học thêm một vài ngôn ngữ lập trình và tìm ra một cách không quá mạnh mẽ để thử và thực sự đánh bại số byte đó.
Cieric

Tôi nghĩ rằng giải pháp của bạn là không chính xác, vì khi bạn tính khoảng cách bạn luôn căn chỉnh các ký tự bằng nhau. Trong một số trường hợp nó không phải là cách tối ưu. Ví dụ: '2 = 1-1' có thể được chuyển đổi trong 3 lần di chuyển thành '2-1 = 1', trong khi việc căn chỉnh các dấu '=' sẽ cho 14 lần di chuyển. Ngoài ra tôi không thấy cách bạn tránh các số 0 hàng đầu. Ví dụ 08=8cho 80=8là không chính xác.
nutki

@nutki Vâng, tôi nghĩ rằng tôi có thể thay đổi điều đó. Tôi đã nghĩ rằng điều đó là sai mặc dù về mặt kỹ thuật bạn phải di chuyển qua số 2 để nhường chỗ cho -1
Cieric

@nutki được rồi, ừ. Xin lỗi tôi thấy những gì bạn có nghĩa là bây giờ. Vâng, tôi sẽ sửa regex và xem liệu tôi có thể thay đổi mã xung quanh cho khoảng cách chỉnh sửa không.
Cieric

1

Perl, 334

Khá nhanh miễn là có thể tiếp cận giải pháp trong 1 hoặc 2 lần di chuyển. Khi không có giải pháp, bạn phải chờ đợi lâu ngay cả trong trường hợp nhỏ nhất 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}

Thí dụ:

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

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

Điều này sẽ không tìm thấy các giải pháp thay đổi độ dài của phương trình như 11=4-> 2 11=11, nhưng tôi không chắc nó sẽ được cho phép.


1
Các giải pháp thay đổi độ dài của phương trình được cho phép miễn là tuân theo EBNF được đề cập trong câu hỏi. Do đó, chúng cũng nên được tìm thấy bởi chức năng của bạn.
vauge

@vauge, yeah Tôi có thể thấy rằng nó có thể được suy ra từ phần "khối machsticks trống" trong chi tiết. Tôi sẽ không thêm nó vào giải pháp này mặc dù trong khi nó có thể hoạt động, nó sẽ làm cho nó chậm hơn.
nutki

@vauge Tôi không muốn nghe thô lỗ, nhưng nếu mã không được sửa thì nó vẫn được tính chứ?
Cieric

@Cieric Nếu không có giải pháp nào khác xử lý tất cả các trường hợp đó thì có, nó sẽ được tính. Tuy nhiên, nếu có bất kỳ câu trả lời nào hoạt động đầy đủ vào cuối thử thách này, tôi sẽ chấp nhận câu trả lời ngắn nhất.
vauge

@vauge được rồi, chỉ cần kiểm tra Tôi chỉ phải đảm bảo số lần di chuyển là chính xác cho đến nay nó luôn hiển thị phương trình đầu ra chính xác.
Cieric
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.