Word search: Difference between revisions

Content added Content deleted
Line 2,269: Line 2,269:
dip (7,6)(9,8)
dip (7,6)(9,8)
</pre>
</pre>

=={{header|Visual Basic .NET}}==
{{trans|C#}}
<lang vbnet>Module Module1

ReadOnly Dirs As Integer(,) = {
{1, 0}, {0, 1}, {1, 1},
{1, -1}, {-1, 0},
{0, -1}, {-1, -1}, {-1, 1}
}

Const RowCount = 10
Const ColCount = 10
Const GridSize = RowCount * ColCount
Const MinWords = 25

Class Grid
Public cells(RowCount - 1, ColCount - 1) As Char
Public solutions As New List(Of String)
Public numAttempts As Integer

Sub New()
For i = 0 To RowCount - 1
For j = 0 To ColCount - 1
cells(i, j) = ControlChars.NullChar
Next
Next
End Sub
End Class

Dim Rand As New Random()

Sub Main()
PrintResult(CreateWordSearch(ReadWords("unixdict.txt")))
End Sub

Function ReadWords(filename As String) As List(Of String)
Dim maxlen = Math.Max(RowCount, ColCount)
Dim words As New List(Of String)

Dim objReader As New IO.StreamReader(filename)
Dim line As String
Do While objReader.Peek() <> -1
line = objReader.ReadLine()
If line.Length > 3 And line.Length < maxlen Then
If line.All(Function(c) Char.IsLetter(c)) Then
words.Add(line)
End If
End If
Loop

Return words
End Function

Function CreateWordSearch(words As List(Of String)) As Grid
For numAttempts = 1 To 1000
Shuffle(words)

Dim grid As New Grid()
Dim messageLen = PlaceMessage(grid, "Rosetta Code")
Dim target = GridSize - messageLen

Dim cellsFilled = 0
For Each word In words
cellsFilled = cellsFilled + TryPlaceWord(grid, word)
If cellsFilled = target Then
If grid.solutions.Count >= MinWords Then
grid.numAttempts = numAttempts
Return grid
Else
'grid is full but we didn't pack enough words, start over
Exit For
End If
End If
Next
Next

Return Nothing
End Function

Function PlaceMessage(grid As Grid, msg As String) As Integer
msg = msg.ToUpper()
msg = msg.Replace(" ", "")

If msg.Length > 0 And msg.Length < GridSize Then
Dim gapSize As Integer = GridSize / msg.Length

Dim pos = 0
Dim lastPos = -1
For i = 0 To msg.Length - 1
If i = 0 Then
pos = pos + Rand.Next(gapSize - 1)
Else
pos = pos + Rand.Next(2, gapSize - 1)
End If
Dim r As Integer = Math.Floor(pos / ColCount)
Dim c = pos Mod ColCount

grid.cells(r, c) = msg(i)

lastPos = pos
Next
Return msg.Length
End If

Return 0
End Function

Function TryPlaceWord(grid As Grid, word As String) As Integer
Dim randDir = Rand.Next(Dirs.GetLength(0))
Dim randPos = Rand.Next(GridSize)

For d = 0 To Dirs.GetLength(0) - 1
Dim dd = (d + randDir) Mod Dirs.GetLength(0)

For p = 0 To GridSize - 1
Dim pp = (p + randPos) Mod GridSize

Dim lettersPLaced = TryLocation(grid, word, dd, pp)
If lettersPLaced > 0 Then
Return lettersPLaced
End If
Next
Next

Return 0
End Function

Function TryLocation(grid As Grid, word As String, dir As Integer, pos As Integer) As Integer
Dim r As Integer = pos / ColCount
Dim c = pos Mod ColCount
Dim len = word.Length

'check bounds
If (Dirs(dir, 0) = 1 And len + c >= ColCount) Or (Dirs(dir, 0) = -1 And len - 1 > c) Or (Dirs(dir, 1) = 1 And len + r >= RowCount) Or (Dirs(dir, 1) = -1 And len - 1 > r) Then
Return 0
End If
If r = RowCount OrElse c = ColCount Then
Return 0
End If

Dim rr = r
Dim cc = c

'check cells
For i = 0 To len - 1
If grid.cells(rr, cc) <> ControlChars.NullChar AndAlso grid.cells(rr, cc) <> word(i) Then
Return 0
End If

cc = cc + Dirs(dir, 0)
rr = rr + Dirs(dir, 1)
Next

'place
Dim overlaps = 0
rr = r
cc = c
For i = 0 To len - 1
If grid.cells(rr, cc) = word(i) Then
overlaps = overlaps + 1
Else
grid.cells(rr, cc) = word(i)
End If

If i < len - 1 Then
cc = cc + Dirs(dir, 0)
rr = rr + Dirs(dir, 1)
End If
Next

Dim lettersPlaced = len - overlaps
If lettersPlaced > 0 Then
grid.solutions.Add(String.Format("{0,-10} ({1},{2})({3},{4})", word, c, r, cc, rr))
End If

Return lettersPlaced
End Function

Sub PrintResult(grid As Grid)
If IsNothing(grid) OrElse grid.numAttempts = 0 Then
Console.WriteLine("No grid to display")
Return
End If

Console.WriteLine("Attempts: {0}", grid.numAttempts)
Console.WriteLine("Number of words: {0}", GridSize)
Console.WriteLine()

Console.WriteLine(" 0 1 2 3 4 5 6 7 8 9")
For r = 0 To RowCount - 1
Console.WriteLine()
Console.Write("{0} ", r)
For c = 0 To ColCount - 1
Console.Write(" {0} ", grid.cells(r, c))
Next
Next

Console.WriteLine()
Console.WriteLine()

For i = 0 To grid.solutions.Count - 1
If i Mod 2 = 0 Then
Console.Write("{0}", grid.solutions(i))
Else
Console.WriteLine(" {0}", grid.solutions(i))
End If
Next

Console.WriteLine()
End Sub

'taken from https://stackoverflow.com/a/20449161
Sub Shuffle(Of T)(list As IList(Of T))
Dim r As Random = New Random()
For i = 0 To list.Count - 1
Dim index As Integer = r.Next(i, list.Count)
If i <> index Then
' swap list(i) and list(index)
Dim temp As T = list(i)
list(i) = list(index)
list(index) = temp
End If
Next
End Sub

End Module</lang>
{{out}}
<pre>Attempts: 148
Number of words: 100

0 1 2 3 4 5 6 7 8 9

0 c d p R e c h a r e
1 O i u b a k e S l v
2 k n l E m c a c a i
3 T e s i T x A s n t
4 t C e s a l O a g a
5 a j D l l e E h l g
6 l u f e m a h s e r
7 l t c a r f e r y u
8 f e r r e i r a m p
9 f a m i l i s m i s

refract (7,7)(1,7) shameful (7,6)(0,6)
ferreira (0,8)(7,8) familism (0,9)(7,9)
langley (8,1)(8,7) sake (7,3)(4,0)
pulse (2,0)(2,4) purgative (9,8)(9,0)
cacm (7,2)(4,2) enid (1,3)(1,0)
char (5,0)(8,0) flax (2,6)(5,3)
tall (0,4)(0,7) isle (3,3)(3,6)
jute (1,5)(1,8) myel (8,8)(8,5)
bake (3,1)(6,1) cell (2,7)(5,4)
marsh (7,9)(7,5) keel (0,2)(3,5)
spur (9,9)(9,6) leaf (5,4)(5,7)
cilia (0,0)(4,4) sims (9,9)(6,9)
marsha (7,9)(7,4)</pre>