программирование
April 18, 2018

Вариант решения задачи про сапера

Один из подписчиков прислал неплохой вариант решения задачи про сапера.

Напомню текст задачи:

Дан файл с решеткой N x N (разделители пробел и \n), который представляет собой минное поле из игры Сапер. O - означает что на поле нет мины, X - что есть. Нужно заменить все O на количество смежных мин (всего смежных клеток 8 - по горизонтали, вертикали и диагонали).

Пример:

Входной файл:

X O O X X X O O
O O O O X O X X
X X O X X O O O
O X O O O X X X
O O X X X X O X
X O X X X O X O
O O O X O X O X
X O X X O X O X

Вывод в консоль:

X 1 1 X X X 3 2
3 3 3 5 X 5 X X
X X 3 X X 5 5 4
3 X 5 5 6 X X X
2 4 X X X X 6 X
X 3 X X X 5 X 3
2 4 5 X 6 X 5 X
X 2 X X 4 X 4 X

А вот один из вариантов решения (на JavaScript):

let str = 'X O O X X X O O\nO O O O X O X X\nX X O X X O O O\nO X O O O X X X\nO O X X X X O X\nX O X X X O X O\nO O O X O X O X\nX O X X O X O X';

let m = str.split('\n').map(item => item.split(' '));
                            
let extraLog = false;

m.forEach(item => {
	console.log(item.join(' '))
});


if (extraLog) {
  console.log('\n');
  console.log('y | x | range | above > below');
  console.log('-----------------------------');
}

let n = m.map((item, index, arr) => {
	let newStr = [];
	
  item.forEach((subitem, subindex, subarr) => {
  	if (subitem === 'X') {
    	newStr.push('X');
    	return;
    }
 
  	let startX = (subindex > 0 ? subindex - 1 : 0);
    let endX =  subindex < subarr.length ? subindex + 1 : subindex;
    
    let aboveArr = index > 0 ? getFilteredArray(arr[index - 1]) : [];
    let belowArr = index < arr.length - 1 ? getFilteredArray(arr[index + 1]) : [];
    
    if (extraLog)
      console.log(index + ' | ' + subindex + ' | ' + startX + ' - ' + endX + ' | ', aboveArr, ' | ', belowArr);
    
    let aboveCount = aboveArr.length;
    let belowCount = belowArr.length;
    let left = (subindex > 0 && subarr[subindex - 1] === 'X' ? 1 : 0);
    let right = (subindex < subarr.length && subarr[subindex + 1] === 'X' ? 1 : 0);
    
    newStr.push(aboveCount + belowCount + left + right);
    
    function getFilteredArray(arr) {
    	return arr.slice(startX, endX + 1).filter(item => item === 'X');
    }
  })
   
  return newStr;
})
 
console.log('\n');
n.forEach(item => {
	console.log(item.join(' '));
})
console.log('\n');

Для тех, кто хочет поточнее разобраться, как работает данный код: просто измените значение переменной extraLog на true. Тогда в консоль будет выведена логика перебора массива.