สมการของไม้ขีดไฟ


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 ที่กำหนด ในตัวอย่างข้างต้นแสดงผลที่ถูกต้องจะเป็น และ1 46+6=52หากมีความเป็นไปได้หลายอย่างสำหรับสมการที่ได้
  • มิฉะนั้น (ดังนั้นถ้าใส่ที่ถูกต้อง แต่มีวิธีที่จะทำให้สมการเป็นจริงไม่ได้) -1คุณจะมีการส่งออก

รายละเอียด

  • คุณไม่ได้รับอนุญาตให้ลบหรือเพิ่มการแข่งขัน นั่นหมายความว่าหากอินพุตถูกสร้างขึ้นจากnไม้ขีดไฟผลผลิตจะต้องประกอบด้วยnไม้ขีดไฟที่แน่นอน
  • "ว่างเปล่า" matchstick- บล็อกได้รับอนุญาตเฉพาะในตอนท้ายและจุดเริ่มต้นของสมการไม่ได้อยู่ตรงกลาง ตัวอย่างเช่นเปลี่ยน7-1=6เป็น7 =6-1เพียงแค่ลบออก-1จากด้านซ้ายและเพิ่มทางด้านขวาโดยไม่อนุญาตให้มีการจัดเรียงก้านไม้ขีดไฟเพียง 3 ครั้ง
  • เนื่องจากฉันไม่เห็นการแมปจากตัวเลขไปยังตำแหน่งจับคู่เป็นส่วนที่น่าสนใจของความท้าทายนี้บวก20 ไบต์คุณอาจ

    • เข้าถึงไฟล์ที่(number/operation ↦ matchstick positions)จัดเก็บการแมปด้วยวิธีที่สมเหตุสมผลหรือ
    • หากภาษาการเขียนโปรแกรมของคุณรองรับMapประเภทข้อมูลสมมติว่าคุณสามารถเข้าถึงแผนที่ที่กำหนดค่า(number/operation ↦ matchstick positions)เริ่มต้นล่วงหน้าด้วย -mapping ตัวอย่างเช่นแผนที่นี้อาจมีลักษณะดังนี้:{(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เอาต์พุต: 1และ1+1=2

อินพุต: 15+6=21เอาต์พุต: 0และ15+6=21

อินพุต: 1=7เอาท์พุท: -1

อินพุต: 950-250=750เอาต์พุต: 2และ990-240=750

อินพุต: 1-2=9เอาต์พุต: 1และ1+2=3

อินพุต: 20 + 3=04เอาท์พุท:อะไรก็ได้

ผู้ชนะ

นี่คือดังนั้นคำตอบที่ถูกต้องสั้นที่สุด (เป็นไบต์) ชนะ ผู้ชนะจะได้รับการคัดเลือกหนึ่งสัปดาห์หลังจากโพสต์คำตอบแรกที่ถูกต้อง


1
โปรดเพิ่มความ0: 1, 2, 3, 4, 5, 6สอดคล้อง
ไม่ใช่ว่า Charles

โอ้ขอบคุณลืมเรื่องนี้ไปโดยสิ้นเชิง!
vauge

@vauge เฮ้ '2 = 1-1' -> '2-1 = 1' ส่งคืน 3 หรือ 14 การเคลื่อนไหวตั้งแต่ 2 เทคนิคต้องย้ายไปทางซ้ายหรือไม่
Cieric

@Cieric ควรคืน 3 เพียงเพราะคุณสามารถเปลี่ยนตำแหน่ง=(2 ไม้ขีดไฟ) และ-(1 ไม้ขีดไฟ) และปล่อยตัวเลขทั้งหมดที่พวกเขาอยู่ อย่างไรก็ตามหากต้องย้ายทั้งสองไปทางซ้ายคุณจะต้องนับการเคลื่อนไหวที่ต้องการด้วย
vauge

มีข้อ จำกัด เกี่ยวกับจำนวนการปฏิบัติงานหรือไม่? อินพุตสามารถเป็น1+1+2=3-6+10อย่างไร และคำถามเดียวกันเกี่ยวกับผลลัพธ์
Qwertiy

คำตอบ:


6

Javascript, 1069 Bytes

ฉันได้ทดสอบด้วยสมการการทดสอบเล็กน้อยและดูเหมือนว่าจะทำงานได้ตลอดเวลาในขณะนี้ ...

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=8สำหรับ80=8ไม่ถูกต้อง
nutki

@ nutki ใช่ฉันคิดว่าฉันสามารถเปลี่ยนได้ ฉันคิดว่าจะผิด แต่เนื่องจากคุณต้องย้ายไป 2 ทางเพื่อให้มีที่ว่างสำหรับ -1
Cieric

@ nutki โอเคใช่ ขอโทษฉันเห็นสิ่งที่คุณหมายถึงตอนนี้ ทีนี้ฉันจะแก้ไข regex และดูว่าฉันสามารถเปลี่ยนรหัสเพื่อแก้ไขระยะทางได้ไหม
Cieric

1

Perl, 334

ค่อนข้างเร็วตราบใดที่โซลูชันสามารถเข้าถึงได้ในการเคลื่อนที่ 1 หรือ 2 ครั้ง 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

สิ่งนี้จะไม่พบวิธีแก้ไขปัญหาที่เปลี่ยนความยาวของ equasion เช่น11=4-> 2 11=11แต่ฉันไม่แน่ใจว่าจะอนุญาต


1
โซลูชั่นที่เปลี่ยนความยาวของสมการได้รับอนุญาตตราบใดที่พวกเขาทำตาม EBNF ที่กล่าวถึงในคำถาม ดังนั้นจึงควรพบฟังก์ชั่นของคุณด้วย
vauge

@ มาตรวัดใช่ฉันเห็นว่ามันสามารถอนุมานได้จากส่วน "บล็อก machsticks เปล่า" ในรายละเอียด ฉันจะไม่เพิ่มลงในโซลูชันนี้แม้ว่าในขณะที่มันสามารถทำงานได้มันจะทำให้ช้าลง
nutki

@vauge ฉันไม่ต้องการฟังเสียงหยาบคาย แต่หากรหัสไม่ได้รับการแก้ไขจะยังคงนับหรือไม่
Cieric

@Cieric หากไม่มีวิธีแก้ไขปัญหาอื่นที่จัดการกับกรณีเหล่านั้นทั้งหมดแล้วใช่มันจะถูกนับ อย่างไรก็ตามหากมีคำตอบใด ๆ ที่ทำงานได้อย่างสมบูรณ์ในตอนท้ายของการท้าทายนี้ฉันจะยอมรับคำตอบที่สั้นที่สุด
vauge

@ วัดไม่เป็นไรแค่ตรวจสอบฉันแค่ต้องแน่ใจว่าจำนวนการย้ายถูกต้องจนถึงตอนนี้มันจะแสดงสมการเอาต์พุตที่ถูกต้องเสมอ
Cieric
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.