簡易列車セット


27

Brioのような木製の線路から実際の列車の完全に小さな金属の完全なデジタル制御まで、さまざまな種類の列車セットが存在しますが、それらはすべて理想的にはできるだけ多くの部品を使用して設計するための線路を必要とします。

したがって、あなたの仕事は、利用可能なピースの入力が与えられた場合、すべての要素を使用して完全な閉回路を構築できるかどうか、そうでない場合は可能な最大回路からいくつのピースを残すかを決定することです。

これは単純化されたトレインセットであるため、大きな曲線、小さな曲線、直線の3つの要素しかありません。これらはすべて正方形グリッドに基づいています。

大きな曲線と小さな曲線を示す正方形のグリッド

  • 「ビッグカーブ」は90度の角で、各次元で2ユニットをカバーします
  • 「小さな曲線」は90度の角で、各方向に1つのユニットをカバーします
  • 「ストレート」は、1ユニット長のストレート要素です

これは、可能な最小回路が4つの小さな曲線で構成されていることを意味します。これは半径1単位の円です。これは、直線要素のペアを追加してさまざまな楕円を形成することで拡張できます。曲線を追加したり、曲線の種類を混合したりすることで、他の回路も可能です。

このトレインセットにはジャンクションもトラックの交差方法も含まれていないため、2つの要素が他の要素の同じ端に接続する(Yフォーメーションなし)、または互いに交差する(Xフォーメーションなし)ことは無効です。さらに、列車セットであるため、列車の通過を許可しないフォーメーションは無効です。例には、90度の角度で交わる直線(常に垂直な直線の間に曲線が必要です)と90度の角度で交わる曲線が含まれます。 (曲線が流れる必要があります)。

また、タイプを無視して、できるだけ多くのピースを使用したいので、常により多くのビットを持つ回路を選択します。 。

入力

利用可能な大きな曲線、小さな曲線、直線の数に対応する、すべて0以上の3つの整数の配列、または同じ順序でプログラムに渡されるパラメーター。

出力

提供された要素の最大可能回路が構築されたときに残ったピースの数に対応する数。

テストデータ

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本の直線と小さな曲線は大きな曲線と同等ですが、より多くのピースを使用するため、推奨されます-回路に大きな曲線がある場合は、この組み合わせを残さないでください
  • 通常、4つの小さな曲線を4つの直線に交換できますが、これにより回路が交差する場合はできません
  • 列車セットも理想化されています-トラック要素は示されている幅を占めるため、曲線が交差せずに単一のグリッド正方形を通過することが有効な場合があります。グリッドは要素の寸法を定義するだけです。特に、2つの大きな曲線を配置して、例の図の左上のグリッドの正方形が、左から上に走る別の大きな曲線の右下の正方形になるようにすることができます(図では、右から下に走る1つを示しています)
  • 小さな曲線は、大きな曲線の下の空のスペースに収まります(上の右下のグリッドの正方形)。2番目の大きな曲線もそのスペースを使用し、最初から1つ横に1つ下にシフトします
  • 小さな曲線は、大きな曲線の外側と同じグリッド空間に収まらない-主に、違法に交差しない曲線に接続する方法がないため

[5,0,0]またはの出力[0,5,0]はになります1。あれは正しいですか?そのようなテストケースを追加してもらえますか?
アーナルド

@arnauldはい、それは正しいです。可能な限り長い回路を構築した後は、常に残りの要素数にする必要があります。
マシュー

これがの解決策であることを確認してください[8,0,0]。グリッドの中央で2つの2x2要素が重複しています。
アーナルド

はい、それはそのテストケースの予想されるソリューションです。
マシュー

自己交差がどのように機能するかについては明確ではありません。許可されているものと禁止されているものをより明確に定義できますか?
小麦ウィザード

回答:


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]も最適化なしのブルートフォースソリューションであるため、かなり時間がかかります。

実際にこれを行ったのは、1年以上にわたって回答が得られていないためです。可能であれば、ちょっと興味がありました。


元のコード:

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私はそれを書き上げる時間がある時に見るでしょう。実際には少し時間がかかるかもしれません。しかし、ええ、通常、これらは私のお気に入りの種類のパズルです。短くなくても、それが可能であることを証明するのは楽しいです。
シエリック

@Matthewが追加しました。
シエリック

p[a.n]-=1代わりに使用することにした理由はありますp[a.n]--か?
ジョナサンフレッチ

qそのような初期化は、許可された入力メソッドではありません。最も一般的には、関数の引数にするか、stdinから読み取ります。
Ørjanヨハンセン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.