Соседние клетки
Я редко пишу что-то в этот канал, потому что на интересные посты обычно нужно потратить много времени. Но само его наличие мне очень нравится! Например, часто в комментарии приходят умные люди и рассказывают, как на самом деле что-то надо было сделать :)
Так вот, представим, что у нас есть клеточное поле размером
В совсем крайнем случае можно написать 4 похожих куска кода:
Но дублировать код не хочется. Если забыть на секундочку о типах, то можно написать примерно так:
Это бы нормально работало, если бы все переменные были типа
И это выглядит некрасиво. Плюс придется из-за этого сделать
Так вот, как проще всего писать такой код на Rust?
P. S. Я еще видел такой вариант (overflowing_add и .0 это обычное сложение, которое разрешает переполнение):
Я редко пишу что-то в этот канал, потому что на интересные посты обычно нужно потратить много времени. Но само его наличие мне очень нравится! Например, часто в комментарии приходят умные люди и рассказывают, как на самом деле что-то надо было сделать :)
Так вот, представим, что у нас есть клеточное поле размером
width
*height
и вы пишете bfs на нем. Есть текущая клетка (row
, col
). Как обойти всех непосещенных соседей (по стороне) этой клетки?В совсем крайнем случае можно написать 4 похожих куска кода:
if row + 1 < height && !used[row + 1][col] {
used[row + 1][col] = true;
queue.push((row + 1, col));
}
if col + 1 < width && !used[row][col + 1] {
...
}
Но дублировать код не хочется. Если забыть на секундочку о типах, то можно написать примерно так:
for (dr, dc) in [(0, 1), (1, 0), (0, -1), (-1, 0)] {
let nrow = row + dr;
let ncol = col + dc;
if 0 <= nrow && nrow < height && 0 <= ncol && ncol < width && !used[nrow][ncol] {
used[nrow][ncol] = true;
queue.push((nrow, ncol));
}
}
Это бы нормально работало, если бы все переменные были типа
i32
. Но в Rust массивы индексируются только типом usize
, который беззнаковый. Поэтому в каком-то месте придется приводить типы. Условно:used[nrow as usize][ncol as usize]
И это выглядит некрасиво. Плюс придется из-за этого сделать
width
и height
типа i32
, а интуитивно кажется, что они должны быть usize
, иначе придется много где добавлять лишние касты.Так вот, как проще всего писать такой код на Rust?
P. S. Я еще видел такой вариант (overflowing_add и .0 это обычное сложение, которое разрешает переполнение):
for (dr, dc) in [(0, 1), (1, 0), (0, !0), (!0, 0)] {
let nrow = row.overflowing_add(dr).0;
let ncol = col.overflowing_add(dc).0;
if nrow < height && ncol < width && !used[nrow][ncol] {
used[nrow][ncol] = true;
queue.push((nrow, ncol));
}
}