पैटरसन के कीड़े एक प्रकार के सेलुलर ऑटोमोबोन हैं जो एक अनंत त्रिकोणीय ग्रिड पर मौजूद हैं और, हर कदम, वे किसी दिशा में मुड़ते हैं और एक इकाई को स्थानांतरित करते हैं। उनके परिभाषित गुण यह हैं कि वे कभी भी एक ही स्थान पर दो बार नहीं जा सकते हैं, और जब भी वे एक ही परिवेश का सामना करते हैं, तो वे एक ही निर्णय लेते हैं। एक कीड़ा हमेशा 3 से स्थित अपनी पूंछ के साथ अपने दृष्टिकोण से "देखता है" और इस षट्भुज के केंद्र में स्थित उसका सिर:
उदाहरण के लिए, नियमों के साथ कृमि पर विचार करें:
- यदि 0, 1, 2, 4, और 5 सभी खाली हैं, तो दिशा 2 में चलें
- यदि 0, 1, 4 और 5 खाली हैं, और 2 भरा हुआ है, तो दिशा 0 में चलें
- यदि 0, 1, और 5 रिक्त हैं, और 2 और 4 भरे हुए हैं, तो दिशा 0 में चलें
इसके परिणामस्वरूप निम्न पथ (विकिपीडिया से) है:
यदि कीड़ा खुद को ऐसी स्थिति में पाता है जहां सभी परिवेश भरे होते हैं, तो यह समाप्त हो जाता है।
इनपुट
संख्याओं की एक सूची। Nth संख्या इंगित करती है कि कृमि को nth की नई स्थिति पर क्या निर्णय लेना चाहिए, जिससे उसका सामना होता है जहां उसे निर्णय लेना होता है। ध्यान दें कि यदि सभी लेकिन इसका एक परिवेश भरा हुआ है, तो इसे केवल उसी दिशा में बढ़ना चाहिए जो खाली है। यह "निर्णय" के रूप में नहीं गिना जाता है और एक संख्या का उपभोग नहीं करता है। ऊपर दिखाए गए उदाहरण कृमि को उत्पन्न करने के लिए, इनपुट होगा [2, 0, 0]
। इनपुट को एक कीड़ा पैदा करने की गारंटी दी जाती है, जो समाप्त हो जाता है और उसका पथ नहीं देता है, और इनपुट कभी कम नहीं होगा।
उत्पादन
निर्देशांक की एक सूची का उत्पादन जहां यह दर्शाता है कि कृमि का सिर कहां से शुरू होता है (1, 0)
। हम केवल y- मूल्य में कमी करने के लिए ऊपर और दाईं ओर बढ़ने पर विचार करेंगे, लेकिन x- मूल्य में कमी और y- मूल्य में कमी होने के लिए ऊपर और बाईं ओर बढ़ना। उदाहरण के लिए, उदाहरण इनपुट के लिए पथ का आउटपुट है
(1, 0), (1, 1), (0, 0), (-1, -1), (0, -1), (0, 0), (0, 1), (-1, 0), (0, 0)
परीक्षण के मामलों
आप परीक्षण चलाने के लिए जावास्क्रिप्ट स्निपेट का भी उपयोग कर सकते हैं।
[2,0,0]: (1,0),(1,1),(0,0),(-1,-1),(0,-1),(0,0),(0,1),(-1,0),(0,0)
[1,0,4,0,1,5]: (1,0),(2,1),(2,2),(1,2),(0,1),(0,0),(0,-1),(1,-1),(2,0),(2,1),(3,1),(4,2),(4,3),(3,3),(2,2),(1,1),(1,0),(2,0),(3,1),(3,0),(4,0),(5,1),(5,2),(4,2),(3,2),(2,1),(1,1),(0,0),(-1,0),(-2,-1),(-2,-2),(-1,-2),(0,-1),(1,0),(1,-1),(2,-1),(3,0),(4,1),(4,2),(5,3),(5,4),(4,4),(3,3),(3,4),(2,4),(1,3),(1,2),(1,1),(0,1),(-1,0),(-1,1),(-2,1),(-3,0),(-3,-1),(-2,-1),(-1,-1),(0,0)
[1,0,5,1]: (1,0),(2,1),(2,2),(1,2),(0,1),(0,0),(0,-1),(1,-1),(2,0),(2,1),(3,2),(3,3),(2,3),(1,2),(0,2),(-1,1),(-1,0),(0,0),(1,1),(1,2),(1,3),(0,3),(-1,2),(-1,1),(-2,0),(-2,-1),(-1,-1),(0,0)
[2,0,1,0]: (1,0),(1,1),(0,0),(-1,-1),(0,-1),(0,0),(-1,0),(-1,-1),(-1,-2),(0,-1),(1,0),(2,1),(1,1),(0,1),(0,0)
निम्नलिखित जल्दबाजी में इकट्ठे (संभवतः छोटी गाड़ी) कार्यक्रम में कीड़े दिखाई देंगे:
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
var input, memory;
var log = str => {
console.log(str);
document.querySelector("textarea").value += str + "\n";
};
var orientations = [
[1, 0],
[1, 1],
[0, 1],
[-1, 0],
[-1, -1],
[0, -1]
];
var arena = {
grid: [[[1, 0, 0]]],
maxX: 1,
maxY: 0,
expandGrid: function() {
var grid = this.grid;
var newWidth = grid[0].length + 2,
newHeight = grid.length + 2;
var createRow = () => {
var result = [];
for (let i = 0; i < newWidth; ++i) result.push([0, 0, 0]);
return result;
};
for (let row of grid) {
row.push([0, 0, 0]);
row.unshift([0, 0, 0]);
};
grid.push(createRow());
grid.unshift(createRow());
},
gridWidth: function() {
return this.grid[0].length
},
gridHeight: function() {
return this.grid.length
},
get: function(x, y) {
var colOffset = Math.floor(this.gridWidth() / 2),
rowOffset = Math.floor(this.gridHeight() / 2);
return this.grid[y + rowOffset][x + colOffset];
},
isAtEnd: function(x, y) {
var colOffset = Math.floor(this.gridWidth() / 2),
rowOffset = Math.floor(this.gridHeight() / 2);
return x === -colOffset || x + colOffset + 1 === this.gridWidth() ||
y === -rowOffset || y + rowOffset + 1 === this.gridHeight();
},
getEdge: function(x, y, o) {
if (o % 2 === 0) return this.get(x, y)[o / 2];
else {
let a, b;
[a, b] = orientations[(o + 3) % 6];
return this.get(x - a, y - b)[((o + 3) % 6) / 2];
}
},
setEdge: function(x, y, o) {
if (Math.abs(x) > this.maxX) this.maxX = Math.abs(x);
if (Math.abs(y) > this.maxY) this.maxY = Math.abs(y);
if (o % 2 === 0) {
if (this.get(x, y)[o / 2]) throw new Error("Path already taken");
this.get(x, y)[o / 2] = 1;
} else {
let a, b;
[a, b] = orientations[(o + 3) % 6];
if (this.get(x - a, y - b)[((o + 3) % 6) / 2]) throw new Error("Path already taken");
this.get(x - a, y - b)[((o + 3) % 6) / 2] = 1;
}
}
};
var drawGrid = function(area) {
var width = canvas.width,
height = canvas.height;
ctx.clearRect(0, 0, width, height);
var gridWidth = arena.gridWidth(),
gridHeight = arena.gridHeight();
var triangleLen = Math.floor(Math.min(
width / (arena.maxX * 2 + arena.maxY),
height / (arena.maxY * Math.sqrt(3)),
width / 4
));
var convert = (x, y) => [(x - y / 2) * triangleLen, triangleLen * y * Math.sqrt(3) / 2];
var drawCirc = function(x, y) {
var a, b;
ctx.beginPath();
[a, b] = convert(x, y);
ctx.arc(a, b, 5, 0, 2 * Math.PI);
ctx.fill();
};
ctx.fillStyle = "black";
for (let y = 0; triangleLen * y * Math.sqrt(3) / 2 < height; ++y) {
for (let x = Math.floor(y / 2); triangleLen * (x - y / 2) < width; ++x) {
drawCirc(x, y);
}
};
var drawLine = function(a, b, c, d) {
var x, y;
ctx.beginPath();
[x, y] = convert(a, b);
ctx.moveTo(x, y);
[x, y] = convert(a + c, b + d);
ctx.lineTo(x, y);
ctx.stroke();
};
var centerY = Math.round(height / (triangleLen * Math.sqrt(3)));
var centerX = Math.round(width / (2 * triangleLen) + centerY / 2);
ctx.fillStyle = "red";
drawCirc(centerX, centerY);
for (let row = -(gridHeight - 1) / 2; row < (gridHeight + 1) / 2; ++row) {
for (let col = -(gridWidth - 1) / 2; col < (gridWidth + 1) / 2; ++col) {
let lines = arena.get(col, row);
for (let j = 0; j < lines.length; ++j) {
if (lines[j]) {
let or = orientations[2 * j];
drawLine(col + centerX, row + centerY, or[0], or[1]);
}
}
}
}
};
var step = function(x, y, absoluteOrientation) {
log('(' + x + ',' + y + ')');
var surroundings = 0;
for (let i = 0; i < 6; ++i) {
if (arena.getEdge(x, y, (absoluteOrientation + i) % 6)) {
surroundings |= (1 << i);
}
}
if (surroundings == 63) {
console.log("Done!");
return;
}
var action;
if (memory[surroundings] !== undefined)
action = memory[surroundings];
else {
action = input.shift();
memory[surroundings] = action;
}
absoluteOrientation = (absoluteOrientation + action) % 6;
arena.setEdge(x, y, absoluteOrientation);
var or = orientations[absoluteOrientation];
x += or[0];
y += or[1];
if (arena.isAtEnd(x, y)) arena.expandGrid();
drawGrid(arena);
setTimeout(function() {
step(x, y, absoluteOrientation);
}, parseFloat(document.querySelector("input[type=number]").value));
};
var go = function() {
input = document.querySelector("input[type=text]").value.split(",").map(x => parseInt(x, 10));
arena.grid = [[[1, 0, 0]]];
arena.maxX = 1;
arena.maxY = 0;
memory = {};
for (let i = 0; i < 6; ++i) {
memory[(~(1 << i)) & 63] = i;
}
arena.expandGrid();
arena.expandGrid();
step(1, 0, 0);
};
document.querySelector("button").onclick = go;
canvas {
border: 1px solid black;
}
Input: <input type="text" placeholder="Comma separated input"><br />
Delay (ms): <input type="number" placeholder="delay" value="500"/><button>Go</button><br />
<canvas width="500" height="400"></canvas><br />
<textarea></textarea>
[1,0,4,2,0,1,5]
।)