ชุดรถไฟแบบง่าย


27

มีชุดรถไฟหลายประเภทตั้งแต่แทร็กไม้อย่าง Brio จนถึงการควบคุมแบบดิจิตอลอย่างสมบูรณ์แบบจำลองโลหะเล็ก ๆ ที่สมบูรณ์แบบของรถไฟจริง แต่พวกมันทั้งหมดต้องการแทร็กที่ออกแบบมาโดยใช้ชิ้นส่วนของคุณให้ได้มากที่สุด

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

เนื่องจากชุดนี้เป็นชุดรถไฟที่เรียบง่ายจึงมีองค์ประกอบ 3 อย่างเท่านั้น: โค้งใหญ่, โค้งเล็ก ๆ และตรง สิ่งเหล่านี้ล้วนมีพื้นฐานมาจากตารางสี่เหลี่ยม:

ตารางสี่เหลี่ยมแสดงเส้นโค้งใหญ่และเส้นโค้งเล็ก ๆ

  • "Big Curve" เป็นมุม 90 องศาครอบคลุม 2 ยูนิตในแต่ละมิติ
  • "Little Curve" เป็นมุม 90 องศาครอบคลุมหนึ่งยูนิตในแต่ละทิศทาง
  • "เส้นตรง" เป็นองค์ประกอบเส้นตรงยาว 1 หน่วย

ซึ่งหมายความว่าวงจรต่ำสุดที่เป็นไปได้จะเกิดขึ้นจาก 4 เส้นโค้งเล็ก ๆ - มันเป็นวงกลมรัศมี 1 หน่วย สิ่งนี้สามารถขยายได้โดยการเพิ่มคู่ขององค์ประกอบตรงในรูปแบบวงรีต่างๆ มีวงจรอื่น ๆ ที่เป็นไปได้โดยการเพิ่มเส้นโค้งมากขึ้นหรือโดยการผสมประเภทของเส้นโค้ง

ชุดขบวนรถไฟนี้ไม่มีทางแยกหรือวิธีการข้ามแทร็กดังนั้นจึงไม่ถูกต้องสำหรับองค์ประกอบสองอย่างที่จะเชื่อมต่อกับส่วนอื่น ๆ ขององค์ประกอบอื่น ๆ (ไม่มีการก่อตัว Y) หรือข้ามแบบอื่น (ไม่มีการก่อตัว X) . นอกจากนี้มันเป็นชุดรถไฟดังนั้นการก่อตัวใด ๆ ที่ไม่อนุญาตให้รถไฟผ่านไม่ถูกต้อง: ตัวอย่างรวมถึงการประชุม straights ที่มุม 90 องศา (จะต้องมีเส้นโค้งระหว่าง straights ตั้งฉาก) และการประชุมโค้งที่มุม 90 องศา (เส้นโค้งต้องไหล)

คุณต้องการใช้ชิ้นส่วนให้มากที่สุดเท่าที่จะเป็นไปได้โดยไม่สนใจว่าเป็นแบบไหนดังนั้นคุณจะเลือกใช้วงจรที่มีบิตมากกว่านี้ในที่สุดคุณมีรถไฟเพียงขบวนเดียวดังนั้นวิธีการแก้ปัญหาใด ๆ .

อินพุต

อาเรย์ของทั้งสามจำนวนเต็มทั้งหมดมากกว่าหรือเท่ากับ 0 สอดคล้องกับจำนวนของเส้นโค้งขนาดใหญ่เส้นโค้งเล็ก ๆ น้อย ๆ และเส้นตรงที่มีอยู่หรือพารามิเตอร์ที่ส่งผ่านไปยังโปรแกรมของคุณในลำดับเดียวกัน

เอาท์พุต

ตัวเลขที่สอดคล้องกับจำนวนชิ้นส่วนที่เหลือเมื่อสร้างวงจรที่เป็นไปได้สูงสุดสำหรับองค์ประกอบที่มีให้

ทดสอบข้อมูล

Minimal circuit using big curves
Input: [4,0,0]
Output: 0

Slightly more complicated circuit
Input: [3,1,2]
Output: 0

Incomplete circuit - can't join
Input: [3,0,0]
Output: 3

Incomplete circuit - can't join
Input: [3,1,1]
Output: 5

Circuit where big curves share a centre
Input: [2,2,0]
Output: 0

Bigger circuit
Input: [2,6,4]
Output: 0

Circuit where both concave and convex curves required
Input: [8,0,0] or [0,8,0]
Output: 0

Circuit with left over bit
Input: [5,0,0] or [0,5,0]
Output: 1

หมายเหตุ

  • 2 straights และเส้นโค้งเล็ก ๆ น้อย ๆ จะเทียบเท่ากับเส้นโค้งขนาดใหญ่ แต่ควรใช้ชิ้นส่วนมากขึ้นดังนั้นจึงเป็นที่ต้องการ - ไม่ควรเป็นสถานการณ์ที่ชุดค่าผสมนี้เหลืออยู่หากมีเส้นโค้งขนาดใหญ่ในวงจร
  • 4 เส้นโค้งเล็ก ๆ น้อย ๆ สามารถสลับเป็น 4 straights ได้ แต่ถ้าไม่ใช่จะทำให้วงจรตัดกัน
  • ชุดรถไฟยังได้รับการออกแบบให้เหมาะสม - องค์ประกอบของแทร็กใช้ความกว้างที่แสดงดังนั้นจึงมีความถูกต้องสำหรับการโค้งผ่านสี่เหลี่ยมกริดเดี่ยวโดยไม่ต้องตัดกันในบางกรณี กริดเพียงกำหนดขนาดองค์ประกอบ โดยเฉพาะอย่างยิ่งสามารถวางเส้นโค้งขนาดใหญ่สองเส้นเพื่อให้ตารางกริดที่มุมบนซ้ายของไดอะแกรมตัวอย่างจะเป็นสี่เหลี่ยมจัตุรัสล่างขวาของเส้นโค้งใหญ่อีกเส้นที่วิ่งจากซ้ายไปด้านบน (ด้วยแผนภาพแสดงการวิ่งจากขวาไปล่าง)
  • เส้นโค้งขนาดเล็กสามารถพอดีกับพื้นที่ว่างใต้เส้นโค้งขนาดใหญ่ (ตารางกริดด้านล่างขวาด้านบน) เส้นโค้งขนาดใหญ่เส้นที่สองสามารถใช้พื้นที่นั้นได้โดยเลื่อนหนึ่งข้ามและอีกอันหนึ่งลดลงจากอันแรก
  • เส้นโค้งขนาดเล็กไม่สามารถพอดีกับพื้นที่กริดเดียวกันกับด้านนอกของเส้นโค้งขนาดใหญ่ส่วนใหญ่เป็นเพราะไม่มีวิธีการเชื่อมต่อกับมันซึ่งไม่ได้ตัดกันอย่างผิดกฎหมาย

ดังนั้นผลลัพธ์สำหรับ[5,0,0]หรือจะเป็น[0,5,0] 1ถูกต้องหรือไม่ คุณสามารถเพิ่มกรณีทดสอบได้ไหม?
Arnauld

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

คุณช่วยยืนยันได้ไหมว่านี่เป็นวิธีแก้ปัญหา[8,0,0]โดยมีองค์ประกอบ 2x2 สองรายการซ้อนกันอยู่ตรงกลางของตาราง
Arnauld

ใช่นั่นเป็นคำตอบที่คาดไว้สำหรับกรณีทดสอบ
แมทธิว

ฉันไม่ชัดเจนเกี่ยวกับการทำงานของการแยกตัวเอง คุณสามารถระบุสิ่งที่ได้รับอนุญาตได้ชัดเจนยิ่งขึ้นและสิ่งต้องห้ามคืออะไร
ข้าวสาลีตัวช่วยสร้าง

คำตอบ:


9

[JavaScript (Node.js)], 1220 ไบต์

f=r=>{var a=[{n:0,d:[[0,-1,"0000000101011"],[1,-1,"0011111111111"],[0,0,"0111101111111"],[1,0,"1100010000000"]],e:[2,-1,1]},{n:0,d:[[-1,-1,"1001111111111"],[0,-1,"0000010010110"],[-1,0,"0110000100000"],[0,0,"1101111011111"]],e:[-2,-1,3]},{n:1,d:[[0,0,"0011101111111"]],e:[1,0,1]},{n:1,d:[[0,0,"1001111011111"]],e:[-1,0,3]},{n:2,d:[[0,0,"1111101011111"]],e:[0,-1,0]}],e=r=>{var a=r.d,e=r.e,n=[];return a.forEach(r=>{var a=r[2];n.push([-r[1],r[0],""+a[10]+a[5]+a[0]+a[8]+a[3]+a[11]+a[6]+a[1]+a[9]+a[4]+a[12]+a[7]+a[2]])}),{d:n,e:[-e[1],e[0],e[2]]}};i=((r,a)=>{for(var n=0;n<r.d;n++,a=e(a));var p=!1;return a.d.forEach(a=>{var e=r[`${r.p.x+a[0]},${r.p.y+a[1]}`];void 0===e&&(e="00000000000000");for(var n="",d=0;d<13;d++)"1"===e[d]&&"1"===a[2][d]&&(p=!0),n+=e[d]===a[2][d]?e[d]:"1";r[`${r.p.x+a[0]},${r.p.y+a[1]}`]=n}),r.p.x+=a.e[0],r.p.y+=a.e[1],r.d=(r.d+a.e[2])%4,!p});var n=[],p=(r,e)=>{a.forEach(a=>{var d=Object.assign({},r);if(d.p=Object.assign({},r.p),!(e[a.n]<=0)&&i(d,a)){if(d.ps+=a.n,0==d.p.x&&0==d.p.y&&0==d.d)return void n.push(d);var s=Object.assign([],e);s[a.n]-=1,p(d,s)}})};p({p:{x:0,y:0},d:0,ps:""},Object.assign([],r));var d=0;n.forEach(r=>{r.ps.length>d&&(d=r.ps.length)}),console.log(r[0]+r[1]+r[2]-d)};

ลองออนไลน์!

หมายเหตุ: อินพุตเป็นตัวแปร q จริงเมื่อเริ่มต้น [2,6,4] จะใช้เวลาค่อนข้างน้อยเพราะนี่เป็นวิธีการแก้ปัญหาที่ดุร้ายโดยไม่มีการเพิ่มประสิทธิภาพ

ที่จริงฉันทำอย่างนี้เพราะยังไม่ได้รับคำตอบในช่วงหนึ่งปีที่ผ่านมาและฉันก็แค่อยากรู้อยากเห็นถ้ามันเป็นไปได้


รหัสเดิม:

var q = [4, 2, 4];
var t = [
    {
        n: 0,
        d: [
            [0, -1, "0000000101011"],
            [1, -1, "0011111111111"],
            [0, 0, "0111101111111"],
            [1, 0, "1100010000000"]
        ],
        e: [2, -1, 1],

    },
    {
        n: 0,
        d: [
            [-1, -1, "1001111111111"],
            [0, -1, "0000010010110"],
            [-1, 0, "0110000100000"],
            [0, 0, "1101111011111"]
        ],
        e: [-2, -1, 3]
    },
    {
        n: 1,
        d: [
            [0, 0, "0011101111111"]
        ],
        e: [1, 0, 1]
    },
    {
        n: 1,
        d: [
            [0, 0, "1001111011111"]
        ],
        e: [-1, 0, 3]
    },
    {
        n: 2,
        d: [
            [0, 0, "1111101011111"]
        ],
        e: [0, -1, 0]
    },
];

r = (p) => {
    var d = p.d; var e = p.e; var o = [];
    d.forEach(i => {
        var d = i[2];
        o.push([-i[1], i[0], "" + d[10] + d[5] + d[0] + d[8] + d[3] + d[11] + d[6] + d[1] + d[9] + d[4] + d[12] + d[7] + d[2]])
    });
    return { d: o, e: [-e[1], e[0], e[2]] };
};

i = (g, p) => {
    //console.log(g.p, g.d);
    for (var i = 0; i < g.d; i++ , p = r(p));
    var c = false;
    p.d.forEach(d => {
        var v = g[`${g.p.x + d[0]},${g.p.y + d[1]}`];
        if (v === undefined) v = "00000000000000";
        var o = "";
        for (var i = 0; i < 13; i++) {
            if (v[i] === '1' && d[2][i] === '1')
                c = true;
            o += (v[i] === d[2][i]) ? v[i] : '1';
        }
        //console.log(o);
        g[`${g.p.x + d[0]},${g.p.y + d[1]}`] = o;
    });
    g.p.x += p.e[0];
    g.p.y += p.e[1];
    g.d = (g.d + p.e[2]) % 4;
    return !c;
};

var l = [];
var re = (g, p) => {
    t.forEach(piece => {
        var gr = Object.assign({}, g);
        gr.p = Object.assign({}, g.p);
        if (p[piece.n] <= 0)
            return;
        if (i(gr, piece)) {
            gr.ps += piece.n;
            if (gr.p.x == 0 && gr.p.y == 0 && gr.d == 0) {
                l.push(gr);
                return;
            }
            var ti = Object.assign([], p);
            ti[piece.n] -= 1;
            re(gr, ti);
        }
    });
};
var gr = { p: { x: 0, y: 0 }, d: 0, ps: "" };
re(gr, Object.assign([], q));

var c = 0;
var lo = 0;
l.forEach(g => {
    if (g.ps.length > lo) {
        require("./draw.js")(g, `outs/out${c++}.png`)
        lo = g.ps.length;
    }
});

console.log(q[0] + q[1] + q[2] - lo);

ก่อนอื่นฉันควรรวมกราฟิกของกระเบื้องที่ฉันใช้

กระเบื้องที่ใช้

The sections of this tile were given a number and
used for comparison and overlap handling later.

So there first thing is the array t at the start. 
This is a collection of track pieces that contain
    n[ame]: the index of the input array.
    d[ata]: the offset from the current tile and the Tile bit values.
    e[nd]: the relative offset and rotation that the piece provides.

function r[otate] ( p[iece] )
    this outputs a piece that is rotated by 90 degrees
    by rearranging the tile bits and the end offset

function i[nsert] ( g[rid], p[iece] )
    this modifies the passed in grid trying to place down each tile of the piece.
    if it hits a point where 2 tiles intersect it sets a flag c[ollision]
    it then adjusts the current p[osition] and and d[irection] stored in the grid.
    then it returns !c[ollision]

function re[peat] ( g[rid], p[eices] )
    this iterates across all nodes which
        creates a copy of the g[rid] as gr[id].
        checks if the piece is available if not continue
        if the peice is added without a collision
            add piece name to gr[id].ps[piece string];
            it checks if its back at the start
                add gr[id] to l[ist]
                return as no more pieces can be added without a collision.
            clone peices remove the used peice ti[nput]
            call re[peate] (gr[id], ti[nput])

call re[peate] with empty grid

search l[ist] for longest piece string
and output input added together minus the length of the longest string.

ขออภัยถ้าบทความอ่านยากฉันไม่ได้อธิบายวิธีการใช้งานโค้ดของฉัน

PS ที่จริงฉันยังทำหน้าที่บางอย่างสำหรับการวาดแผนที่ไปยัง png แต่แน่นอนว่าพวกมันถูกลบเพื่อประหยัดพื้นที่อย่างน้อย


ฉันประทับใจ - ฉันจะหมดหวังกับสิ่งนี้! จะสนใจเขียนบทความ
Matthew

@ Matewew ฉันจะเห็นเมื่อฉันมีเวลาที่จะเขียนขึ้น อาจใช้เวลาสักครู่จริง ๆ แต่ใช่โดยปกติแล้วสิ่งเหล่านี้เป็นปริศนาที่ฉันโปรดปราน แม้ว่ามันจะไม่สั้นมันก็สนุกที่จะพิสูจน์ว่าเป็นไปได้
เซียร์

@Matthew เพิ่มการเขียน
Cieric

มีเหตุผลที่คุณเลือกใช้p[a.n]-=1แทนp[a.n]--หรือไม่
Jonathan Frech

เริ่มต้นqเหมือนที่ไม่ได้เป็นวิธีการป้อนข้อมูลที่ได้รับอนุญาต โดยทั่วไปจะทำให้อาร์กิวเมนต์เป็นฟังก์ชันหรืออ่านจาก stdin
Ørjan Johansen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.