早上好!今天是 3 月 14 日,一年一度的圆周率日。为了和大家庆祝这个日子,我下载了一个 JavaScript 俄罗斯方块游戏 Js Tetris 的源代码,并且小小地修改了一下。那 7 种四联骨牌已经不复存在了,你将看到圆周率中的数字一个接一个地依次落下。这恐怕有希望成为史上最变态的俄罗斯方块了吧。
游戏改造完毕后,我自己居然沉迷了好久。把积木换成数字后游戏变得不是一般的困难,有很多小技巧有待大家慢慢去摸索。我个人的最好成绩是第 32 位。你呢?
早上好!今天是 3 月 14 日,一年一度的圆周率日。为了和大家庆祝这个日子,我下载了一个 JavaScript 俄罗斯方块游戏 Js Tetris 的源代码,并且小小地修改了一下。那 7 种四联骨牌已经不复存在了,你将看到圆周率中的数字一个接一个地依次落下。这恐怕有希望成为史上最变态的俄罗斯方块了吧。
游戏改造完毕后,我自己居然沉迷了好久。把积木换成数字后游戏变得不是一般的困难,有很多小技巧有待大家慢慢去摸索。我个人的最好成绩是第 32 位。你呢?
>>> http://www.matrix67.com/ideagen <<<
在小学应用题里面,师徒二人的工作除了做衣服就是加工零件,百货商场里卖的永远是彩电和冰箱,村里的工程队不是修路就是挖水渠。长大了后,我才惊讶地发现,编出一道背景有新颖一些的应用题并不是一件容易事儿。在冰冷的键盘和屏幕前面,能够进入我们脑子里的东西并不多。在我写文章时,我经常需要想出一些贴近实际生活的例子,或是恰当而又有新意的比方;环顾四周,却发现身边的物品并没有带给我什么启发。此时,我竭尽全力去捕捉生活中的各种小事,却发现那些平时司空见惯的琐事很难被思维触及。
于是,我写了一个小程序。每刷新一次,程序便会自动从近千个形容词和上万个名词中随机挑选出一对显示出来。当你在写文章、出题目、做策划时想不到什么好点子了,不妨用这个小工具来帮你打开思路。
在数学研究中,我们经常需要寻找一个命题的充分条件。有时候,我们在解题过程中会不自觉地思考结论的充分条件。例如,等底等高便是两个三角形面积相等的充分条件,这就为我们证明三角形面积相等指明了一条道路,接下来我们只需要说明那两个三角形的确是等底等高的就行了。又如,“任意顶点的度数大于等于n/2”是“无向图存在Hamilton回路”的充分条件,它经常被用来说明一个图有Hamilton回路。不过,与寻找必要条件不同的是,寻找一个命题“可以由什么推出来”是一个逆向思维,构造一个充分条件并不容易。有没有一种寻找充分条件的系统方法呢?我最近几天加班加点地研究,终于完成了一个充分条件分析器。你可以在输入框中属于一个与变量x相关的命题,系统将自动给出一个命题的充分条件。这个系统虽然是测试版,但它已经十分强大了。它不仅支持三角函数、对数函数、指数函数、阶乘等各类函数,还支持极限、微分、积分运算,甚至能够处理包括中文在内的自然语言。如果你不知道该输入什么,你可以先点击下面的几个样例试一试。
考虑函数f(z)=z^2-0.75。固定z0的值后,我们可以通过不断地迭代算出一系列的z值:z1=f(z0), z2=f(z1), z3=f(z2), ...。比如,当z0 = 1时,我们可以依次迭代出:
z1 = f(1.0) = 1.0^2 - 0.75 = 0.25
z2 = f(0.25) = 0.25^2 - 0.75 = -0.6875
z3 = f(-0.6875) = (-0.6875)^2 - 0.75 = -0.2773
z4 = f(-0.2773) = (-0.2773)^2 - 0.75 = -0.6731
z5 = f(-0.6731) = (-0.6731)^2 - 0.75 = -0.2970
...
可以看出,z值始终在某一范围内,并将最终收敛到某一个值上。
但当z0=2时,情况就不一样了。几次迭代后我们将立即发现z值最终会趋于无穷大:
z1 = f(2.0) = (2.0)^2 - 0.75 = 3.25
z2 = f(3.25) = (3.25)^2 - 0.75 = 9.8125
z3 = f(9.8125) = (9.8125)^2 - 0.75 = 95.535
z4 = f(95.535) = (95.535)^2 - 0.75 = 9126.2
z5 = f(9126.2) = (9126.2)^2 - 0.75 = 83287819.2
...
经过计算,我们可以得到如下结论:当z0属于[-1.5, 1.5]时,z值始终不会超出某个范围;而当z0小于-1.5或大于1.5后,z值最终将趋于无穷。
现在,我们把这个函数扩展到整个复数范围。对于复数z0=x+iy,取不同的x值和y值,函数迭代的结果不一样:对于有些z0,函数值约束在某一范围内;而对于另一些z0,函数值则发散到无穷。由于复数对应平面上的点,因此我们可以用一个平面图形来表示,对于哪些z0函数值最终趋于无穷,对于哪些z0函数值最终不会趋于无穷。我们用深灰色表示不会使函数值趋于无穷的z0;对于其它的z0,我们用不同的颜色来区别不同的发散速度。由于当某个时候|z|>2时,函数值一定发散,因此这里定义发散速度为:使|z|大于2的迭代次数越少,则发散速度越快。这个图形可以编程画出。和上次一样,我用Pascal语言,因为我不会C的图形操作。某个MM要过生日了,我把这个自己编程画的图片送给她^_^
{$ASSERTIONS+}
uses graph;
type
complex=record
re:real;
im:real;
end;
operator * (a:complex; b:complex) c:complex;
begin
c.re := a.re*b.re - a.im*b.im;
c.im := a.im*b.re + a.re*b.im;
end;
operator + (a:complex; b:complex) c:complex;
begin
c.re := a.re + b.re;
c.im := a.im + b.im;
end;
var
z,c:complex;
gd,gm,i,j,k:integer;
begin
gd:=D8bit;
gm:=m640x480;
InitGraph(gd,gm,'');
Assert(graphResult=grOk);
c.re:=-0.75;
c.im:=0;
for i:=-300 to 300 do
for j:=-200 to 200 do
begin
z.re:=i/200;
z.im:=j/200;
for k:=0 to 200 do
begin
if sqrt(z.re*z.re + z.im*z.im) >2 then break
else z:=(z*z)+c;
end;
PutPixel(i+300,j+200,k)
end;
readln;
CloseGraph;
end.
代码在Windows XP SP2,FPC 2.0下通过编译,麻烦大家帮忙报告一下程序运行是否正常(上次有人告诉我说我写的绘图程序不能编译)。在我这里,程序运行的结果如下:

这个美丽的分形图形表现的就是f(z)=z^2-0.75时的Julia集。考虑复数函数f(z)=z^2+c,不同的复数c对应着不同的Julia集。也就是说,每取一个不同的c你都能得到一个不同的Julia集分形图形,并且令人吃惊的是每一个分形图形都是那么美丽。下面的六幅图片是取不同的c值得到的分形图形。你可能不相信这样一个简单的构造法则可以生成这么美丽的图形,这没什么,你可以改变上面程序代码中c变量的值来亲自验证。
c = 0.45, -0.1428

c = 0.285, 0.01

c = 0.285, 0

c = -0.8, 0.156

c = -0.835, -0.2321

c = -0.70176, -0.3842

类似地,我们固定z0=0,那么对于不同的复数c,函数的迭代结果也不同。由于复数c对应平面上的点,因此我们可以用一个平面图形来表示,对于某个复数c,函数f(z)=z^2+c从z0=0开始迭代是否会发散到无穷。我们同样用不同颜色来表示不同的发散速度,最后得出的就是Mandelbrot集分形图形:

前面说过,分形图形是可以无限递归下去的,它的复杂度不随尺度减小而消失。Mandelbrot集的神奇之处就在于,你可以对这个分形图形不断放大,不同的尺度下你所看到的景象可能完全不同。放大到一定时候,你可以看到更小规模的Mandelbrot集,这证明Mandelbrot集是自相似的。下面的15幅图演示了Mandelbrot集的一个放大过程,你可以在这个过程中看到不同样式的分形图形。





网上可以找到很多小程序实现Mandelbrot集的放大过程。把上面给出的代码改一改,你也可以写出一个这样的程序来。
做人要厚道,转贴请注明出处
Current Version : 0.11
Last Update : 2007-05-31
Author : Matrix67.com
Click here to download (Do not directly link to this file)
This program is a batch extractor which exports album covers embedded in mp3 ID3v2 tags. Run pic_extractor.exe under Windows, it will search all mp3 files in the directory, export pictures in ID3v2 tags. Output filenames are formatted as "artist - album". Note that the artist and album info is taken from ID3v1, because the encoding of ID3v2 may vary. If there's no ID3v1 tag contained in your mp3 file, you may need some other powerful ID3 tools (ID3-TagIT fits me well) so you can transfer ID3v2 tags to ID3v1 tags. If there's any invalid character for filename (like '?', '\', '*') or ID3v1 tag doesn't exist, filename changes to "FilenameError", followed by a sequence number.
If you have any suggestion, advice or bug report, feel free to mail me at gs.matrix67@gmail.com, or you can just leave a message below.
Source code can be found here.
英文发布页:http://www.matrix67.com/blog/article.asp?id=259
0.11版发布,主要更新如下:
点击此处下载
转移系统平台后我试用了一大柄的音乐播放软件,最后还是选择了RhythmBox。对于我来说,RhythmBox的唯一缺点就是不支持mp3内部的专辑图片,而我的mp3文件全部都是标签嵌入的图片。RhythmBox可以通过读取~/.gnome2/rhythmbox/covers下“歌手 - 专辑名”格式的文件名来显示图片,于是我想到找个软件来批量导出专辑图片。没想到我把google翻了个底朝天都没找到这样的程序,一狠心打算自己写一个。
这个程序估计会有需要用的人,因此作为0.1 beta版发布在这里。现在已经发布了0.11版。我对这个小程序的开发比较感兴趣,任何觉得有需求的人可以在下面留言。发现Bug请帮忙报告一下(这句话说了N多次都没人回应)。
程序是在Windows下编写的。和上次一样,目前暂时不打算用Delphi(除非我要接着做下去)。C语言的文件操作还不怎么过关,只好又拿Free Pascal写了。
使用方法(请仔细阅读,发生任何意外我不负责!)
由于这是一个测试版,请先备份好你的mp3文件以防不测(其实一般不会发生问题,程序不写mp3文件)。下载该rar文件并解压,你会看到一个.exe文件。 将这个文件拷贝至你的mp3目录下,运行该文件后程序将扫描该目录下的所有mp3文件并寻找可能的内嵌图片,以ID3v1信息来命名图片文件,文件名格式为“歌手 - 专辑名”。相同文件名自动覆盖(这样的话你的专辑图片就是唯一的)。之所以不用ID3v2是因为ID3v2的编码不确定,我暂时不想处理Unicode。如果你的mp3里没有ID3v1标签,你可以随便找一个工具把ID3v2转为ID3v1,推荐用ID3-TagIt。建议你先复制少许mp3文件到新的文件夹试用一下。
以下情况可能导致错误:
1. mp3文件里嵌入多个图片或有图片说明(如果你是iTunes用户应该没问题);
2. ID3v1里有Windows不允许作为文件名的字符;
3. 不存在ID3v1或需要的ID3v1信息不全。
发生后两种情况时,文件名将用FilenameError加数字编号代替。
Matrix67原创
转贴请注明出处
如果有人感兴趣的话,附程序代码:program pic_extractor;
// -------------------------
// Current Version : 0.11
// Last Update : 2007-05-31
// Author : Matrix67.com
// -------------------------
// ----------------------------------------------------
// This program is a batch extractor which exports album
// covers embedded in mp3 ID3v2 tags. Compiled version can
// be found at http://www.matrix67.com/blog/article.asp?id=240
// Version 0.11 tested under Windows XP SP2, Free Pascal 2.0
// Next version will be written in Delphi.
// ----------------------------------------------------
uses dos,sysutils;
var
PictureType: string; // .png|.jpg|.bmp|.gif
FailCount : longint=0; // Number of Invalid Filenames
AlbumCount : longint=0; // Number of Albums
FileHandle : longint;
PicBuffer : array[1..1100000]of char;
InfoBuffer : array[1..210]of char;
FileNameDone: array[1..1100]of string[70];
// FileNameDone[AlbumCount]:=OutputFileName
function SameAlbum(OutputFileName:string):boolean;
var
i:longint;
begin
for i:=1 to AlbumCount do
if FileNameDone[i] = OutputFileName then exit(true);
inc(AlbumCount);
FileNameDone[ AlbumCount ] :=OutputFileName;
exit(false);
end;
function FindAPIC:longint;
// --------------------------------------------------------------
// This function will search the entire tag for APIC tag frame.
// Error may occur if there happens to be another 'APIC' string.
// Bugs will be fixed in next version.
// --------------------------------------------------------------
var
Scanner:string=' ';
FrameLength : longint=0;
Id3Length : longint=0;
identifier : integer;
procedure ReadFrame(var ch:char);
begin
FileRead( FileHandle , ch , SizeOf(ch) );
dec(FrameLength);
end;
var
i:longint;
ch:char;
begin
// Check if ID3 Tag Exists
FileRead( FileHandle, identifier, 2);
if identifier<>$4449 then exit(-1);
// Get Size of ID3 Tag
FileSeek( FileHandle, 4, fsFromCurrent);
for i:=1 to 4 do
begin
FileRead( FileHandle , ch , SizeOf(ch) );
Id3Length:=Id3Length shl 7 + ord(ch);
end;
// Search for APIC header
repeat
FileRead( FileHandle , ch , SizeOf(ch) );
dec(Id3Length);
delete(Scanner, 1, 1);
Scanner:=Scanner+ch;
if Scanner='APIC' then break;
until Id3Length=0;
if Scanner<>'APIC' then exit(-1);
// Calculate size of APIC frame
for i:=1 to 4 do
begin
FileRead( FileHandle , ch , SizeOf(ch) );
FrameLength:=FrameLength shl 8 + ord(ch);
end;
for i:=1 to 2 do FileRead( FileHandle , ch , SizeOf(ch) );
// Filename Extension
repeat ReadFrame(ch) until ch='/';
ReadFrame(ch);
if ch='j' then PictureType:='jpg'
else if ch='p' then PictureType:='png'
else if ch='b' then PictureType:='bmp'
else if ch='g' then PictureType:='gif'
else PictureType:='ukn'; // Unknown
// Drop some useless bits.
// Error may occur if any comment or type description exists.
repeat ReadFrame(ch) until ch=#0;
for i:=1 to 2 do ReadFrame(ch);
FileRead( FileHandle , PicBuffer , FrameLength );
exit(FrameLength);
end;
function FindOutputFileName:string;
// ------------------------------------------------------------------
// This function reads the very end of file for getting ID3v1 tag.
// Filename will be generated using "Artist - Album" format. We use ID3v1
// instead of ID3v2 because the encoding of ID3v2 may vary. This program
// can only handle GBK encodings. Files without ID3v1 lead to invalid
// filenames.
// ------------------------------------------------------------------
var
FindResult:string='';
i:longint;
begin
FileSeek( FileHandle , -128 , fsFromEnd );
FileRead( FileHandle , InfoBuffer , 128 );
// Identifier of ID3v1
// If no ID3v1 found, exit invalid characters for filename.
if InfoBuffer[1]+InfoBuffer[2]+InfoBuffer[3]<>'TAG' then exit('? - ?');
// Name of Album
i:=34;
while InfoBuffer[i]<>#0 do
begin
FindResult:=FindResult+InfoBuffer[i];
inc(i);
end;
// Filename Format : Artist - Album
// This format fits Rhythmbox well
// Format can be customized in further
FindResult:=FindResult + ' - ';
// Name of Artist
i:=64;
while InfoBuffer[i]<>#0 do
begin
FindResult:=FindResult+InfoBuffer[i];
inc(i);
end;
exit(FindResult);
end;
procedure SavePic( var OutputFileName:string; FrameLength:longint );
// ------------------------------------------------------
// Save the extracted picture with the filename provided
// by FindOutputFileName Function. Output directory and
// overwrite option will be added in GUI version.
// ------------------------------------------------------
var
FailedNum:string;
begin
FileHandle:=FileCreate(OutputFileName + '.' + PictureType);
if FileHandle=-1 then
begin
// Error caused by invalid characters, Changing Filename
inc(FailCount);
str(FailCount,FailedNum);
OutputFileName:='FilenameError' + FailedNum;
FileHandle:=FileCreate(OutputFileName + '.' + PictureType);
end;
FileWrite( FileHandle , PicBuffer , FrameLength );
FileClose( FileHandle );
end;
procedure main;
var
FrameLength : longint;
OutputFileName : string;
LastFileName : string;
dir:TSearchRec;
begin
FindFirst( '*.mp3', faAnyFile and not (faVolumeID or faDirectory), Dir);
while (DosError=0) do
begin
LastFileName:=Dir.name;
FileHandle:=FileOpen(Dir.name,fmOpenRead);
if FileHandle=-1 then halt;
write(Dir.name + ' --> ');
FrameLength := FindAPIC;
OutputFileName := FindOutputFileName;
FileClose( FileHandle );
if SameAlbum(OutputFileName) then
writeln('Same Album Cover Already Extracted.')
else if FrameLength=-1 then
writeln('Album Cover Not Found.')
else begin
SavePic(OutputFileName , FrameLength);
write('Found Album Cover, Saved as "');
writeln(OutputFileName + '.' + PictureType + '"');
end;
FindNext(Dir);
if Dir.name=LastFileName then halt;
end;
FindClose(Dir);
end;
begin
main;
end.