Tập tàu đơn giản hóa


27

Nhiều loại tàu khác nhau tồn tại, từ đường ray bằng gỗ như Brio, đến điều khiển hoàn toàn kỹ thuật số bản sao kim loại nhỏ hoàn hảo của tàu thật, nhưng tất cả chúng đều yêu cầu đường ray được thiết kế, lý tưởng nhất là sử dụng càng nhiều mảnh của bạn càng tốt.

Vì vậy, nhiệm vụ của bạn là xác định xem, đầu vào của các phần có sẵn, có thể xây dựng một mạch kín hoàn chỉnh bằng cách sử dụng tất cả các phần tử hay không, và nếu không, sẽ còn lại bao nhiêu phần từ mạch tối đa có thể.

Vì đây là một bộ xe lửa được đơn giản hóa, chỉ có 3 yếu tố: đường cong lớn, đường cong nhỏ và đường thẳng. Tất cả đều dựa trên một lưới vuông:

Lưới vuông hiển thị đường cong lớn và đường cong nhỏ

  • "Đường cong lớn" là một góc 90 độ, bao gồm 2 đơn vị ở mỗi chiều
  • "Đường cong nhỏ" là một góc 90 độ, bao phủ một đơn vị theo mỗi hướng
  • "Thẳng" là một phần tử thẳng, dài 1 đơn vị

Điều này có nghĩa là mạch tối thiểu có thể được hình thành từ 4 đường cong nhỏ - đó là một vòng tròn, bán kính 1 đơn vị. Điều này có thể được mở rộng bằng cách thêm các cặp yếu tố thẳng để tạo thành hình bầu dục khác nhau. Có các mạch khác có thể bằng cách thêm nhiều đường cong hoặc trộn các loại đường cong.

Tập đoàn tàu này không bao gồm bất kỳ mối nối hoặc phương thức nào để các tuyến đường giao nhau, do đó, hai yếu tố không hợp lệ để kết nối với cùng một đầu của một yếu tố khác (không có hình dạng Y) hoặc giao nhau (không có hình dạng X) . Ngoài ra, đó là một bộ xe lửa, do đó, bất kỳ đội hình nào không cho phép tàu đi qua đều không hợp lệ: các ví dụ bao gồm các cuộc gặp gỡ căng thẳng ở góc 90 độ (luôn phải có một đường cong giữa các đường thẳng vuông góc) và đường cong gặp nhau ở góc 90 độ (đường cong phải chảy).

Bạn cũng muốn sử dụng càng nhiều mảnh càng tốt, bỏ qua chúng là loại gì, vì vậy bạn sẽ luôn chọn một mạch có nhiều bit hơn. Cuối cùng, bạn chỉ có một tàu, vì vậy mọi giải pháp dẫn đến nhiều mạch đều không được chấp nhận .

Đầu vào

Hoặc là một mảng gồm ba số nguyên, tất cả đều lớn hơn hoặc bằng 0, tương ứng với số lượng đường cong lớn, đường cong nhỏ và sức căng có sẵn hoặc các tham số được truyền cho chương trình của bạn, theo cùng một thứ tự.

Đầu ra

Một số tương ứng với số phần còn lại khi mạch tối đa có thể cho các phần tử được cung cấp được xây dựng.

Dữ liệu kiểm tra

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

Ghi chú

  • 2 dây đai và một đường cong nhỏ tương đương với một đường cong lớn, nhưng sử dụng nhiều mảnh hơn, vì vậy được ưu tiên - không bao giờ là tình huống mà sự kết hợp này bị bỏ lại, nếu có bất kỳ đường cong lớn nào trong mạch
  • 4 đường cong nhỏ thường có thể được hoán đổi cho 4 điểm căng, nhưng nếu không thì điều này sẽ khiến mạch tự giao nhau
  • Tập hợp tàu cũng được lý tưởng hóa - các phần tử theo dõi chiếm chiều rộng được hiển thị, do đó, nó có giá trị cho các đường cong đi qua một ô vuông lưới mà không giao nhau, trong một số trường hợp. Lưới chỉ xác định kích thước phần tử. Đặc biệt, hai đường cong lớn có thể được đặt sao cho ô vuông lưới ở phía trên bên trái của sơ đồ ví dụ cũng sẽ là hình vuông dưới cùng bên phải của một đường cong lớn khác chạy từ trái sang trên (với sơ đồ hiển thị một đường chạy từ phải xuống dưới)
  • Một đường cong nhỏ có thể vừa với khoảng trống dưới một đường cong lớn (ô vuông dưới cùng bên phải ở trên). Một đường cong lớn thứ hai cũng có thể sử dụng không gian đó, chuyển một đường ngang và xuống từ đường đầu tiên
  • Một đường cong nhỏ không thể vừa trên cùng một không gian lưới như bên ngoài của một đường cong lớn - chủ yếu là do không có cách nào để kết nối với nó mà không giao nhau bất hợp pháp

Vì vậy, đầu ra cho [5,0,0]hoặc [0,5,0]sẽ được 1. Đúng không? Bạn có thể thêm một trường hợp thử nghiệm như vậy?
Arnauld

@arnauld Vâng, đúng rồi. Luôn luôn là số phần tử còn lại sau khi xây dựng mạch dài nhất có thể.
Matthew

Bạn có thể vui lòng xác nhận rằng đây là một giải pháp cho [8,0,0], với hai phần tử 2x2 chồng lên nhau ở giữa lưới không?
Arnauld

Vâng, đó là giải pháp dự kiến ​​cho trường hợp thử nghiệm đó.
Matthew

Tôi không rõ làm thế nào các giao lộ tự làm việc. Bạn có thể rõ ràng hơn trong việc xác định những gì được phép và những gì bị cấm?
Thuật sĩ lúa mì

Câu trả lời:


9

[JavaScript (Node.js)], 1220 byte

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

Hãy thử trực tuyến!

Lưu ý: Đầu vào thực sự là biến q khi bắt đầu. [2,6,4] cũng sẽ mất khá nhiều thời gian vì đây là một giải pháp vũ phu mà không cần tối ưu hóa.

Tôi thực sự đã làm điều này bởi vì nó đã không được trả lời trong hơn một năm và tôi chỉ tò mò nếu có thể.


Mã gốc:

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

đầu tiên tôi nên bao gồm một hình ảnh của gạch tôi đã sử dụng.

gạch được sử dụng

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.

Xin lỗi nếu việc viết lên khó đọc Tôi không quen giải thích cách mã của tôi hoạt động.

PS Tôi thực sự cũng đã thực hiện một vài chức năng để vẽ bản đồ thành png nhưng tất nhiên những chức năng đó đã bị xóa để tiết kiệm ít nhất một khoảng trống.


Tôi rất ấn tượng - Tôi đã từ bỏ hy vọng về điều này! Sẽ có hứng thú với một bài viết lên
Matthew

@Matthew Tôi sẽ thấy khi tôi có thời gian để viết lên. Nó thực sự có thể mất một chút thời gian. Nhưng vâng, thông thường đây là những loại câu đố yêu thích của tôi để làm. Ngay cả khi nó không ngắn, thật vui khi chứng minh điều đó là có thể.
Cieric

@Matthew đã thêm phần viết lên.
Cieric

Có một lý do tại sao bạn chọn sử dụng p[a.n]-=1thay vì p[a.n]--?
Jonathan Frech

Khởi tạo qnhư thế không phải là một phương thức nhập liệu được phép . Thông thường nhất, hoặc làm cho nó một đối số chức năng hoặc đọc nó từ stdin.
Ørjan Johansen
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.