高度对称的多面体和它们的对偶多面体

正四面体、正方体、正八面体、正十二面体、正二十面体,这是古希腊人就发现的五种正多面体,它们拥有最高标准的对称性。这五种正多面体又叫做 Platonic 体,它们在古希腊的哲学观念中占据着至关重要的地位。 Leonhard Euler 发现,多面体的顶点数 V 、棱数 E 和面数 F 一定满足公式 V – E + F = 2 ,这叫做 Euler 多面体公式。利用这个公式,我们可以证明正多面体只有五种。假设一个正多面体的每个面都是正 p 边形,那么所有 F 个面一共就有 p · F 条边;每两条边拼在一起形成了一条棱,因而总的棱数就是 E = p · F / 2 。反过来, F 就应该等于 2 · E / p 。不妨再假设每个顶点处都汇集了 q 条棱,那么总的棱数似乎应有 q · V 个;但这样计算的话,每条棱都被重复算了两次,因而总的棱数实际上应该是 E = q · V / 2 。反过来, V 就应该等于 2 · E / q 。另外, Euler 的多面体公式告诉我们, V – E + F = 2 始终成立。

把上面几个式子合在一起,于是得到:

2 · E / q – E + 2 · E / p = 2

整理可得:

1/p + 1/q – 1/2 = 1/E

因此, 1/p + 1/q 一定大于 1/2 。但是,正多面体每个面至少都有三条边,每个顶点也至少汇集了三条棱,因此 p 和 q 都是大于等于 3 的整数。要想 1/p + 1/q > 1/2 ,只有以下五种可能:

  1. p = 3 , q = 3
  2. p = 3 , q = 4
  3. p = 4 , q = 3
  4. p = 3 , q = 5
  5. p = 5 , q = 3

这正好对应于那五种正多面体。最近 Localhost-8080 沉迷于折纸,我也因此学习了不少与多面体相关的东西。想不到,这些看似老生常谈的东西,里面的水可深着呢。这五种正多面体表面上只是问题的五个不同的解,但互相之间却有着出人意料的联系。我们再列一个更加完整的表格,有意思的东西会慢慢呈现出来:

名称 面数 F 顶点数 V 棱数 E 每个面的边数 p 每个顶点处的棱数 q
正四面体 4 4 6 3 3
正方体 6 8 12 4 3
正八面体 8 6 12 3 4
正十二面体 12 20 30 5 3
正二十面体 20 12 30 3 5

Read more…

用三段 140 字符以内的代码生成一张 1024×1024 的图片

Kyle McCormick 在 StackExchange 上发起了一个叫做 Tweetable Mathematical Art 的比赛,参赛者需要用三条推这么长的代码来生成一张图片。具体地说,参赛者需要用 C++ 语言编写 RD 、 GR 、 BL 三个函数,每个函数都不能超过 140 个字符。每个函数都会接到 i 和 j 两个整型参数(0 ≤ i, j ≤ 1023),然后需要返回一个 0 到 255 之间的整数,表示位于 (i, j) 的像素点的颜色值。举个例子,如果 RD(0, 0) 和 GR(0, 0) 返回的都是 0 ,但 BL(0, 0) 返回的是 255 ,那么图像的最左上角那个像素就是蓝色。参赛者编写的代码会被插进下面这段程序当中(我做了一些细微的改动),最终会生成一个大小为 1024×1024 的图片。

// NOTE: compile with g++ filename.cpp -std=c++11
 
#include <iostream>
#include <cmath>
#include <cstdlib>
#define DIM 1024
#define DM1 (DIM-1)
#define _sq(x) ((x)*(x)) // square
#define _cb(x) abs((x)*(x)*(x)) // absolute value of cube
#define _cr(x) (unsigned char)(pow((x),1.0/3.0)) // cube root
 
unsigned char GR(int,int);
unsigned char BL(int,int);
 
unsigned char RD(int i,int j){
   // YOUR CODE HERE
}
unsigned char GR(int i,int j){
   // YOUR CODE HERE
}
unsigned char BL(int i,int j){
   // YOUR CODE HERE
}
 
void pixel_write(int,int);
FILE *fp;
int main(){
    fp = fopen("MathPic.ppm","wb");
    fprintf(fp, "P6\n%d %d\n255\n", DIM, DIM);
    for(int j=0;j<DIM;j++)
        for(int i=0;i<DIM;i++)
            pixel_write(i,j);
    fclose(fp);
    return 0;
}
void pixel_write(int i, int j){
    static unsigned char color[3];
    color[0] = RD(i,j)&255;
    color[1] = GR(i,j)&255;
    color[2] = BL(i,j)&255;
    fwrite(color, 1, 3, fp);
}

Read more…

2011年度最变态的迷宫难题

    下面大家将会看到的是一个极其简单而又极其复杂的“迷宫”,这无疑是我在本年度见到的最变态的谜题:从左边入口处的 2011 进去,在迷宫里转悠,最后变成 2012 从右边出来。你可以在迷宫里转圈,可以重复之前走过的路,但不能往回退着走。

      

    你能成功走出来吗?

Read more…

汉字地图第二版

    去年年初的时候,我曾经发布过某专业课期末作业研究过程中带来的一个有趣的副产品:汉字的字义网络图。不过,当时我是直接调用的 Mathematica 的相关函数,函数几乎不能调整参数,并且也无法处理边上权重不同的情况。最近在研究引力斥力绘图算法,突然想到把当时的数据重新画一张图。于是就有了汉字地图第二版(点击小图看大图):

   

Read more…

无聊小制作:电影的颜色

    昨天无聊时用 MPlayer 和 Mathematica 做了一张图。大致过程是,用 MPlayer 从各个电影中提取出间隔大致均等的 600 帧图像,导入到 Mathematica 中,再取各帧图像的颜色平均值,用一根根宽度为 1 像素的竖条来表示。得到的结果就是下面这个样子。你能在看到答案之前先猜出电影名字吗?你能识别出每一段颜色都对应着什么情节吗?

 

 

Update: 看了大家的回复,我才悲催地发现,这件事情早有人做过了,而且做得比我更好。大家感兴趣的话可以前往: http://moviebarcode.tumblr.com/