 |
|
 |
There's a much more elegant way of picking a random line from a file. It involves reading every line in the file, but only keeping one line in memory at a time. The mini-puzzle is to tell me how
- Jason
(SonorkID 100.611)
"The sort of guy who'd give the kid an extra scoop of ice cream free if he was an ice-cream man"
- Nish, on Chris Maunder
|
|
|
|
 |
|
 |
What I would do is read the entire file once and store the locations of the beginning of each line in an array. Then generate a random fortune index, fseek to the location stored in the array, and read it in with fgets. This would be far more efficient with an enormous number of fortunes than my method since it requires only four bytes per entry to be saved. However it requires a disk access for each new fortune. As with nearly all things there a tradeoffs.
Interesting thought.
|
|
|
|
 |
|
 |
The algorithm I'm referring to is one I saw in a perl book, and it works quite elegantly:
$line = $_ if rand($.) < 1 while ();
The current line number is stored in the magic variable $. in perl. This little code snippet reads every line from a file, and during every iteration, selects the line just read as the chosen line IF a random number between 0 and the current line number is < 1. If you do a little model, you'll see that it's a fair way to pick a random line.
Interesting idea that's not at first obvious
- Jason
(SonorkID 100.611)
"The sort of guy who'd give the kid an extra scoop of ice cream free if he was an ice-cream man"
- Nish, on Chris Maunder
|
|
|
|
 |
|
 |
I do a similar thing, but instead of storing the start location of each fortune in memory I store these in another (binary file)
I then pick a random number between 1 and the total number of fortunes, jump to the appropriate line in this index file, read the file pointer value for the main fortune text file, and then read the fortune. This involves two file reads but does mean that you can address huge fortune files.
Incidentally, my fortunes are delimited by %% and so are not limited to single line fortunes.
Also, I actually index my fortunes into two index files based on the text length of each fortune. This is more inline with how the original Unix fortune program worked.
Type 'fortune -s' to get a random short fortune, 'fortune -l' to get a random long one and 'fortune' on its own to get either one or the other randomly.
Anyway, I realise that this app was the user's early attempt at coding and he does a very good job at that.
If you're interested have a look at this version (http://www.emgsrus.com/graffiti.htm) as well written by Motion Lab Systems, Inc.
Cheers
JJW
--
Same s**t, different day.
|
|
|
|
 |
|
 |
I haven't seen fortune in years!
Just some thoughts on the gradient (I've not looked at the code - just having a brain dump). I did a project once that required 256 colours to be repeatedly drawn (landscape shading). One of the issues was the time it took to create and destroy the brushes, so I took your approach of caching brushes between draws. The problem was that if I had 4 windows open at once (it was MDI, with different shading in each window) the system would quickly run out of pens. I ended up doing creating the brushes in one hit pre draw, then tearing down post-draw. Not elegant, not as fast as it could be, but at least it kept working. Then I went to OpenGL
Anyway, you just tweaked a memory about brush creation for shading and at the time I remember thinking 'Ah - if only that had a gradient brush!'
cheers,
Chris Maunder
|
|
|
|
 |
|
 |
That is a good point about resource utilization. One has to weigh the trade-offs between the performance of brush creation and destruction against the consumption of GDI resources. In my case, I just wanted to figure out an easy way to get it done and this is what I came up with many years ago.
You have made me curious. I wonder how the GDI does it in W98, W2K, etc. and how Paul DiLascia does it in his gradient title bar implementation. I haven't looked at his code in so long I can't remember.
Actually, these days I have been doing so many applications that I have a serious case of CRS. This is your TLA quiz of the day.
|
|
|
|
 |
|
 |
i think that title bar code just creates a new brush for each line. i've reused his code many times.
i think this is the code:
static void PaintRect(CDC& dc, int x, int y, int w, int h, COLORREF color)
{
CBrush brush(color);
CBrush* pOldBrush = dc.SelectObject(&brush);
dc.PatBlt(x, y, w, h, PATCOPY);
dc.SelectObject(pOldBrush);
}
void MakeCaptionBitmap()
{
if (m_bm.m_hObject)
return;
CRect cr;
GetClientRect(cr);
int w = cr.Width();
int h = cr.Height();
CWindowDC dcWin(this);
CDC dc;
dc.CreateCompatibleDC(&dcWin);
m_bm.DeleteObject();
m_bm.CreateCompatibleBitmap(&dcWin, w, h);
CBitmap* pOldBitmap = dc.SelectObject(&m_bm);
COLORREF clrBG = ::GetSysColor(COLOR_3DFACE); int r = GetRValue(clrBG); int g = GetGValue(clrBG); int b = GetBValue(clrBG); int x = 8*cr.right/8; int w1 = x - cr.left;
int NCOLORSHADES = 128;
int xDelta= max( w / NCOLORSHADES , 1);
PaintRect(dc, x, 0, cr.right-x, h, clrBG);
while (x > xDelta)
{ x -= xDelta; int wmx2 = (w1-x)*(w1-x); int w2 = w1*w1; PaintRect(dc, x, 0, xDelta, h,
RGB(r-(r*wmx2)/w2, g-(g*wmx2)/w2, b-(b*wmx2)/w2));
}
PaintRect(dc,0,0,x,h,RGB(0,0,0));
if (m_nameFont.GetSafeHandle()==NULL)
{
m_nameFont.CreateFont( 18, 0, 0, 0, FW_BOLD,
0, 0, 0, ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
FF_MODERN,
m_csFontName);
}
-c
Civilization is the limitless multiplication of unnecessary necessities.
Mark Twain
|
|
|
|
 |
|
 |
try this. it uses the original "fortune" file. refresh for a new one.
-c
Civilization is the limitless multiplication of unnecessary necessities.
Mark Twain
|
|
|
|
 |
|