一个使用扑克牌表演的记忆魔法

2009-05-25 00:42:53

前些天去黄山路上,同事表演了一个“魔术”。表演方法:

由对方洗牌,洗的次数越多越好。洗好后,表演者拿起全部牌看一编,可以看牌面,但不改变牌的次序,“努力记忆”所有牌面的数值。然后交还对方。
由对方在前十张中随便选一张,告诉表演者是第几张。对方从这张牌开始,牌面数字是几,就往后数几张,然后再按照牌面数字按同样方法继续数,直到不能再继续为止,记住这张牌的数值。数牌时不让表演者看到。
然后,表演者开始利用强大的“记忆”能力开始“心算”,然后告诉对方,最后看到的数值是几。
以此证明,表演者强大的记忆力。

这里用程序来验证一下。

### 初始化扑克 ###
proc init_poker {{max_n 13} {max_m 2}} {
   set rv [list ]
   for {set m 1} {$m<=$max_m} {incr m} {
       for {set i 1} {$i<=$max_n} {incr i} {
           lappend rv $i
       }
   }
   return $rv;
}

### 随机洗牌 ###
proc shuffle_poker {iv {loop 13}} {
    set size [llength $iv]
    
    for {set i 1} {$i<=$loop} {incr i} {
        set r [expr int(floor(rand()*$size))]
        set t [lindex $iv $r]; 
        lset iv $r [lindex $iv 0]
        lset iv 0  $t

        set r [expr int(floor(rand()*$size))]
        set t [lindex $iv $r]; 
        lset iv $r [lindex $iv end]
        lset iv end $t
    }
    return $iv;
}

proc check_result {iv {seed 0}} {
    set size [llength $iv]
    # 第seed张牌是几,就往后数几张牌,直到数到最后,不能再数为止
    while {$seed<$size} {
        set n [lindex $iv $seed] 
        incr seed $n
    }
    # 返回最后数到的那张牌的数值
    return $n
}

### 检查是否必胜 ###

proc check_sure {{max_n 10} {n_poker 2}} {
    # 2副牌,只留下1到10的牌,随机洗牌
    set poker [shuffle_poker [init_poker $max_n [expr 4*$n_poker]] [expr 4*30]]
    
    # 无论从哪张开始数,结果都回落到同一张牌上
    # 殊途而同归
    set rv [list]
    set succ 1
    for {set i 0} {$i<$max_n} {incr i} {
        set v [check_result $poker $i]
        lappend rv $v
        if {[lindex $rv 0] != $v} {
            set succ 0
        }
    }
    
    return $succ
}

### 统计概率 ###

proc test_sure {{max_n 10} {n_poker 2}} {
    set n_succ 0
    set n_max 1000
    for {set i 0} {$i < $n_max} {incr i} {
        set sure [check_sure $max_n $n_poker]
        if {$sure==1} {incr n_succ}
    }
    puts [format "%2d/%d: %4d %4d %6.2f%%" $max_n $n_poker \
                   $n_succ $n_max [expr $n_succ*1.0/$n_max*100]]
}

test_sure 10 1
test_sure 13 1
test_sure 10 2
test_sure 13 2
test_sure 10 3
test_sure 13 3
test_sure 4 1
test_sure 5 1
test_sure 8 1
test_sure 4 2
test_sure 5 2
test_sure 6 2
test_sure 7 2
test_sure 8 2
test_sure 4 3
test_sure 5 3
test_sure 6 3
test_sure 7 3
test_sure 8 3

统计不同玩法的成功概率,结果如下:

10/1:  428 1000  42.80%
13/1:  247 1000  24.70%
10/2:  883 1000  88.30%
13/2:  749 1000  74.90%
10/3:  969 1000  96.90%
13/3:  909 1000  90.90%
 4/1:  938 1000  93.80%
 5/1:  869 1000  86.90%
 8/1:  611 1000  61.10%
 4/2: 1000 1000 100.00%
 5/2:  995 1000  99.50%
 6/2:  981 1000  98.10%
 7/2:  963 1000  96.30%
 8/2:  938 1000  93.80%
 4/3: 1000 1000 100.00%
 5/3: 1000 1000 100.00%
 6/3:  999 1000  99.90%
 7/3:  997 1000  99.70%
 8/3:  985 1000  98.50%


分享到: