Bayangkan sebuah kotak W oleh H kotak yang membungkus toroidally. Item ditempatkan ke kisi sebagai berikut.
Item pertama dapat ditempatkan pada kotak apa saja, tetapi item berikutnya tidak boleh berada dalam jarak Manhattan R dari item sebelumnya (juga dikenal sebagai lingkungan Von Neumann dari rentang R ). Dengan hati-hati memilih posisi memungkinkan pas sejumlah besar item ke grid sebelum tidak ada lagi posisi yang valid. Namun, pertimbangkan tujuan sebaliknya: Berapakah jumlah item terendah yang dapat ditempatkan dan tidak meninggalkan posisi yang valid lebih lanjut?
Berikut adalah zona pengecualian radius 5:
Berikut ini adalah zona pengecualian radius 5 lainnya, kali ini di dekat tepi sehingga perilaku pembungkus terlihat:
Memasukkan
Tiga bilangan bulat:
- W : lebar kotak (bilangan bulat positif)
- H : tinggi kotak (bilangan bulat positif)
- R : radius zona pengecualian (bilangan bulat non-negatif)
Keluaran
Bilangan bulat N , yang merupakan jumlah item terkecil yang dapat ditempatkan mencegah penempatan lebih lanjut yang valid.
Detail
- Jari-jari nol memberikan zona eksklusi 1 kuadrat (yang ditempatkan pada item).
- Jari-jari N tidak termasuk zona yang dapat dicapai dalam langkah-langkah ortogonal N (ingat tepi membungkus toroidally).
Kode Anda harus berfungsi untuk kasus sepele dari R = 0, tetapi tidak perlu bekerja untuk W = 0 atau H = 0.
Kode Anda juga harus berurusan dengan kasus di mana R > W atau R > H .
Batas waktu dan uji kasus
Kode Anda harus dapat menangani semua kasus uji, dan setiap kasus uji harus selesai dalam 5 menit. Ini harus mudah (contoh, solusi JavaScript membutuhkan beberapa detik untuk setiap kasus uji). Batas waktu terutama untuk mengecualikan pendekatan brute force yang ekstrim. Contoh pendekatannya masih cukup brute force.
Jika kode Anda selesai dalam waktu 5 menit pada satu mesin tetapi tidak pada yang lain yang akan cukup dekat.
Uji kasus dalam bentuk input: keluaran sebagaiW H R : N
5 4 4 : 1
5 4 3 : 2
5 4 2 : 2
5 4 1 : 5
7 5 5 : 1
7 5 4 : 2
7 5 3 : 2
7 5 2 : 4
8 8 8 : 1
8 8 7 : 2
8 8 6 : 2
8 8 5 : 2
8 8 4 : 2
8 8 3 : 4
7 6 4 : 2
7 6 2 : 4
11 7 4 : 3
11 9 4 : 4
13 13 6 : 3
11 11 5 : 3
15 14 7 : 2
16 16 8 : 2
Cuplikan untuk membantu memvisualisasikan dan bermain-main dengan ide
canvas = document.getElementById('gridCanvas');ctx = canvas.getContext('2d');widthSelector = document.getElementById('width');heightSelector = document.getElementById('height');radiusSelector = document.getElementById('radius');itemCount = document.getElementById('itemCount');canvasMaxWidth = canvas.width;canvasMaxHeight = canvas.height;gridlineColour = '#888';emptyColour = '#ddd';itemColour = '#420';hoverCellColour = '#840';exclusionColour = '#d22';validColour = '#8f7';invalidColour = '#fbb';overlapColour = '#600';resetGrid();x = -1;y = -1;function resetGrid() {gridWidth = widthSelector.value;gridHeight = heightSelector.value;radius = radiusSelector.value;numberOfItems = 0;itemCount.value = numberOfItems + ' items placed.';cells = [gridWidth * gridHeight];for (i=0; i<gridWidth*gridHeight; i++) {cells[i] = '#ddd';}cellSize = Math.min(Math.floor(canvasMaxWidth/gridWidth), Math.floor(canvasMaxHeight/gridHeight));pixelWidth = gridWidth * cellSize + 1;canvas.width = pixelWidth;pixelHeight = gridHeight * cellSize + 1;canvas.height = pixelHeight;leaveCanvas();}function checkPosition(event) {bound = canvas.getBoundingClientRect();canvasX = event.clientX - bound.left;canvasY = event.clientY - bound.top;newX = Math.min(Math.floor(canvasX / cellSize), gridWidth-1);newY = Math.min(Math.floor(canvasY / cellSize), gridHeight-1);if (newX != x || newY != y) {x = newX;y = newY;drawGrid();}}function leaveCanvas() {x = -1;y = -1;drawGrid();}function drawGrid() {ctx.fillStyle = gridlineColour;ctx.fillRect(0, 0, pixelWidth, pixelHeight);cellColour = cells[x + gridWidth * y];if (cellColour == itemColour || cellColour == exclusionColour) {zoneColour = invalidColour;} else {zoneColour = validColour;}for (gridX=0; gridX<gridWidth; gridX++) {for (gridY=0; gridY<gridHeight; gridY++) {colour = (cells[gridX + gridWidth * gridY]);if (x >= 0 && y >= 0) {if (x == gridX && y == gridY) {colour = hoverCellColour;} else if (manhattanDistance(x, y, gridX, gridY) <= radius) {if (colour == exclusionColour) {colour = overlapColour;} else if (colour != itemColour) {colour = zoneColour;}}}ctx.fillStyle = colour;ctx.fillRect(gridX * cellSize + 1, gridY * cellSize + 1, cellSize - 1, cellSize - 1);}}}function manhattanDistance(a, b, c, d) {horizontal = Math.min(Math.abs((gridWidth + c - a) % gridWidth), Math.abs((gridWidth + a - c) % gridWidth));vertical = Math.min(Math.abs((gridHeight + d - b) % gridHeight), Math.abs((gridHeight + b - d) % gridHeight));return vertical + horizontal;}function placeItem(event) {bound = canvas.getBoundingClientRect();canvasX = event.clientX - bound.left;canvasY = event.clientY - bound.top;attemptX = Math.min(Math.floor(canvasX / cellSize), gridWidth-1);attemptY = Math.min(Math.floor(canvasY / cellSize), gridHeight-1);colour = cells[attemptX + gridWidth * attemptY];if (colour != itemColour && colour != exclusionColour) {for (a=0; a<gridWidth; a++) {for (b=0; b<gridHeight; b++) {if (manhattanDistance(a, b, attemptX, attemptY) <= radius) {cells[a + gridWidth * b] = exclusionColour;}}}cells[attemptX + gridWidth * attemptY] = itemColour;drawGrid();numberOfItems++;itemCount.value = numberOfItems + ' items placed.';}}
<canvas id='gridCanvas' width='500' height='300' style='border:none' onmousemove='checkPosition(event)' onmouseleave='leaveCanvas()' onclick='placeItem(event)'></canvas><br><textarea id='itemCount' readonly></textarea><br><button id='reset' onclick='resetGrid()'>Reset</button> with the following values:<br>Width:<input id='width' type='number' value='20' min='1' max='50' maxlength='2' step='1'><br>Height:<input id='height' type='number' value='13' min='1' max='30' maxlength='2' step='1'><br>Radius:<input id='radius' type='number' value='5' min='0' max='60' maxlength='2' step='1'>
Contoh solusi (ungolfed)
Hanya contoh untuk output kecil (dihasilkan dari jari-jari tidak jauh lebih kecil dari lebar dan tinggi). Dapat menangani salah satu kasus uji tetapi akan kehabisan waktu dan menyerah untuk sebagian besar kasus yang lebih besar.
itemCount = document.getElementById('itemCount')
calculateButton = document.getElementById('calculate')
widthSelector = document.getElementById('width')
heightSelector = document.getElementById('height')
radiusSelector = document.getElementById('radius')
function calculate() {
calculateButton.disabled = true
widthSelector.disabled = true
heightSelector.disabled = true
radiusSelector.disabled = true
itemCount.value = 'Calculating...'
setTimeout(delayedCalculate, 100)
}
function delayedCalculate() {
gridWidth = widthSelector.value
gridHeight = heightSelector.value
radius = radiusSelector.value
startingMin = gridWidth*gridHeight + 1
var cells = [gridWidth * gridHeight]
for (i=0; i<gridWidth*gridHeight; i++) {
cells[i] = 0
}
var gridState = gridWithItemAdded(cells, 0, 0)
var minimum = minFromHere(gridState) + 1
itemCount.value = 'Minimum ' + minimum + ' items required.'
calculateButton.disabled = false
widthSelector.disabled = false
heightSelector.disabled = false
radiusSelector.disabled = false
}
function minFromHere(gridState) {
var x
var y
var newGridState
var noCells = true
var min = startingMin
for (x=0; x<gridWidth; x++) {
for (y=0; y<gridHeight; y++) {
if (gridState[x + gridWidth * y] == 0) {
noCells = false
newGridState = gridWithItemAdded(gridState, x, y)
m = minFromHere(newGridState)
if (m < min) {
min = m
}
}
}
}
if (noCells) return 0
return min + 1
}
function gridWithItemAdded(gridState, x, y) {
var a
var b
var grid = gridState.slice()
for (a=0; a<gridWidth; a++) {
for (b=0; b<gridHeight; b++) {
if (manhattanDistance(a, b, x, y) <= radius) {
grid[a + gridWidth * b] = 1
}
}
}
return grid
}
function manhattanDistance(a, b, c, d) {
horizontal = Math.min(Math.abs((gridWidth + c - a) % gridWidth), Math.abs((gridWidth + a - c) % gridWidth))
vertical = Math.min(Math.abs((gridHeight + d - b) % gridHeight), Math.abs((gridHeight + b - d) % gridHeight))
return vertical + horizontal
}
<textarea id='itemCount' readonly></textarea>
<br>
<button id='calculate' onclick='calculate()'>Calculate</button> with the following values:
<br>
Width:<input id='width' type='number' value='5' min='1' max='50' maxlength='2' step='1'>
<br>
Height:<input id='height' type='number' value='4' min='1' max='30' maxlength='2' step='1'>
<br>
Radius:<input id='radius' type='number' value='1' min='0' max='60' maxlength='2' step='1'>
Jawaban:
Python 2,
216182 byteMasukan seperti
f(16,16,8)
. Menggunakan hampir sama algoritma dengan sampel @ trichoplax , tetapi dengan set. Awalnya saya tidak menempatkan item pertama(0, 0)
, tetapi ini membuatnya tersedak pada beberapa kasus terakhir.Semua case di atas selesai dalam 10 detik, jauh di bawah batas. Faktanya, kasingnya cukup kecil sehingga saya mempunyai sedikit ruang agar kurang efisien, memungkinkan saya untuk menghapus cek yang memeriksa keadaan duplikat.
(Terima kasih kepada @trichoplax untuk bantuan bermain golf)
Diperluas:
sumber
Python 3,
270262260251246226(Terima kasih kepada Sp3000 untuk:
-~
alih-alih+1
, yang membuat saya kehilangan tempat setelahreturn
di baris terakhir.W*H
.%
memberikan hasil positif untuk angka negatif, untuk menghemat 20 byte lainnya)Ini adalah jawaban contoh JavaScript dari pertanyaan yang diangkut ke Python 3.
Untuk menghindari keharusan melewati begitu banyak argumen fungsi di sekitar, saya telah memindahkan dua fungsi pendukung di dalam fungsi kalkulasi sehingga mereka berbagi ruang lingkupnya. Saya juga menyingkat masing-masing fungsi ini menjadi satu baris untuk menghindari biaya indentasi.
Penjelasan
Pendekatan kekuatan yang cukup kasar ini menempatkan item pertama di (0, 0), dan kemudian menandai semua kotak yang dikecualikan. Itu kemudian secara rekursif menempatkan item di semua kotak yang tersisa sampai semua kotak dikeluarkan, dan mengembalikan jumlah item minimum yang diperlukan.
Kode golf:
Kode tidak dikunci:
Kode ungolfed mendefinisikan fungsi dan juga menyertakan kode untuk memungkinkannya dipanggil dari baris perintah. Kode golf hanya mendefinisikan fungsi, yang cukup untuk pertanyaan golf kode standar .
Jika Anda ingin menguji kode golf dari baris perintah, ini dia termasuk penanganan baris perintah (tetapi tidak golf):
Baris perintah kode golf dapat diuji
sumber