Solved

# Word Generator

Posted on 2005-03-14
Medium Priority
293 Views
Preparing some tests to be delivered as "training" (who knows what will they come out with next..)

Need a snippet that will give me combinations of characters (0-9, a-z) given a particular constraint (ex: How many pairs of 2 characters can be combined into a 4-character word?)

Now, my starting point is probably the most troubling part: creating a DB of all character combinations upto 5 characters.. Once I built the DB, I'll easily surf through with SQL or some extra code..

How can I get that done?
Example of output:
0
1
2
...
9
a
b
c
...
00
01
02
...
0a
0b
0c
...
zzzzz

Thanks!

:-)

0
Question by:andreba
• 12
• 9
• 7
• +1

LVL 3

Expert Comment

ID: 13533509
store 0 to z

for i='0' to 'z'
store "value in i" & "one digit previous elements in the database"
next i

for i='0' to 'z'
store "value in i" & "two digit previous elements in the database"
next i

for i='0' to 'z'
store "value in i" & "three digit previous elements in the database"
next i

for i='0' to 'z'
store "value in i" & "four digit previous elements in the database"
next i

-----------------------------------------------------

this is a first level of algo...

u can also make this simple by making one more loop
0

LVL 3

Expert Comment

ID: 13533539
this may be the rough algo....

for j=0 to 4

for i='0' to 'z'
store "value in i" & "j digit previous elements in the database"
next i
next j

0

LVL 3

Assisted Solution

r_a_j_e_s_h earned 400 total points
ID: 13533605
this is a sample code for the first level of algo.....

#include <stdio.h>
#include <string.h>

char *text="0123456789abcdefghijklmnopqrstuvwxyz";
void print1(char *pre)
{
int i;
for (i=0;i<36;i++) {
printf("\n%s%c",pre,text[i]);
}
}

void print2(char *pre)
{
int i,len;
char tempst[5];

for (i=0;i<36;i++) {
strcpy(tempst,pre);
len=strlen(tempst);
tempst[len]=text[i];
tempst[len+1]='\0';
print1(tempst);
}
}

void print3(char *pre)
{
int i,len;
char tempst[5];

for (i=0;i<36;i++) {
strcpy(tempst,pre);
len=strlen(tempst);
tempst[len]=text[i];
tempst[len+1]='\0';
print2(tempst);
}
}

void print4(char *pre)
{
int i,len;
char tempst[5];

for (i=0;i<36;i++) {
strcpy(tempst,pre);
len=strlen(tempst);
tempst[len]=text[i];
tempst[len+1]='\0';
print3(tempst);
}
}

void print5(char *pre)
{
int i,len;
char tempst[5];

for (i=0;i<36;i++) {
strcpy(tempst,pre);
len=strlen(tempst);
tempst[len]=text[i];
tempst[len+1]='\0';
print4(tempst);
}
}

void main()
{
int i;
char tempst[5];
print1("");
print2("");
print3("");
print4("");
print5("");
}
0

LVL 3

Expert Comment

ID: 13533690
that code is a rough one... there are some memory leaks in that.... i think u can solve that.... if u want me to solve , leave a message back....

regards

Rajesh
0

LVL 7

Author Comment

ID: 13533752
Thanks Raj, anything in VB.NET?

:-)
0

LVL 7

Author Comment

ID: 13533756
lol..
I mean.. Would those two initial snippets do the trick?

:-)
0

LVL 3

Expert Comment

ID: 13533767
u can simply convert this in to vb.net code...

i hope there won't be much problem in converting
0

LVL 3

Expert Comment

ID: 13533774
have u run the c code?....

convert that to vb.net ... then u will go smooth afterwards

there won't be a problem

0

LVL 7

Author Comment

ID: 13533953
how to convert? I'm not familiar with C++..

:-)
0

LVL 12

Expert Comment

ID: 13533979
Well here's a different way to generate a set of codes:

Public Class CodeGenerator
Public CharacterSet As String = "abcd"   ' Test using this one so you can see... then make it bigger when needed

Sub Generate(ByVal Length As Integer, Optional ByVal PrecedingCode As String = "")
Dim currentChar As Char
Dim currentCode As String

For Each currentChar In CharacterSet.ToCharArray
currentCode = PrecedingCode & currentChar
RaiseEvent CodeCreated(currentCode)
If Length > 1 Then Generate(Length - 1, currentCode)
Next
End Sub

Public Event CodeCreated(ByVal CodeWord As String)
End Class

====================

then create a form and put a button on it to test:

Dim WithEvents CodeMaker As New CodeGenerator()

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
CodeMaker.Generate(3)
End Sub

Public Sub CodeMade(ByVal NewCode As String) Handles CodeMaker.CodeCreated
MsgBox(NewCode)
End Sub

========================

The order it generates them might not be as nice... but it's quick n easy... anyway, I'm gonna be out of a few hours so can't answer about it... good luck
0

LVL 3

Expert Comment

ID: 13534063
ya S-Twilley  is correct... he implemented in vb.net....his code is following the second snippet i posted....

regards
Rajesh
0

LVL 7

Author Comment

ID: 13534142
hey raj, can you rearrange S-Twilley's code to sort them in the order I posted originally? Will it go through all the permutations as intended?

I'll only be able to test tomorrow..

Thanks all!

:-)
0

LVL 1

Assisted Solution

hagipmc earned 120 total points
ID: 13536096
Public Class Form1
Inherits System.Windows.Forms.Form

Private str As String = "a,b,c,d,e" '"0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"
Private arr() As String = str.Split(",")

Dim a() As Integer
Dim max As Integer
Dim m As Integer

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents txtResult As System.Windows.Forms.TextBox
Friend WithEvents btnClick As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.btnClick = New System.Windows.Forms.Button
Me.txtResult = New System.Windows.Forms.TextBox
Me.SuspendLayout()
'
'btnClick
'
Me.btnClick.Location = New System.Drawing.Point(208, 408)
Me.btnClick.Name = "btnClick"
Me.btnClick.Size = New System.Drawing.Size(80, 24)
Me.btnClick.TabIndex = 0
Me.btnClick.Text = "Click"
'
'txtResult
'
Me.txtResult.Location = New System.Drawing.Point(8, 8)
Me.txtResult.Multiline = True
Me.txtResult.Name = "txtResult"
Me.txtResult.Size = New System.Drawing.Size(192, 424)
Me.txtResult.TabIndex = 3
Me.txtResult.Text = ""
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 437)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub btnAranj_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClick.Click
Try
max = arr.Length
For i As Integer = 1 To 5 'or more(e.g arr.Length)
m = i
ReDim a(m)
GenerateComb(1)
Next

Catch ex As Exception
MessageBox.Show(ex.Message & ex.StackTrace)
End Try
End Sub

'recursive function
Private Sub GenerateComb(ByVal n As Integer)
Dim i, j As Integer
Dim bool As Boolean
Try
For i = 1 To max
a(n) = i
bool = False
For j = 1 To n - 1
If a(j) > i Then bool = True 'use a(j) = i if you dont want the letters to repeat
Next
If Not bool Then
If n = m Then
For j = 1 To m
Me.txtResult.Text &= arr(a(j) - 1)
Next
Me.txtResult.Text &= vbCrLf
Else
Me.GenerateComb(n + 1)
End If
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message & ex.StackTrace)
End Try
End Sub

End Class
0

LVL 12

Accepted Solution

S-Twilley earned 1480 total points
ID: 13537558
Ok, im back, here's the code generator in a better order.... the code has changed... and i know it seems longer but it does prevent lots of nested methods.

==================================

Public Class SimpleCodeGenerator
Private _charSet As String = ""

Public Property CharacterSet() As String
Get
Return _charSet
End Get
Set(ByVal Value As String)
_charSet = Value
End Set
End Property

Public Sub Generate(ByVal Length As String)
Dim CharPos(Length) As Integer
Dim currentPos As Integer

For currentPos = 0 To Length - 1
CharPos(currentPos) = -1
Next

Dim Forever As Boolean = True

While Forever
Dim currString As String = ""

For currentPos = 0 To Length - 1
If CharPos(currentPos) >= 0 Then
currString &= _charSet.Substring(CharPos(currentPos), 1)
End If
Next

RaiseEvent CodeGenerated(currString)

Dim carryInt As Integer = 1

For currentPos = Length - 1 To 0 Step -1
If carryInt = 0 Then Exit For
CharPos(currentPos) += 1
If CharPos(currentPos) > _charSet.Length - 1 Then
CharPos(currentPos) = 0
carryInt = 1
If currentPos = 0 Then Exit For
Else
carryInt = 0
End If
Next

End While
End Sub

Public Event CodeGenerated(ByVal CodeString As String)
End Class

===================

Make a new form with a button

------------

Dim WithEvents x As New SimpleCodeGenerator()

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
x.CharacterSet = "ABC"      ' characters at for each "point"
x.Generate(4)                    ' max length of codes
End Sub

Private Sub CodeCaught(ByVal NewCode As String) Handles x.CodeGenerated
MsgBox(NewCode)
End Sub

====================

Hope that's better for you
0

LVL 7

Author Comment

ID: 13540888
Brilliant, as usual..

Thanks so much!

:-)
0

LVL 7

Author Comment

ID: 13541410
One thing though S-Twilley. If I use

Private Sub CodeCaught(ByVal NewCode As String) Handles x.CodeGenerated
lbl1.text=NewCode
End Sub

It NEVER gets displayed! Only if I add the "MsgBox(NewCode)" line..

Why and how to sort that out?

Thanks!

:-)
0

LVL 12

Expert Comment

ID: 13542276
Doing it that way will only display the last item... and also remember that the code generator is running in the same threat so the form is locked till it is complete (that can be fixed).

As for another reason ... this event is raised for EVERY code that is made, it's not just one event for all.  Just by using lbl1.text =NewCode, you are setting it to a newcode, but as soon as the event is fired again, it is overwritten.

If you want to display all the codes... you could use a listbox, or a multiline textbox... but just be careful when generating large lists of codes!

0

LVL 7

Author Comment

ID: 13542309
How can it be fixed? I need to ensure that, after each code, I can DO something with the code, before I move on to the next one..

:-)
0

LVL 12

Expert Comment

ID: 13542624
The idea of that event is so you can use each code as you see fit... while you're within that method (CodeCaught)... the program won't be moving on until you exit the sub ... so within this sub/method... you could append it to a list... or put it into a database or something...

... the code generator can be modified to generate ONLY ONE code at a time... but I figure as the number of codes increase... doing one code at a time and pausing for user input would take a while.

What exactly do you want to do with each code before moving onto the next?
0

LVL 7

Author Comment

ID: 13542658
It would be great if I could 'see' what code is currently being generated (by having it on a label or something) so that I can roughly estimate how much is left to be done..

As it is, I can actually use it already.. Now I just want to be able to 'monitor'.. User input is not necessary, as you correctly stated..

I'm guessing it has to do with the form locking, which you said can be fixed..

Thanks again!

:-)
0

LVL 12

Expert Comment

ID: 13542682
If you give me a moment to work out the math... I'll edit the code generator class so it runs in its own thread and also passes an extra value to the event handler giving a percent done.
0

LVL 7

Author Comment

ID: 13542697
You're the sweetest!

Is it out of place to ask for a way to 'break' the process of code generation halfway?

I'll open another question if needed..

I wished I could do this in VB6.. I found it so much easier than .net..

Thanks!

:-)
0

LVL 12

Expert Comment

ID: 13542705
You want to be able to force the code generator to stop mid-process?  If that's the case it's very easy to do (and no need for a seperate post).... only question about doing that is would you just restart the code generation from the beginning the next time around... or would expect it to resume?
0

LVL 7

Author Comment

ID: 13542733
From beginning should do.. At least at this stage.. Not sure actually, I haven't looked too far ahead on HOW MUCH will they use this 'training' and whether it will grow or it's a one time thing and then archive..

lol, I was panicking for not being able of putting it together, and now I HAVE TOO MANY OPTIONS! This is great!

:-)
0

LVL 12

Expert Comment

ID: 13543272
I've put in code to pause and resume ... although I've not tested that part:

==================================================

Public Class SimpleCodeGenerator
Private _charSet As String = ""
Private _codeLength As Integer = 0
Private _inProcess As Boolean = False
Private _pauseFlag As Boolean = False
Private _currentCodeNumber As Integer = 0

Private _charPos() As Integer
Private _currentPos, _currentPos2, _carryPos As Integer

Get
Return _codeLength
End Get
End Property
Get
Return _charSet
End Get
End Property
Get
Return _inProcess
End Get
End Property

Public Sub Start(ByVal NewCharacterSet As String, ByVal NewCodeLength As Integer, Optional ByVal ForceRestart As Boolean = False)
If _inProcess And Not ForceRestart Then
RaiseEvent Error_InProcess(Me)
Exit Sub
End If

_pauseFlag = True

If Not _thisThread Is Nothing Then
Try
Catch
End Try
End If

_currentCodeNumber = 1
_charSet = NewCharacterSet
_codeLength = NewCodeLength
_pauseFlag = False
ReDim _charPos(_codeLength)

For _currentPos = 0 To _codeLength - 1
_charPos(_currentPos) = -1
Next

End Sub

Private Sub Generate()
_inProcess = True

Dim Forever As Boolean = True

While Forever
If _pauseFlag Then Exit Sub

Dim currString As String = ""

For _currentPos2 = 0 To _codeLength - 1
If _charPos(_currentPos2) >= 0 Then
currString &= _charSet.Substring(_charPos(_currentPos2), 1)
End If
Next

RaiseEvent CodeGenerated(Me, currString, _currentCodeNumber)
_currentCodeNumber += 1

Dim carryInt As Integer = 1

For _carryPos = _codeLength - 1 To 0 Step -1
If carryInt = 0 Then Exit For
_charPos(_carryPos) += 1

If _charPos(_carryPos) > _charSet.Length - 1 Then
_charPos(_carryPos) = 0
carryInt = 1
If _carryPos = 0 Then Exit While
Else
carryInt = 0
End If
Next
End While

_inProcess = False
End Sub

Public Sub Quit()
If Not _thisThread Is Nothing Then
Try
Catch
End Try
End If
_inProcess = False
_pauseFlag = False
End Sub
Public Sub Pause()
If _inProcess Then
_pauseFlag = True
End If
End Sub
Public Sub Continue()
If _inProcess Then
_pauseFlag = False

If Not _thisThread Is Nothing Then
Try
Catch
End Try
End If

End If
End Sub

Public Function GetComplexity()
Dim prevTotal As Integer = 1
Dim currTotal As Integer
Dim grandTotal As Integer = 1

Dim currentLevel As Integer

For currentLevel = 1 To _codeLength
currTotal = _charSet.Length * prevTotal
grandTotal += currTotal
prevTotal = currTotal
Next

Return grandTotal
End Function

Public Event CodeGenerated(ByVal Sender As Object, ByVal CodeString As String, ByVal CodeNumber As Integer)
Public Event Error_InProcess(ByVal Sender As Object)
End Class

================================

Dim WithEvents x As New SimpleCodeGenerator()

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
x.Start("ABCD", 3)
End Sub

Private Sub CodeCaught(ByVal sender As Object, ByVal newcode As String, ByVal codenumber As Integer) Handles x.CodeGenerated
Dim percent As Single
Dim thisGenerator As SimpleCodeGenerator = sender

percent = 100 * codenumber / thisGenerator.GetComplexity
MsgBox("New Code:    '" & newcode & "'" & vbCrLf & _
"Code Number: " & codenumber & vbCrLf & _
"Total Codes: " & thisGenerator.GetComplexity & vbCrLf & _
"Percent:     " & Format(percent, "0.0"))

End Sub

==========================

The function GetComplexity... im not happy with that, my head isn't working now to get a single line equation to work out the number... it works i think anyway. Let me know of any bugs, ya can reach me on the email on profile, but no new project questions there, only about this one :P
0

LVL 7

Author Comment

ID: 13543424
Crazily amazing.. How come SO MUCH CODE is required for such a simple task?? We'd think VB could be smarter than that..

Thanks a bizillion S-Twilley, i'll be testing it tomorrow, but even if there are bugs, I'll open another question for it.. You really love the job!

:-)
0

LVL 12

Expert Comment

ID: 13543448
Well there might be a shorter way of doing it... that way is long because im trying to prevent using nested calls to the same function (which can use up a lot of memory).... it's also spaced out and such so it's clear to read.

It can probably be shortened but I think while it's still being tested you should keep it like that.

Anyway, good luck with it

PS... not so much that I love the job, more like I'd rather be doing this than my own project
0

LVL 7

Author Comment

ID: 13553485
Your latest program STOPS after every code generated to show me a MSGBOX! That's gonna take EONS..

Like I said, the previous one is workable.. I'm trying to figure out how to, maybe, use a Timer to that I can update my labels, instead of the While Forever loop..

Will keep you posted..

Thanks again!

:-)
0

LVL 12

Expert Comment

ID: 13553517
only used a msgbox in it to show you the updated code and how you can calculate the %age.

u should be able to change the code to something like:

Private Sub CodeCaught(ByVal sender As Object, ByVal newcode As String, ByVal codenumber As Integer) Handles x.CodeGenerated
Dim percent As Single
Dim sPercent As String
Dim thisGenerator As SimpleCodeGenerator = sender

percent = 100 * codenumber / thisGenerator.GetComplexity
sPercent = Format(percent, "0.0")
If sPercent <> lblPercent.Text Then
lblPercent.Text = sPercent
lblPercent.Refresh
End If

lblLastCode.Text = newcode 'This will probably be going so fast that you wont see it properly
' one options is that when the code is > 4 characters long, or 3... that you ignore
' the last 3 characters and put in *** so it's not constantly changing...
'then you'd see what kinda place you are with the code e.g.   ABA***
lblLastCode.Refresh

End Sub
0

## Featured Post

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.