Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
6
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Switch to GitLab Next
Sign in / Register
Toggle navigation
W
wordbase-hacker
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Iterations
Merge Requests
0
Merge Requests
0
Requirements
Requirements
List
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Test Cases
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Package Registry
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issue
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PurkkaKoodari
wordbase-hacker
Commits
d600d3d1
Commit
d600d3d1
authored
Sep 09, 2017
by
PurkkaKoodari
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Optimize finding words by 100x (whoops)
parent
70ab8395
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
98 additions
and
70 deletions
+98
-70
app/src/main/java/net/pietu1998/wordbasehacker/BoardActivity.java
...main/java/net/pietu1998/wordbasehacker/BoardActivity.java
+68
-47
app/src/main/java/net/pietu1998/wordbasehacker/BoardDrawable.java
...main/java/net/pietu1998/wordbasehacker/BoardDrawable.java
+11
-11
app/src/main/java/net/pietu1998/wordbasehacker/solver/Board.java
.../main/java/net/pietu1998/wordbasehacker/solver/Board.java
+4
-3
app/src/main/java/net/pietu1998/wordbasehacker/solver/Coordinate.java
.../java/net/pietu1998/wordbasehacker/solver/Coordinate.java
+3
-3
app/src/main/java/net/pietu1998/wordbasehacker/solver/Possibility.java
...java/net/pietu1998/wordbasehacker/solver/Possibility.java
+12
-5
app/src/main/java/net/pietu1998/wordbasehacker/solver/Tile.java
...c/main/java/net/pietu1998/wordbasehacker/solver/Tile.java
+0
-1
No files found.
app/src/main/java/net/pietu1998/wordbasehacker/BoardActivity.java
View file @
d600d3d1
...
...
@@ -10,7 +10,6 @@ import java.util.Arrays;
import
java.util.List
;
import
net.pietu1998.wordbasehacker.solver.Board
;
import
net.pietu1998.wordbasehacker.solver.Coordinate
;
import
net.pietu1998.wordbasehacker.solver.Game
;
import
net.pietu1998.wordbasehacker.solver.Move
;
import
net.pietu1998.wordbasehacker.solver.Possibility
;
...
...
@@ -100,6 +99,12 @@ public class BoardActivity extends Activity {
this
.
dialog
=
dialog
;
}
private
class
TrieNode
{
private
TrieNode
[]
nodes
=
new
TrieNode
[
1024
];
private
boolean
hasChildren
=
false
;
private
String
content
=
null
;
}
@Override
protected
Integer
doInBackground
(
Void
...
params
)
{
try
{
...
...
@@ -152,10 +157,20 @@ public class BoardActivity extends Activity {
layout
[
Integer
.
parseInt
((
String
)
tile
.
get
(
1
))][
Integer
.
parseInt
((
String
)
tile
.
get
(
2
))]
=
flags
;
}
}
short
charMap
[]
=
new
short
[
65536
];
short
charIndex
=
0
;
Tile
[][]
tiles
=
new
Tile
[
10
][
13
];
short
[]
tileMap
=
new
short
[
130
];
for
(
int
x
=
0
;
x
<
10
;
x
++)
{
for
(
int
y
=
0
;
y
<
13
;
y
++)
{
tiles
[
x
][
y
]
=
new
Tile
(
layout
[
x
][
y
],
rows
[
y
].
charAt
(
x
));
char
letter
=
rows
[
y
].
charAt
(
x
);
int
mapping
=
charMap
[
letter
];
if
(
mapping
==
0
)
mapping
=
charMap
[
letter
]
=
(
short
)
++
charIndex
;
tiles
[
x
][
y
]
=
new
Tile
(
layout
[
x
][
y
],
letter
);
tileMap
[
x
+
10
*
y
]
=
(
short
)
(
mapping
-
1
);
}
}
game
.
setBoard
(
new
Board
(
tiles
,
words
));
...
...
@@ -163,36 +178,40 @@ public class BoardActivity extends Activity {
publishProgress
(
R
.
string
.
analyzing_words
);
words
=
game
.
getBoard
().
getWords
();
int
longest
=
0
;
for
(
int
i
=
0
;
i
<
words
.
length
;
i
++)
{
if
(
words
[
i
].
length
()
>
longest
)
longest
=
words
[
i
].
length
();
}
List
<
List
<
String
>>
byLength
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
longest
;
i
++)
byLength
.
add
(
new
ArrayList
<
String
>());
for
(
int
i
=
0
;
i
<
words
.
length
;
i
++)
{
for
(
int
j
=
0
;
j
<
words
[
i
].
length
();
j
++)
byLength
.
get
(
j
).
add
(
words
[
i
]);
}
String
[][]
wordsByLength
=
new
String
[
longest
][];
for
(
int
i
=
0
;
i
<
longest
;
i
++)
{
wordsByLength
[
i
]
=
byLength
.
get
(
i
).
toArray
(
new
String
[
0
]);
Arrays
.
sort
(
wordsByLength
[
i
]);
TrieNode
root
=
new
TrieNode
();
for
(
String
word
:
words
)
{
if
(
game
.
isPlayed
(
word
))
continue
;
if
(
word
.
length
()
>
longest
)
longest
=
word
.
length
();
TrieNode
node
=
root
;
for
(
int
i
=
0
;
i
<
word
.
length
();
i
++)
{
int
mapping
=
charMap
[
word
.
charAt
(
i
)]
-
1
;
node
.
hasChildren
=
true
;
TrieNode
next
=
node
.
nodes
[
mapping
];
if
(
next
==
null
)
node
=
node
.
nodes
[
mapping
]
=
new
TrieNode
();
else
node
=
next
;
}
node
.
content
=
word
;
}
publishProgress
(
R
.
string
.
finding_words
);
results
=
new
ArrayList
<>();
long
start
=
System
.
currentTimeMillis
();
for
(
int
iteration
=
0
;
iteration
<
20
;
iteration
++)
{
for
(
int
iteration
=
0
;
iteration
<
100
;
iteration
++)
{
boolean
positions
[]
=
new
boolean
[
130
];
byte
coords
[]
=
new
byte
[
2
*
longest
];
short
letters
[]
=
new
short
[
longest
];
for
(
int
x
=
0
;
x
<
10
;
x
++)
{
for
(
int
y
=
0
;
y
<
13
;
y
++)
{
if
(
game
.
getBoard
().
getTiles
()[
x
][
y
].
isSet
(
Tile
.
PLAYER
))
{
findWords
(
game
,
0
,
longest
,
x
,
y
,
new
ArrayList
<
Coordinate
>(),
new
char
[
longest
],
results
,
wordsByLength
);
findWords
(
tileMap
,
0
,
longest
,
x
,
y
,
coords
,
positions
,
letters
,
root
);
}
}
}
if
(
iteration
<
1
9
)
results
.
clear
();
if
(
iteration
<
9
9
)
results
.
clear
();
}
long
end
=
System
.
currentTimeMillis
();
Log
.
d
(
"WordbaseHacker"
,
"Finding took "
+
(
end
-
start
)
+
"ms"
);
...
...
@@ -220,28 +239,31 @@ public class BoardActivity extends Activity {
}
}
private
void
findWords
(
Game
game
,
int
length
,
int
max
,
int
x
,
int
y
,
List
<
Coordinate
>
coords
,
char
[]
letters
,
List
<
Possibility
>
results
,
String
[][]
wordsByLength
)
{
if
(
length
>=
max
||
x
<
0
||
x
>
9
||
y
<
0
||
y
>
12
||
coords
.
contains
(
new
Coordinate
(
x
,
y
)))
private
void
findWords
(
short
[]
tiles
,
int
length
,
int
max
,
int
x
,
int
y
,
byte
[]
coords
,
boolean
[]
positions
,
short
[]
letters
,
TrieNode
node
)
{
int
index
=
y
*
10
+
x
;
if
(
length
>=
max
||
x
<
0
||
x
>
9
||
y
<
0
||
y
>
12
||
positions
[
index
])
return
;
List
<
Coordinate
>
withCoords
=
new
ArrayList
<>(
coords
);
withCoords
.
add
(
new
Coordinate
(
x
,
y
));
char
[]
withLetter
=
Arrays
.
copyOf
(
letters
,
max
);
withLetter
[
length
]
=
game
.
getBoard
().
getTiles
()[
x
][
y
].
getLetter
();
String
word
=
new
String
(
withLetter
,
0
,
length
+
1
);
int
pos
=
findPos
(
wordsByLength
[
length
],
word
);
if
(
pos
>=
wordsByLength
[
length
].
length
||
!
wordsByLength
[
length
][
pos
].
startsWith
(
word
))
short
letter
=
tiles
[
index
];
node
=
node
.
nodes
[
letter
];
if
(
node
==
null
)
return
;
if
(
Arrays
.
asList
(
wordsByLength
[
length
]).
contains
(
word
)
&&
!
game
.
isPlayed
(
word
))
results
.
add
(
new
Possibility
(
withCoords
.
toArray
(
new
Coordinate
[
0
]),
Arrays
.
copyOf
(
withLetter
,
length
+
1
)));
findWords
(
game
,
length
+
1
,
max
,
x
,
y
+
1
,
withCoords
,
withLetter
,
results
,
wordsByLength
);
findWords
(
game
,
length
+
1
,
max
,
x
-
1
,
y
+
1
,
withCoords
,
withLetter
,
results
,
wordsByLength
);
findWords
(
game
,
length
+
1
,
max
,
x
+
1
,
y
+
1
,
withCoords
,
withLetter
,
results
,
wordsByLength
);
findWords
(
game
,
length
+
1
,
max
,
x
-
1
,
y
,
withCoords
,
withLetter
,
results
,
wordsByLength
);
findWords
(
game
,
length
+
1
,
max
,
x
+
1
,
y
,
withCoords
,
withLetter
,
results
,
wordsByLength
);
findWords
(
game
,
length
+
1
,
max
,
x
,
y
-
1
,
withCoords
,
withLetter
,
results
,
wordsByLength
);
findWords
(
game
,
length
+
1
,
max
,
x
-
1
,
y
-
1
,
withCoords
,
withLetter
,
results
,
wordsByLength
);
findWords
(
game
,
length
+
1
,
max
,
x
+
1
,
y
-
1
,
withCoords
,
withLetter
,
results
,
wordsByLength
);
coords
[
length
*
2
]
=
(
byte
)
x
;
coords
[
length
*
2
+
1
]
=
(
byte
)
y
;
letters
[
length
]
=
letter
;
if
(
node
.
content
!=
null
)
results
.
add
(
new
Possibility
(
Arrays
.
copyOf
(
coords
,
length
*
2
+
2
),
node
.
content
));
if
(!
node
.
hasChildren
)
return
;
positions
[
index
]
=
true
;
findWords
(
tiles
,
length
+
1
,
max
,
x
,
y
+
1
,
coords
,
positions
,
letters
,
node
);
findWords
(
tiles
,
length
+
1
,
max
,
x
-
1
,
y
+
1
,
coords
,
positions
,
letters
,
node
);
findWords
(
tiles
,
length
+
1
,
max
,
x
+
1
,
y
+
1
,
coords
,
positions
,
letters
,
node
);
findWords
(
tiles
,
length
+
1
,
max
,
x
-
1
,
y
,
coords
,
positions
,
letters
,
node
);
findWords
(
tiles
,
length
+
1
,
max
,
x
+
1
,
y
,
coords
,
positions
,
letters
,
node
);
findWords
(
tiles
,
length
+
1
,
max
,
x
,
y
-
1
,
coords
,
positions
,
letters
,
node
);
findWords
(
tiles
,
length
+
1
,
max
,
x
-
1
,
y
-
1
,
coords
,
positions
,
letters
,
node
);
findWords
(
tiles
,
length
+
1
,
max
,
x
+
1
,
y
-
1
,
coords
,
positions
,
letters
,
node
);
positions
[
index
]
=
false
;
}
private
int
findPos
(
String
[]
items
,
String
item
)
{
...
...
@@ -286,10 +308,6 @@ public class BoardActivity extends Activity {
}
private
void
updateView
()
{
if
(
possibilities
.
size
()
==
0
)
{
((
TextView
)
findViewById
(
R
.
id
.
status
)).
setText
(
R
.
string
.
no_moves
);
return
;
}
int
max
=
Integer
.
MIN_VALUE
;
Possibility
best
=
null
;
for
(
Possibility
pos
:
possibilities
)
{
...
...
@@ -299,9 +317,12 @@ public class BoardActivity extends Activity {
best
=
pos
;
}
}
if
(
best
==
null
)
{
((
TextView
)
findViewById
(
R
.
id
.
status
)).
setText
(
R
.
string
.
no_moves
);
return
;
}
((
ImageView
)
findViewById
(
R
.
id
.
movePicture
)).
setImageDrawable
(
new
BoardDrawable
(
best
,
game
.
isFlipped
()));
((
TextView
)
findViewById
(
R
.
id
.
status
)).
setText
(
getResources
().
getString
(
R
.
string
.
best_move
,
new
String
(
best
.
getWord
()),
max
));
((
TextView
)
findViewById
(
R
.
id
.
status
)).
setText
(
getResources
().
getString
(
R
.
string
.
best_move
,
best
.
getWord
(),
max
));
}
private
void
loadScoring
()
{
...
...
app/src/main/java/net/pietu1998/wordbasehacker/BoardDrawable.java
View file @
d600d3d1
...
...
@@ -81,20 +81,20 @@ public class BoardDrawable extends Drawable {
t
.
isSet
(
Tile
.
MINE
|
Tile
.
SUPER_MINE
)
?
whiteText
:
blackText
);
}
}
if
(
pos
.
getCoordinates
().
length
>
1
)
{
Coordina
te
[]
c
=
pos
.
getCoordinates
();
canvas
.
drawCircle
(
80
*
c
[
0
]
.
x
+
40
,
80
*
c
[
0
].
y
+
40
,
32
,
path
);
if
(
c
[
0
]
.
x
!=
c
[
1
].
x
&&
c
[
0
].
y
!=
c
[
1
].
y
)
canvas
.
drawLine
(
c
[
0
]
.
x
*
80
+
(
c
[
1
].
x
-
c
[
0
].
x
)
*
SQRT512
+
40
,
c
[
0
].
y
*
80
+
(
c
[
1
].
y
-
c
[
0
].
y
)
*
SQRT512
+
40
,
c
[
1
].
x
*
80
+
40
,
c
[
1
].
y
*
80
+
40
,
path
);
else
if
(
c
[
0
]
.
x
==
c
[
1
].
x
)
canvas
.
drawLine
(
80
*
c
[
0
]
.
x
+
40
,
48
*
c
[
0
].
y
+
32
*
c
[
1
].
y
+
40
,
80
*
c
[
1
].
x
+
40
,
80
*
c
[
1
].
y
+
40
,
if
(
pos
.
getCoordinates
().
length
>
2
)
{
by
te
[]
c
=
pos
.
getCoordinates
();
canvas
.
drawCircle
(
80
*
c
[
0
]
+
40
,
80
*
c
[
1
]
+
40
,
32
,
path
);
if
(
c
[
0
]
!=
c
[
2
]
&&
c
[
1
]
!=
c
[
3
]
)
canvas
.
drawLine
(
c
[
0
]
*
80
+
(
c
[
2
]
-
c
[
0
])
*
SQRT512
+
40
,
c
[
1
]
*
80
+
(
c
[
3
]
-
c
[
1
]
)
*
SQRT512
+
40
,
c
[
2
]
*
80
+
40
,
c
[
3
]
*
80
+
40
,
path
);
else
if
(
c
[
0
]
==
c
[
2
]
)
canvas
.
drawLine
(
80
*
c
[
0
]
+
40
,
48
*
c
[
1
]
+
32
*
c
[
3
]
+
40
,
80
*
c
[
2
]
+
40
,
80
*
c
[
3
]
+
40
,
path
);
else
canvas
.
drawLine
(
48
*
c
[
0
]
.
x
+
32
*
c
[
1
].
x
+
40
,
80
*
c
[
0
].
y
+
40
,
80
*
c
[
1
].
x
+
40
,
80
*
c
[
1
].
y
+
40
,
canvas
.
drawLine
(
48
*
c
[
0
]
+
32
*
c
[
2
]
+
40
,
80
*
c
[
1
]
+
40
,
80
*
c
[
2
]
+
40
,
80
*
c
[
3
]
+
40
,
path
);
for
(
int
i
=
1
;
i
<
c
.
length
-
1
;
i
++
)
{
canvas
.
drawLine
(
80
*
c
[
i
]
.
x
+
40
,
80
*
c
[
i
].
y
+
40
,
80
*
c
[
i
+
1
].
x
+
40
,
80
*
c
[
i
+
1
].
y
+
40
,
path
);
for
(
int
i
=
2
;
i
<
c
.
length
-
2
;
i
+=
2
)
{
canvas
.
drawLine
(
80
*
c
[
i
]
+
40
,
80
*
c
[
i
+
1
]
+
40
,
80
*
c
[
i
+
2
]
+
40
,
80
*
c
[
i
+
3
]
+
40
,
path
);
}
}
}
...
...
app/src/main/java/net/pietu1998/wordbasehacker/solver/Board.java
View file @
d600d3d1
...
...
@@ -39,8 +39,9 @@ public class Board {
}
}
for
(
int
i
=
0
;
i
<
pos
.
getCoordinates
().
length
;
i
++)
takeTile
(
newTiles
,
pos
.
getCoordinates
()[
i
].
x
,
pos
.
getCoordinates
()[
i
].
y
);
byte
[]
coords
=
pos
.
getCoordinates
();
for
(
int
i
=
0
;
i
<
coords
.
length
;
i
+=
2
)
takeTile
(
newTiles
,
coords
[
i
],
coords
[
i
+
1
]);
Set
<
Coordinate
>
connected
=
new
HashSet
<
Coordinate
>();
for
(
int
x
=
0
;
x
<
10
;
x
++)
{
...
...
@@ -67,7 +68,7 @@ public class Board {
}
}
}
pos
.
setScore
(
new
Score
(
pos
.
getCoordinates
().
length
,
oldMines
-
newMines
,
newPlayer
-
oldPlayer
,
oldOpponent
pos
.
setScore
(
new
Score
(
pos
.
getCoordinates
().
length
/
2
,
oldMines
-
newMines
,
newPlayer
-
oldPlayer
,
oldOpponent
-
newOpponent
,
newDistP
-
oldDistP
,
oldDistO
-
newDistO
,
newDistP
==
12
));
pos
.
setResult
(
new
Board
(
newTiles
,
words
));
}
...
...
app/src/main/java/net/pietu1998/wordbasehacker/solver/Coordinate.java
View file @
d600d3d1
...
...
@@ -3,17 +3,17 @@ package net.pietu1998.wordbasehacker.solver;
public
class
Coordinate
{
public
final
int
x
,
y
;
private
final
int
hash
;
private
final
int
index
;
public
Coordinate
(
int
x
,
int
y
)
{
this
.
x
=
x
;
this
.
y
=
y
;
this
.
hash
=
(
x
<<
8
)
|
y
;
this
.
index
=
y
+
10
*
x
;
}
@Override
public
int
hashCode
()
{
return
hash
;
return
index
;
}
@Override
...
...
app/src/main/java/net/pietu1998/wordbasehacker/solver/Possibility.java
View file @
d600d3d1
package
net.pietu1998.wordbasehacker.solver
;
import
android.support.annotation.NonNull
;
public
class
Possibility
{
private
Coordinate
[]
coordinates
;
@NonNull
private
byte
[]
coordinates
;
@NonNull
private
String
word
;
private
Score
score
;
private
Board
result
;
private
char
[]
word
;
public
Possibility
(
Coordinate
[]
coordinates
,
char
[]
word
)
{
public
Possibility
(
@NonNull
byte
[]
coordinates
,
@NonNull
String
word
)
{
this
.
coordinates
=
coordinates
;
this
.
word
=
word
;
}
...
...
@@ -20,6 +24,7 @@ public class Possibility {
this
.
score
=
score
;
}
@NonNull
public
Board
getResult
()
{
return
result
;
}
...
...
@@ -28,11 +33,13 @@ public class Possibility {
this
.
result
=
result
;
}
public
Coordinate
[]
getCoordinates
()
{
@NonNull
public
byte
[]
getCoordinates
()
{
return
coordinates
;
}
public
char
[]
getWord
()
{
@NonNull
public
String
getWord
()
{
return
word
;
}
...
...
app/src/main/java/net/pietu1998/wordbasehacker/solver/Tile.java
View file @
d600d3d1
...
...
@@ -19,7 +19,6 @@ public class Tile {
public
int
getFlags
()
{
return
flags
;
}
public
char
getLetter
()
{
return
letter
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment