Ein Node.JS JavaScript-Lösungsansatz. Berechnet alle 100 eindeutigen Wörter in weniger als einer Sekunde, einschließlich dem Lesen der Wörterdatei (MBA 2012).
Ausgabe:
["FAM","TUX","TUB","FAE","ELI","ELM","ELB","TWA","TWA","SAW","AMI","SWA","SWA","AME","SEA","SEW","AES","AWL","AWE","SEA","AWA","MIX","MIL","AST","ASE","MAX","MAE","MAW","MEW","AWE","MES","AWL","LIE","LIM","AWA","AES","BUT","BLO","WAS","WAE","WEA","LEI","LEO","LOB","LOX","WEM","OIL","OLM","WEA","WAE","WAX","WAF","MILO","EAST","WAME","TWAS","TWAE","EMIL","WEAM","OIME","AXIL","WEST","TWAE","LIMB","WASE","WAST","BLEO","STUB","BOIL","BOLE","LIME","SAWT","LIMA","MESA","MEWL","AXLE","FAME","ASEM","MILE","AMIL","SEAX","SEAM","SEMI","SWAM","AMBO","AMLI","AXILE","AMBLE","SWAMI","AWEST","AWEST","LIMAX","LIMES","LIMBU","LIMBO","EMBOX","SEMBLE","EMBOLE","WAMBLE","FAMBLE"]
Code:
var fs = require('fs')
var Node = function(value, row, col) {
this.value = value
this.row = row
this.col = col
}
var Path = function() {
this.nodes = []
}
Path.prototype.push = function(node) {
this.nodes.push(node)
return this
}
Path.prototype.contains = function(node) {
for (var i = 0, ii = this.nodes.length; i < ii; i++) {
if (this.nodes[i] === node) {
return true
}
}
return false
}
Path.prototype.clone = function() {
var path = new Path()
path.nodes = this.nodes.slice(0)
return path
}
Path.prototype.to_word = function() {
var word = ''
for (var i = 0, ii = this.nodes.length; i < ii; ++i) {
word += this.nodes[i].value
}
return word
}
var Board = function(nodes, dict) {
// Erwartet ein n x m Array.
this.nodes = nodes
this.words = []
this.row_count = nodes.length
this.col_count = nodes[0].length
this.dict = dict
}
Board.from_raw = function(board, dict) {
var ROW_COUNT = board.length
, COL_COUNT = board[0].length
var nodes = []
// Ersetze das Brett durch Nodes
for (var i = 0, ii = ROW_COUNT; i < ii; ++i) {
nodes.push([])
for (var j = 0, jj = COL_COUNT; j < jj; ++j) {
nodes[i].push(new Node(board[i][j], i, j))
}
}
return new Board(nodes, dict)
}
Board.prototype.toString = function() {
return JSON.stringify(this.nodes)
}
Board.prototype.update_potential_words = function(dict) {
for (var i = 0, ii = this.row_count; i < ii; ++i) {
for (var j = 0, jj = this.col_count; j < jj; ++j) {
var node = this.nodes[i][j]
, path = new Path()
path.push(node)
this.dfs_search(path)
}
}
}
Board.prototype.on_board = function(row, col) {
return 0 <= row && row < this.row_count && 0 <= col && col < this.col_count
}
Board.prototype.get_unsearched_neighbours = function(path) {
var last_node = path.nodes[path.nodes.length - 1]
var offsets = [
[-1, -1], [-1, 0], [-1, +1]
, [ 0, -1], [ 0, +1]
, [+1, -1], [+1, 0], [+1, +1]
]
var neighbours = []
for (var i = 0, ii = offsets.length; i < ii; ++i) {
var offset = offsets[i]
if (this.on_board(last_node.row + offset[0], last_node.col + offset[1])) {
var potential_node = this.nodes[last_node.row + offset[0]][last_node.col + offset[1]]
if (!path.contains(potential_node)) {
// Erstelle einen neuen Pfad, wenn auf dem Brett und dieser Knoten noch nicht besucht wurde.
neighbours.push(potential_node)
}
}
}
return neighbours
}
Board.prototype.dfs_search = function(path) {
var path_word = path.to_word()
if (this.dict.contains_exact(path_word) && path_word.length >= 3) {
this.words.push(path_word)
}
var neighbours = this.get_unsearched_neighbours(path)
for (var i = 0, ii = neighbours.length; i < ii; ++i) {
var neighbour = neighbours[i]
var new_path = path.clone()
new_path.push(neighbour)
if (this.dict.contains_prefix(new_path.to_word())) {
this.dfs_search(new_path)
}
}
}
var Dict = function() {
this.dict_array = []
var dict_data = fs.readFileSync('./web2', 'utf8')
var dict_array = dict_data.split('\n')
for (var i = 0, ii = dict_array.length; i < ii; ++i) {
dict_array[i] = dict_array[i].toUpperCase()
}
this.dict_array = dict_array.sort()
}
Dict.prototype.contains_prefix = function(prefix) {
// Binäre Suche
return this.search_prefix(prefix, 0, this.dict_array.length)
}
Dict.prototype.contains_exact = function(exact) {
// Binäre Suche
return this.search_exact(exact, 0, this.dict_array.length)
}
Dict.prototype.search_prefix = function(prefix, start, end) {
if (start >= end) {
// Wenn kein weiterer Ort zum Suchen vorhanden ist, gibt es unabhängig davon zurück.
return this.dict_array[start].indexOf(prefix) > -1
}
var middle = Math.floor((start + end)/2)
if (this.dict_array[middle].indexOf(prefix) > -1) {
// Wenn unser Präfix existiert, geben wir true zurück.
return true
} else {
// Rekurs
if (prefix <= this.dict_array[middle]) {
return this.search_prefix(prefix, start, middle - 1)
} else {
return this.search_prefix(prefix, middle + 1, end)
}
}
}
Dict.prototype.search_exact = function(exact, start, end) {
if (start >= end) {
// Wenn kein weiterer Ort zum Suchen vorhanden ist, gibt es unabhängig davon zurück.
return this.dict_array[start] === exact
}
var middle = Math.floor((start + end)/2)
if (this.dict_array[middle] === exact) {
// Wenn unser Präfix existiert, geben wir true zurück.
return true
} else {
// Rekurs
if (exact <= this.dict_array[middle]) {
return this.search_exact(exact, start, middle - 1)
} else {
return this.search_exact(exact, middle + 1, end)
}
}
}
var board = [
['F', 'X', 'I', 'E']
, ['A', 'M', 'L', 'O']
, ['E', 'W', 'B', 'X']
, ['A', 'S', 'T', 'U']
]
var dict = new Dict()
var b = Board.from_raw(board, dict)
b.update_potential_words()
console.log(JSON.stringify(b.words.sort(function(a, b) {
return a.length - b.length
})))
1 Stimmen
Eine einfache Lösung ist die Klasse BoggleFinder aima.cs.berkeley.edu/python/search.html
0 Stimmen
Das macht doch keinen Spaß, oder? :)
18 Stimmen
Bitte übersetzen Sie dies beibehalten die gleichen HTML-Tags, wenn diese vorhanden sind von en nach de: Featureanfrage MEHR RÄTSEL
6 Stimmen
In Bezug auf die Zeitpunkte: In meiner Lösung wird praktisch die gesamte Zeit damit verbracht, den Trie aufzubauen. Sobald der Trie erstellt ist, kann er viele Male wiederverwendet werden. Wenn nur ein Rätsel gelöst wird, wäre es effizienter, eine einfachere Datenstruktur zu verwenden (wie eine Menge aller Wörter und aller Präfixe).
3 Stimmen
Auch Adam hat ein größeres Wörterbuch, wie durch die Anzahl der längeren Wörter in seiner Lösung belegt wird. Sie sollten alle basierend auf einem gemeinsamen Wörterbuch getestet werden.
0 Stimmen
@Reich: Ich führe sie alle auf meinem Computer mit meinem eigenen Wörterbuch aus.
2 Stimmen
Ich nehme an, dass niemand viel Boggle spielt? "Qu" ist ein "Buchstabe" und ich bin mir nicht sicher, wie viele der Lösungen dieses kleine Detail beachtet haben. Es sieht so aus, als ob einige von ihnen es ermöglichen würden, das "u" unabhängig zu verwenden, unter anderem Probleme.
2 Stimmen
Ich hatte kürzlich diese Frage bei einem Vorstellungsgespräch und bin nett in den Details steckengeblieben. Ich behandelte es als ein Graphenproblem, was in Ordnung ist, aber die Lösungen hier verwenden viel weniger Speicher. Ich code jetzt meine eigene Lösung. Gut gemacht an alle, die beigetragen haben!
0 Stimmen
Diese Frage scheint nicht zum Thema zu gehören, da es um Rätsellösungen geht. Es wäre passender auf codegolf.stackexchange.com
0 Stimmen
@Blazemonger Die Frage ist nach dem effizientesten Algorithmus zur Lösung eines Boggle gestellt, nicht nach dem kürzesten, und es handelt sich nicht um ein Rätsel im Codegolf-Stil. Soweit ich weiß, waren algorithmusbezogene Fragen fair für StackOverflow. Dies ist nicht off-topic, und ich denke, die Community hat ziemlich laut darüber gesprochen.
2 Stimmen
Sie sagen, dass Sie einen allgemeinen Algorithmus möchten, aber "Sie suchen hauptsächlich" nach konkretem Code in Python, PHP oder Perl. Sie haben keine eigene Arbeit geleistet, was heutzutage als wesentlich für SO-Fragen angesehen wird. Kommentare kennzeichnen dies eindeutig als "Rätsel" und nicht als eng definiertes Problem mit einer einzigen Lösung. Alles zusammen genommen könnte es als Codegolf geeignet sein, wie es geschrieben ist, aber wenn Sie diese Frage heute eingereicht hätten, würde sie sicherlich nicht als angemessen für SO angesehen. Meiner Meinung nach setzt es ein schlechtes Beispiel für Neulinge, was hier als "gute Frage" angesehen wird, wenn Sie sie offen lassen.
1 Stimmen
@Blazemonger 1. Die Bitte um bestimmte Sprachen ist für die Frage nach einem Algorithmus irrelevant. 2. Ich habe meine versuchte Lösung beschrieben und meine eigene gepostet. 3. Es ist definitiv eng und ausreichend definiert. 4. Es würde sicherlich offen bleiben, wenn es heute gepostet würde. 5. Wenn Neuankömmlinge Fragen stellen würden, die nur halb so gut sind wie diese, wären wir in guter Verfassung. Kurz gesagt, ich widerspreche respektvoll praktisch allem, was du gesagt hast.
0 Stimmen
@PaoloBergantino Tatsächlich sind offene Fragen, die zum analytischen Denken anregen, viel besser als die "Mach meinen Job, während ich Mittagessen gehe" Art von sogenannten Anfängerfragen, die heutzutage auf SO so verbreitet sind.
0 Stimmen
Ich erwarte, dass diese Frage gesperrt wird, da der Wert der Antworten darin liegt, aber ich stimme zu, dass sie nicht zum Thema gehört. Ich werde es erneut versuchen zu schließen. cc @Blazemonger.