【破事水】FLAME游戏背后的算法

一日,光头程序员的女票在看某短视频APP的时候刷到了一个叫FLAME游戏的视频1,说是列出两个人的名字,然后经过如下的操作之后就可以算出两人的关系:
F 是朋友
L 是心爱的人
A 是喜欢的人
M 是结婚对象
E 是敌人
写下两人的英文名字,可以用拼音将你们名字中相同的字母划掉,然后剩下几个拼音就从剩的总数重复数FLAME(点到哪个划掉哪个,只剩最后一个字母)
字母对应着你们的关系

0x00 初次尝试

在没看到视频的当下,我直接拿起张三(Zhang San)和李四(Li Si)开始了第一轮的计算:

Created with Raphaël 2.3.0 开始 Zhang San & Li Si 去掉相同的S 得到Zhang an & Li i 剩下10个字母

然后开始计算 FLAME:

  1. 去除第10个字母,也就是 FLAME
  2. 接着还是去除第10个字母,也就是 FLAM;
  3. 故技重施,得到 FAM;
  4. AM 则去掉 M,得到最后的字母为 A

也就是喜欢的人(Affection2)。

0x01 更进一步

女票表示,不对劲,去的有点少,不好数。
所以添加一条新规则 —— 可以去掉名字中所有重复的字母。

那么0x00中求出来的 Zhang an & Li i 就要进一步剔除,得到 Zhg & L
这样就只要数4个字母了。

接着还是算FLAME的方法,每次去掉的位置为剩余字母数N对FLAME剩余字母数n的求余数,也就是:

N = 1 N = 1 N=1 n ∈ { 2 , 3 , 4 , 5 } n\in\{2,3,4,5\} n{2,3,4,5}时,
[ 1 m o d    5 , 1 m o d    4 , 1 m o d    3 , 1 m o d    2 ] [{1}\mod{5},{1}\mod{4},{1}\mod{3},{1}\mod{2}] [1mod5,1mod4,1mod3,1mod2]
[ 1 , 1 , 1 , 1 ] [1,1,1,1] [1,1,1,1]
也就是说四次全删除第一个字母即可,
通过求这四个数的最小公倍数,我们可以知道:
这样的规律每 3 × 4 × 5 = 60 3\times4\times5=60 3×4×5=60 次产生一个轮回;

那么,这回我就直接把一次轮回的所有可能都枚举出来了,也就是:

剩余字母数你们的关系
1E
2F
3L
4L
5M
6L
7E
8F
9A
10A
11E
12F
13E
14F
15L
16A
17E
18F
19E
20F
21M
22M
23E
24F
25M
26L
27A
28L
29E
30F
31E
32F
33M
34A
35M
36L
37E
38F
39L
40L
41E
42F
43E
44F
45A
46M
47E
48F
49E
50F
51A
52A
53E
54F
55M
56L
57M
58M
59E
60F

统计一下每个字母在这60次中出现的频次和概率:

字母出现次数概率
F1626.67%
L1016.67%
A813.33%
M1016.67%
E1626.67%
27% 17% 13% 17% 27% 一个轮回中 F L A M E 出现的概率 F 朋友 L 心爱的人 A 喜欢的人 M 结婚对象 E 敌人

如果按拼音来说,最长的拼音可以有6个字母(如chuang),一个人名包括复姓,一般最多5个汉字,假设两人名字的字母没有一个重复的,才有可能到达最后的60,那么便不符合普遍现象;
所以,我们选取前 20 种情况,看看每种关系的概率如何:

字母出现次数概率
F630%
L420%
A315%
M15%
E630%
30% 20% 15% 5% 30% 前 20 种可能中 F L A M E 出现的概率 F 朋友 L 心爱的人 A 喜欢的人 M 结婚对象 E 敌人

我们就会发现:
只有 第5次 时出现了M(结婚对象);
F(朋友)和E(敌人)平分秋色,占比最大;
L(心爱的人)还比A(喜欢的人)的概率更高点。

所以,这道题其实至少三成是道送命题,遇到的话,还请慎重把握。

0x02 举一反三

那么我们能不能在后面那个求FLAME的算法里动点手脚呢?
当然可以,同样是FLAME,再划掉字母后,将剩下的字母填充进剩下的空里,保证是5个字母直到5个字母变成同一个字母为止。

示例:
还是Zhang San和Li Si,根据0x01已知他们最后剩下4个字母,经过改造后的算法为

  1. 整体左移,且标定位置前后都移动,留出的空按从左到右的顺序填充剩下字母:
    FLAME
    FLAEF
    FLAFL
    LALAL
    LLLLL
  2. 或是后移,前不移:
    FLAME
    FLAEF
    FLAFL
    LLALA
    AAAAA
  3. 或是前移,后不移:
    FLAME
    FLAFE
    LALAE
    LLLEE
    LLLLL
  4. 或是前后都不移:
    FLAME
    FLAFE
    LLAAE
    LLLEE
    LLLLL

那么同理,整体右移和按从右到左的顺序又能排列组合出共计 2 × 2 × 4 = 16 2\times2\times4=16 2×2×4=16 种不同的算法。

0x03 求本溯源

本着严谨的科学态度,咱打开了搜索引擎,倒是找到了一个关于FLAMES游戏的玩法说明2

What is the full form of Full form for Flames?
FLAMES stands for Friends, Lover, Affection, Marriage, Enemy, Sister(sibling).

Calculating relationship using Flames Game (step by step) Manually:

  1. Write down your name and partner’s name.
  2. Strikeout common letters in both names.
  3. Get the count remaining letters (Assuming it as N).
  4. Remove the N’th letter from the word FLAMES (If N > 6; start the second loop)
  5. Continue until you left with a single letter, and it is the Flames relationship.

翻译一下就是:

FLAMES里每个字母具体代表了什么关系呢?
F是朋友,L是情人,A是在意的人,M是结婚对象,E是敌人,S是姐妹(有血缘关系的兄弟姐妹3)。

手把手教你算FLAMES游戏:

  1. 写下你和你伴侣的名字。
  2. 将两人名字中相同的字母去掉。
  3. 记下剩下的字母数 (假设这个数是N)。
  4. 从单词FLAMES中删除第N个字母 (如果N大于6,则再从头开始数)。
  5. 重复以上步骤直到剩下最后一个字母,而这个字母据说就是你们俩之间的关系。

0x04 得寸进尺

那么以后还可以开发一个什么uncopyrightable Game来检查你的一段话和别人的一段话有没有可能出现版权纠纷:
U: Unfortunate 不幸地有问题
N: No 无版权问题
C: Closer 几近出问题
O: Open 原作者很开放
Y: Yours 你原创的
编不下去了,有大佬高兴的话可以在评论区补全
想试试看的话可以看看后面参考资料里关于函数 loopModGame(string, n) 的JS实现。

0x05 参考资料


/**
 * 返回FLAME游戏剩余字母数为n时的结果
 * 
 * @author LearningPawn
 * @param {Number} 两名字去重后的剩余字母数
 * @return {string} 最终得出的字母
 */
function flamegame(n) {
    var string = "FLAME";
    var list = [n%5, n%4, n%3, n%2];
    for (i in list) {	// 逐个去除字母,余数为0时,表示去除最后一位
        if(list[i] == 0) {
            string = string.substring(0, string.length-1);
        } else {
            string = string.replace(string[list[i]-1], "");
        }
    }
    return string;
}
/**
 * FLAME游戏的推广
 * 
 * @author LearningPawn
 * @param {string} 关键字母字符串,如"FLAME"
 * @param {Number} 两名字去重后的剩余字母数
 * @return {string} 最终得出的字母
 */
function loopModGame(string, n) {
    var length = string.length;    
    var list = [];
    for (i = length; i > 1; i--) {	// 求余到1时则无需再删字符
    	list.push(n%i);
    }
    console.log(list)
    for (i in list) {	// 逐个去除字母,余数为0时,表示去除最后一位
        if(list[i] == 0) {
            string = string.substring(0, string.length-1);
        } else {
            string = string.replace(string[list[i]-1], "");
        }
    }
    return string;
}

  1. 一个有趣的小游戏,来测试下你们两人实质上是什么关系吧[偷笑]——英国报姐 ↩︎

  2. PLAY FLAMES GAME ↩︎ ↩︎

  3. Sibling | Definition of Sibling by Merriam-Webster ↩︎

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学渣戊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值