|
I am making a program that can take a string and give you all possible strings that can be made out of the characters it contains.
Example:
Bug
Yeilds:
bug
bgu
ugb
ubg
gbu
gub
Can anyone think of how to do this short of trying until I get 6! unique results?
The best way to accelerate a Macintosh is at 9.8m/sec² - Marcus Dolengo
|
|
|
|
|
Hi,
the only way you will get 6! permutations is by starting off with a word that contains
6 letters, all of them different.
This is the algorithm to find all the different permutations in alphabetical order:
- initialize an int "len" to the number of total characters
- initialize a string "chars" with all the different letters in alphabetical order
- initialize an array "multipl" , with length equal to chars.Length, and values equal
to the multiplicity of each of the letters
- initialize a string "answer" to ""
- invoke the method explained below with the initialized values set out above
- create a recursive method void permute(len, answer, multipl)
that in a foreach loop over chars considers appending that character
to the partial answer, provided its multipl is non-zero; then calls itself again
(with len-1, adjusted answer, and adjusted multipl) unless len got zero, in which
case you have reached the next permutation.
BTW this topic belongs in the "algo & math" forum.
|
|
|
|
|
I have a list view which contains 100 items. For each item i need to do some work on it which takes a long time. I want to create (100 / 4) threads so i can split the work.
Lets assume my original code is
for(int i = 0; i < listview1.Items.Count; i++)<br />
{<br />
doStuff(listview1.Items[i].Subitems[1].Text);<br />
listview1.Items[i].Subitems[2].Text = "blah";<br />
}
Thread[] threads = new Thread[100/4];
Now how to split the work for each thread?
Thread 0:
for(int i = 0; i < 4; i++)<br />
{<br />
doStuff(listview1.Items[i].Subitems[1].Text);<br />
listview1.Items[i].Subitems[2].Text = "blah";<br />
}
Thread 1:
for(int i = 4; i < 8; i++)<br />
{<br />
doStuff(listview1.Items[i].Subitems[1].Text);<br />
listview1.Items[i].Subitems[2].Text = "blah";<br />
}
and so on.
|
|
|
|
|
Creating that many thread will not improve proformance, actually that many threads will slow proformance dramatically.
The best way to accelerate a Macintosh is at 9.8m/sec² - Marcus Dolengo
|
|
|
|
|
I think in my case it will, my function just takes a long time because it is using ping, so multiple threads will reduce the waiting time.
|
|
|
|
|
Yes, multiple is different than 25. Try looking at this, and use 1 or 2. Worker Thread[^]
The best way to accelerate a Macintosh is at 9.8m/sec² - Marcus Dolengo
|
|
|
|
|
This won't speed things up, it will add the cost of switching betweeen threads. Threads don't make things faster, they just leave the main (UI) thread responsive during large operations.
One thread that calls doStuff for all the items, and then at the end sets all the text as you want to show it's done, may make sense. Or even one that sets the text on each item as it goes.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
Hi,
adding threads may help as long as your job shows some remaining idle cycles,
provided the threads are not competing heavily for the same resources (CPU, memory
bandwidth, I/O bandwidth, ...).
In case of multiple pings, I expect there is some system limitation that will
make it impossible to have more than N outstanding pings, dont know what N would be tho.
Now if a succeeding ping needs a few seconds, and a failing ping times out in say
one minute, it would be bad design to split the ping destinations statically
(you might be unlucky and have all failing pings in the same thread, while the
other threads have long finished all the succesful pings, so threading did not help).
I would rather decide on a few threads, and let them fetch a ping target as soon
as they start or are idle again. So I would initially copy all targets to a list, and
(with lock) have the threads remove them one by one (so I'd use the list as a queue).
|
|
|
|
|
Hi,
as said before I wouldn't use that much threads. Second I wouldn't assign each thread its tasks from the beginning. It may be that some of your list elements need more time than others (especially true for pings) so each thread should fetch the next element whenever it needs to.
I would start by creating some sort of queue class which holds all your tasks:
public class MyQueue {
private string[] _elements;
private int _counter;
public MyQueue(string[] elements) {
_elements = elements;
_counter = 0;
}
public string GetNextElement() {
lock (_elements) {
if (_counter >= _elements.Length)
return null;
string result = _elements[_counter];
counter++;
return result;
}
}
}
Now define a function:
private void DoStuffInThread(object parameter) {
MyQueue queue = (MyQueue)parameter;
string nextElement;
while ((nextElement = queue.GetNextElement()) != null) {
}
}
And let the threading begin:
Thread[] threads = new Thread[numberOfDesiredThreads];
for (int i = 0; i < threads.Length; i++) {
threads[i] = new Thread(new ParameterizedThreadStart(DoStuffInThread));
threads[i].Start();
}
You have to add your processing logic, assignment of the results to the listview and also check when all threads are finished. Keep in mind that you should never change control properties directly from a different thread. Instead use Control.Invoke to make it safe.
Robert
|
|
|
|
|
Worked great thanks.
One problem though, not sure if im doing this correctly, everytime i try close the program while the threads are running it gets errors. I have a form closing event that invokes the Thread.Abort() method before closing but it doesnt seem to work. I think its the object disposed error.
private void displayPing(int index, string msg)<br />
{<br />
if (this.listView1.InvokeRequired)<br />
{<br />
try<br />
{<br />
displayCallBack hscb = new displayCallBack(displayPing);<br />
this.Invoke(hscb, new object[] { index, msg});<br />
}<br />
catch (Exception) { }<br />
}<br />
else<br />
{ <br />
try<br />
{<br />
this.listView1.Items[index].SubItems[5].Text = msg;<br />
}<br />
catch (Exception) { }<br />
}<br />
}
|
|
|
|
|
if you use too many threads, it will slow the computer, but to ban that, you should use Thread.Sleep(time in msec); or use boolean thread and it will be some useful
|
|
|
|
|
Alright so I've been working on this zombie simulation for a while and I recently redid it to work better. Problem is when I loop through to draw 1000 zombies on screen it only draws (and moves) a random number from 1 to 4. It is weird...anyways the code is below make someone can tell me why...
<br />
using System; <br />
using System.Drawing; <br />
using System.Drawing.Drawing2D; <br />
using System.Collections; <br />
using System.ComponentModel; <br />
using System.Windows.Forms; <br />
using System.Data; <br />
<br />
namespace ZombiesSim<br />
{<br />
public class Zombie : System.Windows.Forms.Form <br />
{<br />
private System.ComponentModel.IContainer components;<br />
<br />
private Timer timer = new Timer();<br />
private int freeze;<br />
private Brush human, panichuman, zombie, wall;<br />
private int num = 1000;<br />
private int speed = 1;<br />
private bool gxstart;<br />
private Being[] beings;<br />
private Bitmap world;<br />
private int width, height;<br />
private Random rand = new Random();<br />
private Building[] buildings;<br />
<br />
<br />
public Zombie() <br />
{ <br />
InitializeComponent(); <br />
<br />
human = new SolidBrush( Color.Purple );<br />
panichuman = new SolidBrush( Color.Pink );<br />
zombie = new SolidBrush( Color.Lime );<br />
wall = new SolidBrush( Color.DimGray );<br />
<br />
width = this.ClientSize.Width;<br />
height = this.ClientSize.Height;<br />
<br />
world = new Bitmap( width, height );<br />
gxstart = true;<br />
<br />
beings = new Being[4000];<br />
<br />
for( int i = 0; i < 1000; i++ )<br />
{<br />
beings[i] = new Being( width, height, zombie );<br />
}<br />
<br />
buildings = new Building[130];<br />
<br />
for( int i = 0; i < 100; i++ )<br />
{<br />
buildings[i] = new Building( rand.Next( width ), rand.Next( height ), rand.Next( 30, 90 ), rand.Next( 30, 90 ), wall );<br />
}<br />
<br />
for( int i = 100; i < 130; i++ )<br />
{<br />
buildings[i] = new Building( rand.Next( width ), rand.Next( height ), rand.Next( 40, 60 ), rand.Next( 40, 60 ), wall );<br />
}<br />
<br />
timer.Tick += new EventHandler( OnTimer );<br />
timer.Enabled = true;<br />
timer.Interval = 30;<br />
<br />
freeze = 0;<br />
<br />
this.SetStyle( ControlStyles.DoubleBuffer, true );<br />
this.SetStyle( ControlStyles.AllPaintingInWmPaint, true );<br />
this.SetStyle( ControlStyles.UserPaint, true );<br />
}<br />
<br />
protected override void Dispose( bool disposing ) <br />
{ <br />
if( disposing ) <br />
{ <br />
if (components != null) <br />
{ <br />
components.Dispose(); <br />
} <br />
} <br />
base.Dispose( disposing ); <br />
} <br />
<br />
#region Windows Form Designer generated code <br />
private void InitializeComponent() <br />
{ <br />
this.components = new System.ComponentModel.Container(); <br />
this.SuspendLayout(); <br />
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); <br />
this.ClientSize = new System.Drawing.Size(666, 666); <br />
this.Name = "Zombie Simulation"; <br />
this.Text = "Zombie Simulation"; <br />
this.ResumeLayout(false);<br />
this.MaximizeBox = false;<br />
this.FormBorderStyle = FormBorderStyle.FixedDialog;<br />
this.Paint += new System.Windows.Forms.PaintEventHandler(this.OnPaint);<br />
}<br />
#endregion<br />
<br />
[STAThread]<br />
static void Main()<br />
{<br />
Application.Run(new Zombie());<br />
}<br />
<br />
private void OnPaint(object sender, PaintEventArgs e)<br />
{<br />
e.Graphics.FillRectangle( new SolidBrush( Color.Black ), 0, 0, width, height );<br />
<br />
foreach( Building building in buildings )<br />
{<br />
e.Graphics.FillRectangle( building.Color, building.Draw() );<br />
}<br />
<br />
for( int i = 0; i < 1000; i++ )<br />
{<br />
e.Graphics.FillRectangle( beings[i].Color, beings[i].Draw() );<br />
}<br />
<br />
}<br />
<br />
private void OnTimer(object obj, EventArgs ea)<br />
{<br />
for( int i = 0; i < 1000; i++ )<br />
{<br />
beings[i].move(); <br />
}<br />
Invalidate( false );<br />
}<br />
}<br />
<br />
public class Being : Rect<br />
{<br />
private int dir, type, active, maxwidth, maxheight;<br />
private Random rand;<br />
<br />
public Being( int height, int width, Brush theHue )<br />
{<br />
rand = new Random();<br />
type = 1;<br />
active = 0;<br />
hue = theHue;<br />
maxwidth = width;<br />
maxheight = height;<br />
dir = rand.Next( 1, 4 );<br />
position();<br />
rect = new Rectangle( xpos, ypos, 5, 5 );<br />
}<br />
<br />
public void position()<br />
{<br />
xpos = rand.Next( 1, maxwidth - 1);<br />
ypos = rand.Next( 1, maxheight - 1);<br />
}<br />
<br />
public void infect( int x, int y )<br />
{<br />
if( x == xpos && y == ypos )<br />
type = 2;<br />
}<br />
<br />
public void infect()<br />
{<br />
type = 2;<br />
}<br />
<br />
public void uninfect()<br />
{<br />
type = 1;<br />
}<br />
<br />
public void look( int x, int y )<br />
{<br />
dir = rand.Next( 1, 4 );<br />
<br />
if( dir == 1 )<br />
y++;<br />
if( dir == 2 )<br />
x++;<br />
if( dir == 3 )<br />
y--;<br />
if( dir == 4 )<br />
x--;<br />
}<br />
<br />
public void move()<br />
{<br />
rect.Offset( rand.Next( -4, 4 ), rand.Next( -4, 4 ) );<br />
if( rect.X > 666 )<br />
rect.X = 664;<br />
if( rect.Y > 666 )<br />
rect.Y = 664;<br />
if( rect.X < 0 )<br />
rect.X = 0;<br />
if( rect.Y < 0 )<br />
rect.Y = 0;<br />
}<br />
}<br />
<br />
public class Building : Rect<br />
{<br />
<br />
public Building( int x, int y, int randw, int randh, Brush theHue )<br />
{<br />
hue = theHue;<br />
rect = new Rectangle( x, y, randw, randh );<br />
}<br />
}<br />
}
|
|
|
|
|
mfkr wrote: if( rect.X > 666 )
rect.X = 664;
if( rect.Y > 666 )
rect.Y = 664;
if( rect.X < 0 )
rect.X = 0;
if( rect.Y < 0 )
rect.Y = 0;
Once they hit the edge, they stay there ? They move in a completely random way ? It's more typical to keep variables to say what direction they are moving in the x and y, initialise them randomly, then when they hit an edge, reverse their direction.
Have you stepped through the code to see what is happening ?
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
That isn't what I'm really worried about right now. I'm worried more about getting all the beings on the screen...I have a loop for 1000 and it only does 1 to 4...I know that the code you have above is bad but it is temporary just to test...
|
|
|
|
|
Well, it's way too much code to expect anyone is going to read it all, that's why I suggested a breakpoint or some logging code, to see if they are actually all being moved, and what the result is.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
I'm not familiar with how windows seeds its Random number generator but if it is like others I've used they are often seeded with the system tick if you don't specify a seed value. You create a new generator for each being, and I bet they all get started with the same seed so they're just drawing over the tops of each other.
Either use one Random() to rule them all, or put some sort of delay between calls.
|
|
|
|
|
I think I got it. For some reason whenever you start a new instance of being...the random that I start an instance of is just about always the same. However, if I run the random from the main program...it actually creates a random position...odd...Thanks guys.
|
|
|
|
|
It's not odd, it happens for exactly the reason you were just told it would happen.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
No, not odd. Understand how a Random Number Generator works. There's no such thing as a truely random number in a computer. They can't come up with a number out of thin air. Even humans can't do this reliably.
The RNG is a smallish piece of code that takes a starting number (a seed) and puts it through a complex calculations to arive at a new number. The next pseudo-random number takes the previous one and runs it through the same math to arrive at a new number, and so on, and so on.
This generates a string of REPEATABLE pseudo-random numbers, given any seed value.
As the previous poster said, if you don't give a seed value when you create your Random object, the timer value is used. All of your objects are creating their own Random object, but they're all seeded with the exact same value! There result will be all of of those Random objects each generating the exact same string of numbers!
Typically, you'd create a static Random somewhere, much like a "global variable", that all of your code can get to. That way, you only have one source of random numbers, which will give you a closer approximation of "random" acrossed your code than having multiple sources.
|
|
|
|
|
Hi
I have an array of integers, where each one is an index for an array of objects, and I'm trying to sort the array by the .name property of the objects. I've set up a class using the IComparer interface to do this.
List<int> SubjList = new List<int>();
SubjectIndexComparer<int> subjectIndexComparer = new SubjectIndexComparer<int>();
...
SubjList.Sort(subjectIndexComparer);
public class SubjectIndexComparer<T> : IComparer<T>
{
...
public int Compare(T x, T y)
{
string textX = Singleton.Instance.subjList[(int)x].name;
string textY = Singleton.Instance.subjList[(int)y].name;
...
}
}
However, this doesn't work because I can't cast x and y from type T to int. I only want the function to work if T can be casted to an integer. How can I implement this? I don't actually need the function to be generic, it would be fine if it just took integers, but the List.Sort() method required that form. Thanks in advance.
Jack
|
|
|
|
|
Why don't you try with:
public class SubjectIndexComparer<int> : IComparer<int>
{
...
public int Compare(int x, int y)
{
...
}
}
? Does that helps?
|
|
|
|
|
I tried with:
public class SubjectIndexComparer : IComparer
{
...
public int Compare(int x, int y)
{
...
}
}
but I got:
'UQTimetable.SubjectIndexComparer' does not implement interface member 'System.Collections.IComparer.Compare(object, object)'
I tried with:
public class SubjectIndexComparer : IComparer
{
...
public int Compare(object x, object y)
{
...
}
}
but I got:
The best overloaded method match for 'System.Collections.Generic.List<int>.Sort(System.Collections.Generic.IComparer<int>)' has some invalid arguments
Argument '1': cannot convert from 'UQTimetable.SubjectIndexComparer' to 'System.Collections.Generic.IComparer<int>'
Any more ideas?
Jack
|
|
|
|
|
Use this:
public class SubjectIndexComparer : IComparer<int>
{
public int Compare(int x, int y)
{
...
}
}
|
|
|
|
|
that's what I meant... tnx for correcting me Daniel.
|
|
|
|
|
Worked a treat! Thanks
Jack
|
|
|
|
|