Basitleştirilmiş Tren Seti


27

Brio gibi tahta raylardan, gerçek trenlerin minik metal kopyalarının tamamen dijital kontrolüne kadar birçok farklı tipte tren seti mevcuttur, fakat hepsinin ideal olarak mümkün olan en fazla parçanızı kullanarak tasarlanması gereken bir ray gerekir.

Bu nedenle, göreviniz, mevcut parçaların girişi göz önüne alındığında, tüm elemanları kullanarak komple bir kapalı devre oluşturmak mümkün olup olmadığını ve eğer değilse, mümkün olan maksimum devreden kaç adet parça bırakılacağını belirlemektir.

Bu basitleştirilmiş bir tren seti olduğundan, sadece 3 öğe vardır: büyük eğri, küçük eğri ve düz. Bunların hepsi kare bir ızgaraya dayanıyor:

Büyük eğri ve küçük eğri gösteren kare ızgara

  • "Big Curve" 90 derecelik bir köşedir ve her boyutta 2 birim içerir
  • "Küçük Eğri" 90 derecelik bir köşedir, her yöne bir ünite örter
  • "Düz", 1 birim uzunluğunda düz bir öğedir

Bu, mümkün olan minimum devrenin 4 küçük eğriden oluştuğu anlamına gelir - bu, yarıçap 1 birimin bir dairesidir. Bu, çeşitli ovaller oluşturmak için düz eleman çiftleri eklenerek uzatılabilir. Daha fazla eğri ekleyerek veya eğri türlerini karıştırarak mümkün başka devreler vardır.

Bu tren seti, herhangi bir kavşağı veya rayların geçmesi için yöntemleri içermez; bu nedenle, iki elemanın başka bir elemanın aynı ucuna bağlanması (Y formasyonu yok) veya üst üste geçmesi (X formasyonu yok) için geçerli değildir. . Ek olarak, bir tren setidir, bu nedenle bir trenin geçmesine izin vermeyen herhangi bir oluşum geçerli değildir: örnekler, 90 derecelik açılarda birleşen (her zaman dikey yüksekliklerde bir eğri olmalıdır) ve 90 derecelik açılarda birleşen eğrileri içerir. (eğriler akmalıdır).

Ayrıca, ne tür olduklarını göz ardı ederek mümkün olduğu kadar çok parça kullanmak istersiniz, bu nedenle her zaman daha fazla bit içeren bir devreyi tercih edersiniz. Sonunda, sadece bir treniniz vardır, bu nedenle birden fazla devreyle sonuçlanan herhangi bir çözüm kabul edilemezdir. .

Giriş

Büyük eğrilerin, küçük eğrilerin ve mevcut büyüklüklerin sayısına veya programınıza geçirilen parametrelere aynı sırada karşılık gelen, 0'dan büyük veya 0'a eşit üç tam sayı dizisi.

Çıktı

Sağlanan elemanlar için mümkün olan maksimum devre oluşturulduğunda, kalan parça sayısına karşılık gelen bir sayı.

Test verisi

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

notlar

  • 2 yükseklik ve küçük bir eğri büyük bir eğriye eşdeğerdir, ancak daha fazla parça kullanın, bu nedenle tercih edilir - eğer devrede büyük eğriler varsa, bu kombinasyonun kaldığı bir durum olmamalıdır
  • 4 küçük eğri, genellikle 4 yükseklik için değiştirilebilir, ancak bu, devrenin kesişmesine neden olmazsa olmaz
  • Tren seti de idealleştirilir - ray elemanları gösterilen genişlikleri alır, bu nedenle bazı durumlarda kavislerin kesişmeden tek bir ızgara kareden geçmesi geçerlidir. Izgara sadece eleman boyutlarını tanımlar. Özellikle, iki büyük eğri yerleştirilebilir, böylece örnek diyagramın sol üst kısmındaki ızgara karesi, soldan tepeye uzanan başka bir büyük eğrinin sağ alt karesi olacaktı (diyagram bir sağdan aşağı doğru koşarken)
  • Küçük bir eğri boş alana büyük bir eğri altında sığabilir (üstte sağ alt ızgara kare). İkinci bir büyük eğri de o alanı kullanabilir, biri birinden birinden diğerine kaymıştır.
  • Küçük bir eğri, büyük bir eğrinin dışıyla aynı ızgara alanına sığamaz - çoğunlukla yasadışı yollarla kesişmeyen bir yolla bağlanma yolu yoktur.

Böylece çıktı [5,0,0]ya da [0,5,0]olurdu 1. Bu doğru mu? Böyle bir test durumu ekleyebilir misiniz?
Arnauld,

@arnauld Evet, doğru. Mümkün olan en uzun devreyi yaptıktan sonra daima kalan eleman sayısı olmalıdır.
Matthew

O gönderebilir misiniz bu bir çözümdür [8,0,0]iki 2x2 elemanları ızgara merkezinde örtüşen ile?
Arnauld,

Evet, bu test durumu için beklenen çözüm budur.
Matthew,

Kendi kendine kesişimin nasıl çalıştığı konusunda net değilim. Neye izin verildiğini ve neyin yasak olduğunu tanımlamakta daha açık olabilir misiniz?
Buğday Sihirbazı,

Yanıtlar:


9

[JavaScript (Node.js)], 1220 bayt

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

Çevrimiçi deneyin!

Not: Giriş aslında başlangıçtaki q değişkenidir. [2,6,4], bu optimizasyon olmadan kaba kuvvet çözümü olduğu için biraz zaman alacaktır.

Aslında bunu yaptım çünkü bir yıldan uzun süredir cevaplanmadı ve mümkün olup olmadığını merak ettim.


Orijinal Kod:

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

ilk önce kullandığım çini bir grafik içermelidir.

kullanılan fayans

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.

Üzgünüm, yazmak zorsa kodumun nasıl çalıştığını açıklamaya alışkın değilim.

PS Haritaları bir png'ye çizmek için aslında birkaç işlev de yaptım, fakat elbette en azından yer kazanmak için kaldırıldı.


Ben etkilendim - Bu konuda biraz umut verdim! Bir
Matthew

@Matthew Bir tane yazmak için zaman bulduğumda göreceğim. Aslında biraz zaman alabilir. Ama evet, normalde bunlar benim en sevdiğim bulmaca türleridir. Kısa olmasa bile, mümkün olduğunu kanıtlamak eğlencelidir.
Cieric

@Matthew, yazıyı ekledi.
Cieric

Kullanmak seçtim bir sebebi var mı p[a.n]-=1yerine p[a.n]--?
Jonathan Frech

Bunun qgibi bir başlatılması izin verilen bir giriş yöntemi değil . En yaygın olarak, onu bir işlev argümanı yap ya da stdin'den oku.
Ørjan Johansen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.