|
Yes, recursion is the right technique here. If you do it right, you get all the results in a predictable order (e.g. numeric ascending if your original data was numeric ascending).
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
|
|
|
|
|
There are some interesting approaches to generating permutations that you may want to check out. Google will be your friend.
In your case, a lexicographic ordered permutation algorithm may be the right one. You can find an example here[^].
There are many permutation generation algorithms on Knuth's The Art Of Computer Programming and other similar books, if you want to dig more into it.
However, you should be aware that the time complexity for generating permutations is of order O(n!), whatever algorithm you use, so you may bump on the time barrier if you raise your "n" too much. It's still an improvement over the naive nested for loops algorithm you tried as first solution, which has time complexity O(n^n).
Enjoy!
2+2=5 for very large amounts of 2
(always loved that one hehe!)
|
|
|
|
|
Good evening everybody,
in a viewer application I display images read from a non-GDI-compatible format through an RGB array:
Dim arrayImage() As Byte = MakeRGBArray(Me.DPXFile, ImageOffset, Width)
Dim gch As GCHandle = GCHandle.Alloc(arrayImage, GCHandleType.Pinned)
Dim pBuf As IntPtr = gch.AddrOfPinnedObject
PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
PictureBox1.Image = New Bitmap(Width, Height, 3 * Width, Imaging.PixelFormat.Format24bppRgb, pBuf)
gch.Free()
This basically works, but from time to time I run into trouble (i.e. the program crashes) when resizing or refreshing the form or the picture box. The AccessViolationException reports an attempt to read from protected memory, so I figure the GCHandle might not be freed before unloading the picture
I'm not experienced regarding the memory details, but it seems to work to leave the last line away and free the handle just before the next picture is loaded with If gch.IsAllocated Then gch.Free() . Could anybody please tell me if I'm on the right track with that or running into the next trouble? More questions arise from that, like: Would the handle be freed automatically when the form is closed?
Thanks for advice
Mick
|
|
|
|
|
Is it possible that the issue is that you are freeing an object which is still in use, because the bitmap is using it ? That seems likely to me, and it explans what's happening ( an intermittent crash, when the memory is reused )
Christian Graus
Driven to the arms of OSX by Vista.
Read my blog to find out how I've worked around bugs in Microsoft tools and frameworks.
|
|
|
|
|
Hi,
that is what documentation is for. MSDN on the Bitmap constructor that takes an IntPtr says: "The caller is responsible for allocating and freeing the block of memory specified by the scan0 parameter, however, the memory should not be released until the related Bitmap is released."
Hence you can't unpin the data as long as the bitmap is alive.
One solution could be to create a second image from the first one, like so (not tested, and C# syntax):
Bitmap bm1 = new Bitmap(Width, Height, 3 * Width, Imaging.PixelFormat.Format24bppRgb, pBuf);
Bitmap bm2 = new Bitmap(bm1);
bm1.Dispose();
gch.Free();
PictureBox1.Image=bm2;
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
|
|
|
|
|
@ Christian
I guess you're right. I had thought the new bitmap represents a separate instance after its construction and freed the memory too early, obviously.
@ Luc
Thank you for the workaround idea that makes sense. For the moment, I figure, I can leave the current solution of just freeing GCHandle later...
|
|
|
|
|
I would like to be able to pass arguments that may include system variables to File.Copy as part of a console app for updating my applications.
the console app is passed items from the main program that are read from an xml file
Private Function DownloadNetworkFile(ByVal UpdatePath As String, ByVal ProgramPath As String, ByVal FileName As String) As Boolean
If File.Exists(UpdatePath & "\" & FileName) = True Then
Try
If Not Directory.Exists(ProgramPath) Then
Directory.CreateDirectory(ProgramPath)
End If
File.Copy(UpdatePath & "\" & FileName, ProgramPath & "\" & FileName, True)
Console.WriteLine("Copy File " & FileName & "OK?= TRUE")
myUpdateLog.AppendLine("Copy File " & FileName & "OK?= TRUE")
Return False
Catch ex As Exception
Console.WriteLine("Copy File " & FileName & " OK?= " & ex.Message)
myUpdateLog.AppendLine("Copy File " & FileName & " OK?= " & ex.Message)
Console.WriteLine("Press Enter to continue")
myUpdateLog.AppendLine("Press Enter to continue")
Console.ReadKey()
Return True
End Try
Else
Console.WriteLine("Copy File " & FileName & "OK?= DOES NOT EXIST AT " & UpdatePath & "\" & FileName)
myUpdateLog.AppendLine("Copy File " & FileName & "OK?= DOES NOT EXIST AT " & UpdatePath & "\" & FileName)
Return True
End If
End Function>
when i do send %windir% file.copy does not fail but then it also does not seem to copy the file to the correct location.
for example
DownloadNetworkFile("c:","%windir%","test.bat")
in the console app i get Copy File test.bat OK?= TRUE
but when i go to the Windows Directory it is not there.
is there something i'm missing?
Thank you
|
|
|
|
|
This will get the Windows install directory
dim SystemRoot as string = System.Environment.GetEnvironmentVariable("SYSTEMROOT")
and two more ways to get the system32 directory:
dim sys32_1 as string = System.Environment.GetFolderPath(System.Environment.SpecialFolder.System)
dim sys32_2 as string = System.Environment.SystemDirectory
then you can do as you please with the path.
If at first you don't succeed ... post it on The Code Project and Pray.
|
|
|
|
|
You might try checking your ProgramPath parameter for %windir% first, and replace it with the value of your variable:
if ProgramPath = "%windir%" then ProgramPath = System.Environment.GetEnvironmentVariable("windir") Hope it helps.
Regards
Mick
|
|
|
|
|
i was hoping that file.copy would understand the system variables and be able to just "take them and go". i was hoping i was just missing something.
using anything else other than a system variable works just fine.
i guess i may have to try to parse the string to see if it contains any of the variables and then change it before allowing the code to run. i can setup a case statement for most of them but it just seems to be slow.
the issue is one day we may have a font file that needs to be installed on the computer during an update, and then the next day it may be some other file in another random place. since we have no control over where the customer installs the software or on what drive the software is installed it would be nice to be able to have these "old standards" usable to us.
maybe you guys have a better suggestion for what i'm trying to do?
|
|
|
|
|
Easy enough to solve. Use a Regular Expression to return the text inside the % characters, then just look that up in the environment variables and rebuilt the path using the returned values. It's mostly just simple string manipulation.
|
|
|
|
|
never thought about a regex. i pretty much suck when it comes to expressions, but i guess i'm not the only one.
any thoughts on what it might look like.
|
|
|
|
|
The RegEx expression might look something like:
%{1}(?'EnvName'\w{1,32})%{1}
This will capture the occurance of everything inside of a pair of % characters as a named capture group. Google for "RegEx.GetGroupNames" for an example of grabbing the text returned by the groups.
Oh, almost forgot. I use Expresso when it comes to Regular Expressions. It's an indispensible tool.
|
|
|
|
|
this is what i have so far
Dim regex As RegularExpressions.Regex
regex = New RegularExpressions.Regex("%{1}(?'EnvName'\w{1,32})%{1}")
Dim found As RegularExpressions.MatchCollection = regex.Matches(ProgramPath)
For Each aMatch As RegularExpressions.Match In found
Console.WriteLine(aMatch.ToString)
Console.WriteLine(Environment.GetEnvironmentVariable(aMatch.ToString.Replace("%", "")))
Next
which works like a champ
this "%windir%%programfiles%%systemroot%" for ProgramPath
gives me
%windir%
C:\WINDOWS
%programfiles%
C:\Program Files
%systemroot%
C:\WINDOWS
i am working on trying to get the regex to replace the %windir% with the GetEnvironmentVariable
but so far no luck. the input can be "%windir%\test"
most of the replace examples i find are for phone numbers and the like.
thank you again for your help.
|
|
|
|
|
Not sure if this is what you guys had in mind for final code but i hope this passes muster.
Dim regex As RegularExpressions.Regex
regex = New RegularExpressions.Regex("%{1}(?'EnvName'\w{1,32})%{1}")
Dim found As RegularExpressions.MatchCollection = regex.Matches(ProgramPath)
For Each aMatch As RegularExpressions.Match In found
myUpdateLog.AppendLine(ProgramPath)
ProgramPath = RegularExpressions.Regex.Replace(ProgramPath, aMatch.ToString, Environment.GetEnvironmentVariable(aMatch.ToString.Replace("%", "")))
myUpdateLog.AppendLine(ProgramPath)
Next
as a side note if anyone is interrested in an app for updating your programs let me know and i will share the code with you.
|
|
|
|
|
When I use the following code:
Private Sub addstart()
Dim Reg As Object
Set Reg = CreateObject("WScript.shell")
Reg.RegWrite "HKEY_CURRENT_USER\SOFTWARE\MICROSOFT\WINDOWS\CURRENTVERSION\RUN\" & App.EXEName, App.Path & "\" & App.EXEName & ".exe"
End Sub
Private Sub removeStart()
On Error Resume Next
Dim Reg As Object
Set Reg = CreateObject("WScript.shell")
Reg.RegDelete "HKEY_CURRENT_USER\SOFTWARE\MICROSOFT\WINDOWS\CURRENTVERSION\RUN\" & App.EXEName
End Sub
The program starts up fine at windows startup, but a dialog box pops up it says "you have changed the system configuration utility to make changes in the way Windows starts."
Is there a way to have your program automatically start without having that message pop up?
|
|
|
|
|
There's some other app that's putting that message up. It's not comming from Windows. Perhaps a virus scanner or some other startup monitoring software you have...
BTW: The entires in that registry key you're referring to are not run at Windows startup. They are run whenever a user logs into Windows at the console.
|
|
|
|
|
Hi there basicly im creating programe about customers in rent car office and i need to print the application with vb2008 by clicking on the printer button
Regrads,
|
|
|
|
|
Take a look at the Printer and PrintDocument classes on MSDN.
There is also a PrintPreview class, if you want to provide that functionality.
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
Hi Guys,
I have this weird problem in a VB6 application i am maintaining where an unexpected value is returned from addition of two doubles. One of those doubles is negative. Eg.
Dim tst As Double
Dim tst1 As Double
tst = -8.4
tst1 = 8.45
tst = tst + tst1
MsgBox tst
The Value of tst is 4.99999999999989E-02 when the MsgBox appears.
Anyone know whats going on here?
Thanks In Advance
|
|
|
|
|
For standard questions like this I have a standard answer:
The way floats/doubles are stored in binary makes it impossible to exactly represent
most values, especially the ones that seem like round numbers to humans thinking
using base ten.
So 4, 2, 1, 0.5, 3.5, 3.75 and many others are representable exactly (basically since
they all equal an integer divided by some power of 2); but 3.6 and 3.8 and an infinite
number of other values are not.
Now whatever float/double function you call, if it returns a float/double will suffer
from the same phenomenon. So the only way to really get "3.6" or "3.8" is by using a
function that not only rounds but returns a string. I trust there are some formatting
methods that do just that in every programming language; In .NET languages
ToString() should be one of them, given an appropriate format specifier.
If you want to know much more about this topic, here it is:
http://docs.sun.com/source/806-3568/ncg_goldberg.html
BTW: to circumvent the floating-point rounding problem, especially for monetary
numbers, they introduced the "decimal" data type (which basically stores decimal
digits).
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
|
|
|
|
|
Cheers Luc,
I Knew it was something simple just could not put my finger on it, i found the following code will work:
Dim tst As Double
Dim tst1 As Double
tst = -8.4
tst1 = 8.45
tst = tst + tst1
<big>tst = Round(tst, 2)</big>
MsgBox tst
|
|
|
|
|
Hello,
I have a task that needs to be executed many times in a thread, so as to keep my GUI responsive. Right now I'm using the ThreadPool to accomplish the tasks, and it works perfectly. I get all the data I expect back from the threads, life's good.
When those tasks are finished, I then fire off another set of threads to accomplish another set of tasks, in the same fashion. The work method of these threads uses a call to RegistryKey.OpenRemoteBaseKey, which does exactly that, opens a remote registry key. The problem is: if the user running the application does not have permission to open the remote registry the call will throw an IOException, but I expect this behaviour because the user does not have permission to do it. However, the call itself can take FOREVER.
I wrote the application initially to use delegate methods and used the WaitHandle.WaitOne() method on AutoResetEvents in a state object I passed to each delegate. I tried the WaitOne method using a timeout, which worked fine until I realized that even though the WaitOne timed out, the thread was still running. This is a problem because (from what I understand) processes are only given a certain number of ThreadPool threads and, once used, they must be finished in order to be released back to the threadpool. In my work method, I also have a variable that can be signalled when the thread should be stopped, but that (obviously) only works on code that I've written.
So, my question is, how can I cancel a thread that's stuck on a .NET method? Is there some sort of garbage collection method I can call if I give it a handle? There has to be a way.
I've searched Google, MSDN and everywhere in between for solutions to this, but no one has an answer.
|
|
|
|
|
Brandon D. Legault wrote: how can I cancel a thread that's stuck on a .NET method?
You can't. You don't have any access to the managed thread pool threads themselves. If it's that critical, you'll have to implement your own threads to have greater control.
|
|
|
|
|
I apologize, but I really can't accept that. There has to be a way to do it.
I've tried using my own threads (by my own threads I assume you mean just a managed thread?) but I've read many many times that Thread.Abort is frowned upon, bad design etc... , also, it doesn't actually cancel the thread, it only flags it for cancellation, and waits for an appropriate time to cancel it.
OpenRemoteBaseKey isn't the only .NET method that works this way. ManagementScope.Connect(), which I also use to retrieve information in this application (and need to be able to cancel as well), is written similarly in that you cannot cancel it once you start it.
Without being able to cancel them, I don't see any practical functionality in either of these two methods (or any other .NET methods that work like this). I shouldn't have to write my own wrapper around the native methods *shudder*, to expose a functionality that should be shipped with these methods in the first place.
|
|
|
|
|