Advertisement
horvathm

Untitled

Dec 20th, 2020
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const data = require('fs').readFileSync('input', 'utf8').trim().split('\n\n')
  2.     .map(t => t.split('\n'));
  3.  
  4. //console.log(data);
  5.  
  6. const tiles = {};
  7. const joins = {};
  8.  
  9. for (const tile of data) {
  10.     const [head, ...body] = tile;
  11.  
  12.     const id = head.substring(5, head.length - 1);
  13.     //console.log(id);
  14.  
  15.     const edges = [
  16.         body[0].split(''),
  17.         body[body.length - 1].split(''),
  18.         body.map(r => r[0]),
  19.         body.map(r => r[r.length - 1]),
  20.     ];
  21.     //console.log(edges);
  22.  
  23.     const eintswf = edges.map(e => {
  24.         const x = parseInt(e.join('').replace(/#/g, 1).replace(/\./g, 0), 2);
  25.         const y = parseInt([...e].reverse().join('').replace(/#/g, 1).replace(/\./g, 0), 2);
  26.         return x < y ? { e: x, f: false } : { e: y, f: true };
  27.     });
  28.     const eints = eintswf.map(e => e.e);
  29.     //console.log(eints);
  30.  
  31.     for (const edge of eints) {
  32.         if (!(edge in joins)) {
  33.             joins[edge] = [id];
  34.         } else {
  35.             joins[edge].push(id);
  36.         }
  37.     }
  38.  
  39.     tiles[id] = {
  40.         body,
  41.         hedges: [{ t: true, e: eints[0] }, { t: false, e: eints[1] }],
  42.         vedges: [{ l: true, e: eints[2] }, { l: false, e: eints[3] }],
  43.     };
  44. }
  45.  
  46. //console.log(joins);
  47.  
  48. const borders = {};
  49. const corners = {}
  50.  
  51. for (const [edge, ids] of Object.entries(joins)) {
  52.     if (ids.length === 1) {
  53.         if (borders[ids[0]]) {
  54.             corners[ids[0]] = true;
  55.         }
  56.         borders[ids[0]] = true;
  57.     }
  58. }
  59.  
  60. //console.log(corners);
  61.  
  62. const edgeRemove = (a, e) => {
  63.     const index = a.findIndex(x => x.e == e);
  64.     a.splice(index, 1);
  65.     return a;
  66. }
  67.  
  68. let startId = Object.keys(corners)[1];
  69. let startTile = tiles[startId];
  70. let startRot = false;
  71.  
  72. let img = [[{
  73.     id: startId,
  74.     rot: startRot,
  75.     vflp: undefined,
  76. }]];
  77.  
  78. let row = 0;
  79.  
  80. while (true) {
  81.     let thisId = startId;
  82.     let thisTile = startTile;
  83.     let thisRot = startRot;
  84.  
  85.     while (true) {
  86.         let thisEdge, thisHflp, thatId;
  87.  
  88.         if (!thisRot) {
  89.             const thisEdgeItem = thisTile.vedges.filter(e => joins[e.e] && joins[e.e].length === 2)[0];
  90.             if (!thisEdgeItem) break; // line end
  91.             thisEdge = thisEdgeItem.e;
  92.             thisHflp = thisEdgeItem.l;
  93.         } else {
  94.             const thisEdgeItem = thisTile.hedges.filter(e => joins[e.e] && joins[e.e].length === 2)[0];
  95.             if (!thisEdgeItem) break; // line end
  96.             thisEdge = thisEdgeItem.e;
  97.             thisHflp = thisEdgeItem.t;
  98.         }
  99.  
  100.         // If we just started a row, flip first tile as needed
  101.         if (thisId === startId) {
  102.             img[row][0].hflp = thisHflp;
  103.         }
  104.  
  105.         thatId = joins[thisEdge].filter(i => i !== thisId)[0];
  106.         const thatTile = tiles[thatId];
  107.  
  108.         const thatRot = !(thatTile.vedges[0].e === thisEdge || thatTile.vedges[1].e === thisEdge);
  109.  
  110.         // hflip
  111.  
  112.         let thatHflp;
  113.         if (!thatRot) {
  114.             const thatEdgeItem = thatTile.vedges.filter(e => e.e === thisEdge)[0];
  115.             thatHflp = !thatEdgeItem.l;
  116.         } else {
  117.             const thatEdgeItem = thatTile.hedges.filter(e => e.e === thisEdge)[0];
  118.             thatHflp = !thatEdgeItem.t;
  119.         }
  120.  
  121.         // vflip
  122.  
  123.         let thatVflp;
  124.         if (row > 0) {
  125.             const aboveImgItem = img[row - 1][img[row].length];
  126.             const aboveId = aboveImgItem.id;
  127.             const aboveTile = tiles[aboveId];
  128.             const aboveRot = aboveImgItem.rot;
  129.  
  130.             let aboveEdge, aboveVflp;
  131.             if (row === 1) {
  132.                 if (!aboveRot) {
  133.                     const aboveEdgeItem = aboveTile.hedges.filter(e => joins[e.e] && joins[e.e].length === 2)[0];
  134.                     aboveEdge = aboveEdgeItem.e;
  135.                     aboveVflp = aboveEdgeItem.t;
  136.                 } else {
  137.                     const aboveEdgeItem = aboveTile.vedges.filter(e => joins[e.e] && joins[e.e].length === 2)[0];
  138.                     aboveEdge = aboveEdgeItem.e;
  139.                     aboveVflp = !aboveEdgeItem.l;
  140.                 }
  141.                 aboveImgItem.vflp = aboveVflp;
  142.             } else {
  143.                 if (!aboveRot) {
  144.                     aboveEdge = aboveTile.hedges[0].e;
  145.                 } else {
  146.                     aboveEdge = aboveTile.vedges[0].e;
  147.                 }
  148.                 aboveVflp = aboveImgItem.vflp;
  149.             }
  150.  
  151.             if (!thatRot) {
  152.                 const thatEdgeItem = thatTile.hedges.filter(e => e.e === aboveEdge)[0];
  153.                 thatVflp = !thatEdgeItem.t;
  154.             } else {
  155.                 const thatEdgeItem = thatTile.vedges.filter(e => e.e === aboveEdge)[0];
  156.                 thatVflp = thatEdgeItem.l;
  157.             }
  158.  
  159.             delete joins[aboveEdge];
  160.             if (!thatRot) {
  161.                 edgeRemove(thatTile.hedges, aboveEdge);
  162.             } else {
  163.                 edgeRemove(thatTile.vedges, aboveEdge);
  164.             }
  165.             if (!aboveRot) {
  166.                 edgeRemove(aboveTile.hedges, aboveEdge);
  167.             } else {
  168.                 edgeRemove(aboveTile.vedges, aboveEdge);
  169.             }
  170.         }
  171.  
  172.         img[row].push({
  173.             id: thatId,
  174.             rot: thatRot,
  175.             vflp: thatVflp,
  176.             hflp: thatHflp,
  177.         });
  178.  
  179.         //console.log(img);
  180.  
  181.         delete joins[thisEdge];
  182.         if (!thisRot) {
  183.             edgeRemove(thisTile.vedges, thisEdge);
  184.         } else {
  185.             edgeRemove(thisTile.hedges, thisEdge);
  186.         }
  187.         if (!thatRot) {
  188.             edgeRemove(thatTile.vedges, thisEdge);
  189.         } else {
  190.             edgeRemove(thatTile.hedges, thisEdge);
  191.         }
  192.  
  193.         thisId = thatId;
  194.         thisRot = thatRot;
  195.         thisTile = thatTile;
  196.     }
  197.  
  198.     let startEdge, startVflp, belowId;
  199.  
  200.     if (!startRot) {
  201.         const startEdgeItem = startTile.hedges.filter(e => joins[e.e] && joins[e.e].length === 2)[0];
  202.         if (!startEdgeItem) break; // done
  203.         startEdge = startEdgeItem.e;
  204.         startVflp = startEdgeItem.t;
  205.     } else {
  206.         const startEdgeItem = startTile.vedges.filter(e => joins[e.e] && joins[e.e].length === 2)[0];
  207.         if (!startEdgeItem) break; // done
  208.         startEdge = startEdgeItem.e;
  209.         startVflp = !startEdgeItem.l
  210.     }
  211.  
  212.     // If we just started, flip [0, 0] tile as needed
  213.     if (row === 0) {
  214.         img[0][0].vflp = startVflp;
  215.     }
  216.  
  217.     belowId = joins[startEdge].filter(i => i !== startId)[0];
  218.     const belowTile = tiles[belowId];
  219.  
  220.     const belowRot = !(belowTile.hedges[0].e === startEdge || belowTile.hedges[1].e === startEdge);
  221.  
  222.     let belowVflp;
  223.     if (!belowRot) {
  224.         const belowEdgeItem = belowTile.hedges.filter(e => e.e === startEdge)[0];
  225.         belowVflp = !belowEdgeItem.t;
  226.     } else {
  227.         const belowEdgeItem = belowTile.vedges.filter(e => e.e === startEdge)[0];
  228.         belowVflp = belowEdgeItem.l;
  229.     }
  230.  
  231.     img.push([{
  232.         id: belowId,
  233.         rot: belowRot,
  234.         vflp: belowVflp,
  235.     }]);
  236.     row++;
  237.  
  238.     //console.log(img);
  239.  
  240.     delete joins[startEdge];
  241.     if (!startRot) {
  242.         edgeRemove(startTile.hedges, startEdge);
  243.     } else {
  244.         edgeRemove(startTile.vedges, startEdge);
  245.     }
  246.     if (!belowRot) {
  247.         edgeRemove(belowTile.hedges, startEdge);
  248.     } else {
  249.         edgeRemove(belowTile.vedges, startEdge);
  250.     }
  251.  
  252.     startId = belowId;
  253.     startRot = belowRot;
  254.     startTile = belowTile;
  255. }
  256.  
  257. //console.log(img);
  258.  
  259. const transform = (body, rot, hflp, vflp) => {
  260.     const out = [];
  261.     if (rot) {
  262.         for (let i = 1; i < body.length - 1; i++) {
  263.             out.push([]);
  264.             for (let j = 1; j < body[0].length - 1; j++) {
  265.                 out[i - 1][j - 1] = body[j][body.length - i - 1];
  266.             }
  267.         }
  268.     } else {
  269.         for (let i = 1; i < body.length - 1; i++) {
  270.             out.push([]);
  271.             for (let j = 1; j < body[0].length - 1; j++) {
  272.                 out[i - 1][j - 1] = body[i][j];
  273.             }
  274.         }
  275.     }
  276.     if (hflp) {
  277.         for (let i = 0; i < out.length; i++) {
  278.             for (let j = 0; j < Math.floor(out[0].length / 2); j++) {
  279.                 const tmp = out[i][out[0].length - j - 1];
  280.                 out[i][out[0].length - j - 1] = out[i][j];
  281.                 out[i][j] = tmp;
  282.             }
  283.         }
  284.     }
  285.     if (vflp) {
  286.         for (let i = 0; i < Math.floor(out.length / 2); i++) {
  287.             for (let j = 0; j < out[0].length; j++) {
  288.                 const tmp = out[out.length - i - 1][j];
  289.                 out[out.length - i - 1][j] = out[i][j];
  290.                 out[i][j] = tmp;
  291.             }
  292.         }
  293.     }
  294.     return out;
  295. };
  296.  
  297. const out = [];
  298.  
  299. for (let i = 0; i < img.length; i++) {
  300.     for (let j = 0; j < img[0].length; j++) {
  301.         const tile = tiles[img[i][j].id];
  302.         const data = transform(tile.body, img[i][j].rot, img[i][j].hflp, img[i][j].vflp);
  303.  
  304.         for (let a = 0; a < data.length; a++) {
  305.             if (!out[i * data.length + a]) {
  306.                 out[i * data.length + a] = [];
  307.             }
  308.  
  309.             for (let b = 0; b < data[0].length; b++) {
  310.                 out[i * data.length + a][j * data[0].length + b] = data[a][b];
  311.             }
  312.         }
  313.     }
  314. }
  315.  
  316. const variants = (d) => {
  317.     const hd = [];
  318.     const vd = [];
  319.     const hvd = []
  320.     const rd = [];
  321.  
  322.     for (let i = 0; i < d.length; i++) {
  323.         hd.push([]);
  324.         vd.push([]);
  325.         hvd.push([]);
  326.         rd.push([]);
  327.  
  328.         for (let j = 0; j < d[0].length; j++) {
  329.             hd[i][j] = d[i][d[0].length - j - 1];
  330.             vd[i][j] = d[d.length - i - 1][j];
  331.             hvd[i][j] = d[d.length - i - 1][d[0].length - j - 1];
  332.             rd[i][j] = d[j][d.length - i - 1];
  333.         }
  334.     }
  335.  
  336.     const rhd = [];
  337.     const rvd = [];
  338.     const rhvd = []
  339.  
  340.     for (let i = 0; i < rd.length; i++) {
  341.         rhd.push([]);
  342.         rvd.push([]);
  343.         rhvd.push([]);
  344.  
  345.         for (let j = 0; j < rd[0].length; j++) {
  346.             rhd[i][j] = rd[i][rd[0].length - j - 1];
  347.             rvd[i][j] = rd[rd.length - i - 1][j];
  348.             rhvd[i][j] = rd[rd.length - i - 1][rd[0].length - j - 1];
  349.         }
  350.     }
  351.  
  352.     return [
  353.         d, hd, vd, hvd,
  354.         rd, rhd, rvd, rhvd
  355.     ];
  356. };
  357.  
  358. const vars = variants(out);
  359.  
  360. // for (const asdf of [vars[6]]) {
  361. //     console.log('-----');
  362. //     for (let i = 0; i < asdf.length; i++) {
  363. //         console.log(asdf[i].join(''));
  364. //     }
  365. // }
  366.  
  367. let had;
  368. let pic;
  369.  
  370. //   01234567890123456789
  371. // 0                   #
  372. // 1 #    ##    ##    ###
  373. // 2  #  #  #  #  #  #  
  374.  
  375. //for (const asdf of [vars[6]]) {
  376. for (const asdf of vars) {
  377.     had = [];
  378.  
  379.     for (let i = 0; i < asdf.length; i++) {
  380.         for (let j = 0; j < asdf[0].length; j++) {
  381.             if (asdf[i + 0] && asdf[i + 1] && asdf[i + 2] &&
  382.                 asdf[i + 0][j + 18] === '#' &&
  383.                 asdf[i + 1][j +  0] === '#' &&
  384.                 asdf[i + 1][j +  5] === '#' &&
  385.                 asdf[i + 1][j +  6] === '#' &&
  386.                 asdf[i + 1][j + 11] === '#' &&
  387.                 asdf[i + 1][j + 12] === '#' &&
  388.                 asdf[i + 1][j + 17] === '#' &&
  389.                 asdf[i + 1][j + 18] === '#' &&
  390.                 asdf[i + 1][j + 19] === '#' &&
  391.                 asdf[i + 2][j +  1] === '#' &&
  392.                 asdf[i + 2][j +  4] === '#' &&
  393.                 asdf[i + 2][j +  7] === '#' &&
  394.                 asdf[i + 2][j + 10] === '#' &&
  395.                 asdf[i + 2][j + 13] === '#' &&
  396.                 asdf[i + 2][j + 16] === '#') {
  397.  
  398.                 if (!had[i + 0]) {
  399.                     had[i + 0] = [];
  400.                 }
  401.                 if (!had[i + 1]) {
  402.                     had[i + 1] = [];
  403.                 }
  404.                 if (!had[i + 2]) {
  405.                     had[i + 2] = [];
  406.                 }
  407.  
  408.                 had[i + 0][j + 18] = true;
  409.                 had[i + 1][j +  0] = true;
  410.                 had[i + 1][j +  5] = true;
  411.                 had[i + 1][j +  6] = true;
  412.                 had[i + 1][j + 11] = true;
  413.                 had[i + 1][j + 12] = true;
  414.                 had[i + 1][j + 17] = true;
  415.                 had[i + 1][j + 18] = true;
  416.                 had[i + 1][j + 19] = true;
  417.                 had[i + 2][j +  1] = true;
  418.                 had[i + 2][j +  4] = true;
  419.                 had[i + 2][j +  7] = true;
  420.                 had[i + 2][j + 10] = true;
  421.                 had[i + 2][j + 13] = true;
  422.                 had[i + 2][j + 16] = true;
  423.             }
  424.         }
  425.     }
  426.  
  427.     if (had.length > 0) {
  428.         pic = asdf;
  429.         break;
  430.     }
  431. }
  432.  
  433. // console.log(pic);
  434. // console.log(had);
  435.  
  436. let sum = 0;
  437.  
  438. for (let i = 0; i < pic.length; i++) {
  439.     for (let j = 0; j < pic[0].length; j++) {
  440.         if (pic[i][j] === '#' && !(had[i] && had[i][j])) {
  441.             sum++;
  442.         }
  443.     }
  444. }
  445.  
  446. console.log(sum);
  447.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement