Нахождение координат по сетке (2D массив) - PullRequest
0 голосов
/ 17 сентября 2018

В настоящее время я пытаюсь решить проблему, которую не удалось решить в фиктивном интервью на доске.Я застрял несколько раз.Любая помощь приветствуется.

Вопрос был сформулирован так:

С учетом сетки NxN с массивом координат лампы.Каждая лампа обеспечивает освещение для каждого квадрата на их оси X, каждого квадрата на их оси Y и каждого квадрата, который лежит в их диагонали (вспомним о королеве в шахматах).Учитывая массив координат запроса, определите, освещена ли эта точка или нет.

Подвох в том, что при проверке запроса все лампы, находящиеся рядом или включенные в этот запрос, отключаются.Если вы посещаете координату / ячейку, выключите все лампы, которые находятся в этих координатах или рядом.Две ячейки являются смежными, если они имеют один и тот же край или угол.

  • написать функцию checkLampIllumination(N, lamps, queries)
  • N: размер сетки
  • lamps: координаты лампы
  • queries: координаты на сетке, которые нужно проверить, горят они или нет

Тестовый пример, который мне дали, был:

N = 8

lamps = [
    [1,6],
    [5,6],
    [7,3],
    [3,2]
]

queries = [
    [4,4],
    [6,6],
    [8,1],
    [3,2],
    [2,3]
]

ВЫХОД:

['DARK','LIGHT','DARK','DARK','LIGHT']

Второй тестовый пример:

checkLampIllumination(8, [[4,3],[4,4]], [[3,4],[7,6]])

N = 8

lamps = [
    [4,3],
    [4,4]
]

queries = [
    [3,4],
    [7,6]
]

ВЫХОД:

['DARK','LIGHT']

Вот мой текущий удар по нему,Я думаю, что текущее решение просто создает сетку.Я действительно не знаю, куда идти отсюда.

const checkLampIllumination=(N, lamps, queries) => {
    var gridNxN = []
    var row = []
    for (var i = 1; i < 100; i++) {
        if (i.toString().indexOf('0') !== -1) {
            row.push(i)
            gridNxN.push(row)
            row = []
        } else {
            row.push(i)
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Поскольку сейчас мы не на собеседовании, я решил сохранить код не компактным, чтобы его было легче понять.Вы можете сократить его, если хотите.Мне нравятся такие проблемы, поэтому я не торопился с этим.

Также я обновил визуальную сетку.Теперь вы можете видеть состояние сетки при ее изменении.

var lamps = [
    [1,6],
    [5,6],
    [7,3],
    [3,2]
];

var queries = [
    [4,4],
    [6,6],
    [8,1],
    [3,2],
    [2,3]
];

/* ==================== VISUAL GRID ==================== */

function arrayFlatten(array) {
    var result = [];
    array.forEach(function (item) {
        if (item instanceof Array) {
            result = result.concat(arrayFlatten(item));
        } else {
            result.push(item);
        }
    });
    return result;
}

function createGrid(lamps, queries) {
    var grid = document.createElement("table");
    grid.classList.add("grid");
    var gridSize = Math.max.apply(null, arrayFlatten([lamps, queries])) + 1;
    
    document.body.appendChild(grid);
    
    // create cells
    for (var i = 0; i < gridSize; i++) {
        var row = document.createElement("tr");
        for (var j = 0; j < gridSize; j++) {
            var cell = document.createElement("td");
            row.appendChild(cell);
        }
        grid.appendChild(row);
    }
    
    // add lamps
    lamps.forEach(lamp => grid.rows[lamp[1]].cells[lamp[0]].classList.add("lamp"));

    var illuminatedRows = Array.from(new Set(lamps.map(([lampX, lampY]) => lampY)));
    var illuminatedCols = Array.from(new Set(lamps.map(([lampX, lampY]) => lampX)));
    illuminatedRows.sort();
    illuminatedCols.sort();

    // add lights
    // horizontal
    for (var i = 0; i < grid.rows.length; i++) {
        if (illuminatedRows.includes(i)) {
            Array.from(grid.rows[i].cells).forEach(cell => cell.classList.add("horizontal-light"));
        }
    }
    // vertical
    for (var i = 0; i < grid.rows.length; i++) {
        for (var j = 0; j < grid.rows[i].cells.length; j++) {
            if (illuminatedCols.includes(j)) {
                grid.rows[i].cells[j].classList.add("vertical-light");
            }
        }
    }
    // diagonal
    for (var i = 0; i < grid.rows.length; i++) {
        for (var j = 0; j < grid.rows[i].cells.length; j++) {
            var x = j;
            var y = i;
            lamps.forEach(function (lamp) {
                if (isDiagonal(lamp[0], lamp[1], x, y)) {
                    grid.rows[i].cells[j].classList.add("diagonal-light");
                }
            });
        }
    }
    
}

createGrid(lamps, queries);

/* ==================== CALCULATION ==================== */

function isHorizontal(y1, y2) {
    return y1 == y2;
}

function isVertical(x1, x2) {
    return x1 == x2;
}

function isDiagonal(x1, y1, x2, y2) {
    return Math.abs(x1 - x2) == Math.abs(y1 - y2);
}

function isIlluminated(queryX, queryY, lampX, lampY) {
    return isHorizontal(queryY, lampY) || isVertical(queryX, lampX) || isDiagonal(queryX, queryY, lampX, lampY);
}

function isAdjacent(x1, y1, x2, y2) {
    return Math.abs(x2 - x1) < 2 && Math.abs(y2 - y1) < 2
}

// check every lamp for each query
function checkLamps(lamps, queryX, queryY) {
    // store checks for each lamp for a query
    var checks = [];
    // loop every lamp
    for (var i = lamps.length - 1; i >= 0; i--) {
        var lampX = lamps[i][0];
        var lampY = lamps[i][1];
        // check if the target cell is adjacent to the current lamp
        if (isAdjacent(queryX, queryY, lampX, lampY)) {
            console.log("Query (" + [queryX, queryY].join() + ") is adjacent to lamp (" + [lampX, lampY].join() + "). Removing this lamp.");
            // lamp is adjacent; remove it
            lamps.splice(i, 1);
            // create a grid with the new state (for visual purposes)
            createGrid(lamps, queries);
            // skip this lamp
            continue;
        } else {
            // storing the check for the current lamp
            checks.push(isIlluminated(queryX, queryY, lampX, lampY));
        }
    }
    // if all checks are false, it's dark
    // if there's even a single true, that means the cell is illuminated by a lamp
    if (checks.includes(true)) {
        console.log("(" + [queryX, queryY].join() + ") is LIGHT");
    } else {
        console.log("(" + [queryX, queryY].join() + ") is DARK");
    }
}

function checkLampIllumination(lamps, queries) {
    // create a local copy of lamps because it'll (might) mutate
    var lamps = lamps.slice();
    // loop queries
    queries.forEach(([queryX, queryY]) => checkLamps(lamps, queryX, queryY));
}

checkLampIllumination(lamps, queries);
.grid {
    background-color: black;
    border-collapse: collapse;
    margin-right: 1em;
    float: left;
}
.grid td {
    width: 25px;
    height: 25px;
    border: 1px solid hsl(0, 0%, 50%);
}
.grid td.horizontal-light,
.grid td.vertical-light,
.grid td.diagonal-light {
    background-color: hsla(0, 0%, 80%, .33);
}
.grid td.horizontal-light.vertical-light,
.grid td.horizontal-light.diagonal-light,
.grid td.vertical-light.diagonal-light {
    background-color: hsla(0, 0%, 80%, .45);
}
.grid td.horizontal-light.vertical-light.diagonal-light {
    background-color: hsla(0, 0%, 80%, .6);
}
.grid td.lamp {
    background-color: hsl(0, 0%, 100%) !important;
}
0 голосов
/ 17 сентября 2018

Только для визуализации ламп и запросов вы можете поиграть с генератором пиксельных изображений , если хотите.

Сначала я создал бы вспомогательную функцию isAdjacent, чтобы проверить,две точки являются смежными.Затем выполните итерацию по каждому запросу (квадрат цели) и проверьте, освещает ли цель лампу.Проблема сводится к проверке того, что:

  • Лампа не находится рядом, и верно хотя бы одно из следующих условий:

  • Лампа либоимеет одинаковую координату X, или

  • такая же координата Y, или

  • они находятся на одной диагонали, что можно проверить с помощьювидя, что разница между координатами X лампы и цели равна разнице между координатами Y лампы и цели.

Поместив это в код, вы получите:

let lamp = [
  [1, 6],
  [5, 6],
  [7, 3],
  [3, 2]
];
const queries = [
  [4, 4],
  [6, 6],
  [8, 1],
  [3, 2],
  [2, 3]
]

const isAdjacent = (x1, y1, x2, y2) => Math.abs(x2 - x1) < 2 && Math.abs(y2 - y1) < 2;
queries.forEach(([checkX, checkY]) => {
  const thisSquareIlluminated = lamp.some(([lampX, lampY]) => (
    !isAdjacent(checkX, checkY, lampX, lampY) && (
      lampX === checkX
      || lampY === checkY
      || Math.abs(lampX - checkX) === Math.abs(lampY - checkY)
    )
  ));
  console.log(thisSquareIlluminated ? 'LIGHT' : 'DARK');
});

Я бы не рекомендовал строить подсвеченные квадраты заранее, потому что тогда, задав запрос, вы не узнаете, имеет ли конкретный квадрат с подсветкой только освещение из-засоседняя лампа или нет, по крайней мере, без повторения всех ламп снова - лучше просто выполнить итерацию по ним один раз, после выбора запроса.

Обратите внимание, что вход N = 8 нигде не используется - этокрасная сельдь, если вам также не нужно проверять, находятся ли лампы / запросы в допустимых местах на доске.

...