Спрощений набір поїздів


27

Існує багато різних типів поїздів, починаючи від дерев’яних колій, таких як Brio, до повного цифрового управління ідеальними крихітними металевими репліками реальних поїздів, але всі вони потребують проектування колії, в ідеалі, використовуючи якомога більше ваших деталей.

Отже, ваше завдання - визначити, чи можна, з огляду на введення доступних фрагментів, побудувати повну замкнуту схему, використовуючи всі елементи, а якщо ні, то скільки штук залишиться від максимально можливого кола.

Оскільки це спрощений набір поїздів, є лише 3 елементи: велика крива, маленька крива та пряма. Усі вони базуються на квадратній сітці:

Квадратна сітка, що показує велику і маленьку криву

  • "Велика крива" - кут на 90 градусів, що охоплює 2 одиниці в кожному вимірі
  • "Маленька крива" - кут на 90 градусів, що охоплює по одній одиниці в кожному напрямку
  • "Прямий" - прямий елемент, довжиною 1 одиниця

Це означає, що мінімальний можливий контур формується з 4 маленьких кривих - це коло, радіусом 1 одиниця. Це можна розширити, додавши пари прямих елементів для формування різних овалів. Можливі й інші схеми, додавши більше кривих або змішавши типи кривих.

Цей набір поїздів не містить жодних з'єднань або методів для перетину колій, тому не допустимо, щоб два елементи з'єднувалися з одним і тим же кінцем іншого елемента (без утворень Y) або перетиналися один з одним (без X формувань) . Крім того, це набір поїздів, тому будь-яка формація, яка не дозволяє поїзду проходити, не є дійсною: приклади включають прямі, що зустрічаються під кутом 90 градусів (завжди повинна бути крива між перпендикулярними прямими) і криві, що відповідають під кутом 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 прямі і маленька крива еквівалентні великій кривій, але використовуйте більше шматочків, тому бажано - ніколи не повинно бути ситуації, коли ця комбінація залишається, якщо в схемі є якісь великі криві
  • 4 маленьких кривих зазвичай можна замінити на 4 прямі, але ні, якщо це призведе до того, що схема перетинається сама
  • Набір поїздів також ідеалізований - елементи колії займають показані ширини, тому криві справедливі для проходження через один квадрат сітки без пересічення, в деяких випадках. Сітка просто визначає розміри елементів. Зокрема, дві великі криві можуть бути розміщені так, що квадрат сітки в лівій верхній частині прикладу діаграми також був би нижній правий квадрат іншої великої кривої, що працює зліва вгору (при цьому діаграма показує, що одна працює праворуч донизу)
  • Невелика крива може вміститись у порожній простір під великою кривою (нижній правий квадрат сітки вгорі). Друга велика крива також могла використовувати цей простір, змістивши одну впоперек і одну вниз від першої
  • Мала крива не може вміщуватися в тому ж просторі сітки, що і зовні великої кривої - в основному тому, що немає можливості підключитися до неї, яка не перетинається незаконно

Тож вихід для [5,0,0]або [0,5,0]був би 1. Це правильно? Чи можете ви додати такий тестовий випадок?
Арнольд

@arnauld Так, це правильно. Завжди повинна бути кількість елементів, що залишилася після побудови максимально довгої схеми.
Метью

Чи можете ви підтвердити, що це рішення [8,0,0], з двома елементами 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] також займе зовсім небагато часу, оскільки це жорстоке рішення без оптимізацій.

Я насправді зробив це, тому що на нього не було відповіді вже більше року, і мені було просто цікаво, якщо це можливо.


Оригінальний код:

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 Я побачу, коли отримаю час написати його. Насправді це може зайняти трохи часу. Але так, зазвичай це мої улюблені види головоломок. Навіть якщо це не коротко, це цікаво довести, що це можливо.
Cieric

@Matthew додав написання.
Cieric

Чи є причина, чому ви вирішили використовувати p[a.n]-=1замість p[a.n]--?
Джонатан Фрех

Ініціалізація qтак не є дозволеним методом введення . Найчастіше або роблять це аргументом функції, або читають з stdin.
Ørjan Johansen
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.