zoukankan      html  css  js  c++  java
  • Look-and-Say 数列

    Look-and-See (边看边说) 数列具有好玩儿而神秘的特性,本文简要介绍它和它衍生出来的康威常数。

    沿革

    1977年7月1-13日,国际奥林匹克数学竞赛在前南斯拉夫首都贝尔格莱德举行,赛间,荷兰队非正式地给英国队出了个难题(其实类似脑筋急转弯),大致是这样的:

    1
    1, 11, 21, 1211, 111221

    上述数列的下一项是什么呢?

    英国队未予答复...

    故事并没有结束,后来,在剑桥大学执教的著名数学家约翰·霍顿·康威( John·Horton·Conway)从他的学生那儿拿到了这道题,他发现了其中的奥秘,并对它进行了分析和传播。

    康威在1986年去普林斯顿大学接任了著名的约翰·冯·诺依曼(John von Neumann)教授的位子,继续教书。

    特征

    给定种子数 d (种子数在0到9之间,非1), 那么,该数列就可以具体化为:

    1
    d, 1d, 111d, 311d, 13211d, 111312211d, 31131122211d, …

    如果种子数是1, 具体化后的数列就是本文开头的那个数列了。

    如果种子数是22,那么,具体化后的数列的每一项的每个数字,都是2,并且每一项都是22。

    当种子数不是22 时, 具体化后的数列的各项是依次增长的。

    增长率

    种子数不为22时,此数列的后项与前项比有极限,这个极限被称为康威常数,常用 λ 表示。

    λ ≈  1.303577269034296391257099112152551890730702504659404875754861390628550...

    我想知道:这里应该有图片,可是为什么51CTO的图片上传的“确认”按钮点了没效果呢?

    由于无法上传,请查看我创建的百度词条“Look-and-say 数列” 中的配图.

    (上图截取自维基百科: Look-and-say sequence , 我在百度百科为这个词建立了词条,感兴趣的可以去看下)

    上图中的四条曲线各自是一个 Look-and-say 数列的图示: 红色的种子数是23,蓝色的是1,紫色的是13,绿色的是312。

    随着 x 轴方向的变量不断变大,各个曲线的斜率趋向统一,极限值就是康威常数( Conway Constant )。

    用途

    看起来是无用之用的一个脑筋急转弯性质的数列,但康威却给出了不同的回答。

    康威基于这个数列建立了 Cosmological theorem,解释了宇宙衰变(Cosmological decay),用这个数列解释了化学元素衰变和相对原子质量之间的关系。

    实现牛肉板面的做法

    多种编程语言均可实现这个数列,现在我给出该数列在几种编程语言中的实现:

    JavaScript 实现1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /*
    node las.js
     */
    function lookAndSay(str) {
        return str.replace(/(.)1*/g, function(seq, p1){return seq.length.toString() + p1})
    }
     
    var num = "1";
    for (var i = 10; i > 0; i--) {
        console.log(num);
        num = lookAndSay(num);
    }

    JavaScript 实现2:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    /*
    * @Author: suifengtec
    * @Date:   2017-08-22 03:45:05
    * @Last Modified by:   suifengtec
    * @Last Modified time: 2017-08-22 03:51:02
    */
    /*
    node las1.js
     */
    function lookAndSay(digits) {
        var result = '',
            chars = (digits + ' ').split(''),
            lastChar = chars[0],
            times = 0;
      
        chars.forEach(function(nextChar) {
            if (nextChar === lastChar) {
                times++;
            }
            else {
                result += (times + '') + lastChar;
                lastChar = nextChar;
                times = 1;
            }
        });
      
        return result;
    }
      
    (function output(seed, iterations) {
        for (var i = 0; i < iterations; i++) {
            console.log(seed);
            seed = lookAndSay(seed);
        }
    })("1", 10);

    Lua语言的实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    -- @Author: suifengtec
    -- @Date:   2017-08-22 03:51:07
    -- @Last Modified by:   'suifengtec'
    -- @Last Modified time: 2017-08-22 03:56:18
    --a lua implement of the look-and-say sequence
    -- lua las.lua
    function lookAndSay(n)
      local t = {1}
      return function()
        local ret = {}
        for i, v in ipairs(t) do
          if t[i-1] and v == t[i-1] then
            ret[#ret - 1] = ret[#ret - 1] + 1
          else
            ret[#ret + 1] = 1
            ret[#ret + 1] = v
          end
        end
        t = ret
        n = n - 1
        if n > 0 then return table.concat(ret) end
      end
    end
    for i in lookAndSay(10) do print(i) end

    PHP 实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <?php
     
    /**
     * @Author: suifengtec
     * @Date:   2017-08-22 03:57:46
     * @Last Modified by:   'suifengtec'
     * @Last Modified time: 2017-08-22 03:59:52
     */
    /*
    php -S 127.0.0.1:9988 
    http://127.0.0.1:9988/las.php
     */
    function lookAndSay($str) {
      
        return preg_replace_callback('#(.)1*#'function($matches) {
            return strlen($matches[0]).$matches[1];
        }, $str);
    }
      
    $num '1';
     
    foreach(range(1,10) as $i) {
        echo $num.'<br/>';
        $num = lookAndSay($num);
    }

    Python 实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    # -*- coding: utf-8 -*-
    # @Author: suifengtec
    # @Date:   2017-08-22 04:00:59
    # @Last Modified by:   'suifengtec'
    # @Last Modified time: 2017-08-22 04:02:27
     
    #
    # Look and Say 数列的 Python 实现
    # python las.py
    #
     
     
    def lookAndSay(number):
        result = ""
     
        repeat = number[0]
        number = number[1:]+" "
        times = 1
     
        for actual in number:
            if actual != repeat:
                result += str(times)+repeat
                times = 1
                repeat = actual
            else:
                times += 1
     
        return result
     
    num = "1"
     
    for in range(10):
        print(num)
        num = lookAndSay(num)

    Rust 中的实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    /*
    rustc -o rs.exe las.rs && rs
     */
    fn las(in_seq: &[i8]) -> Vec<i8> {
        assert!(!in_seq.is_empty());
      
        let mut result = Vec::new();
        let mut current_number = in_seq[0];
        let mut current_runlength = 1;
      
        for i in &in_seq[1..] {
            if current_number == *i {
                current_runlength += 1;
            else {
                result.push(current_runlength);
                result.push(current_number);
                current_runlength = 1;
                current_number = *i;
            }
        }
        result.push(current_runlength);
        result.push(current_number);
        result
    }
      
    fn main() {
        let mut seq = vec![1];
      
        for i in 0..10 {
            println!("{}=>{:?}", i, seq);
            seq = las(&seq);
        }
    }

    Go 语言的实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    /*
    * @Author: coolwp.com
    * @Date:   2017-08-22 01:55:09
    * @Last Modified by:   suifengtec
    * @Last Modified time: 2017-08-22 02:37:27
    **/
     
    package main
     
    import (
        "fmt"
        "math"
        "strconv"
        "strings"
    )
     
    // 获取以 1 为种子数的Look-and-say 数列任意位置的数字
    func getNumberOfLookAndSaySequeceSeed1(position intint {
     
        if position == 1 {
            return 1
        }
        if position == 2 {
            return 11
        }
     
        str := "11"
     
        for i := 3; i <= position; i++ {
            str += "$"
            length := len(str)
            tmp := ""
            cnt := 1
            for j := 1; j < length; j++ {
                strSlice := strings.Split(str, "")
                if strSlice[j] != strSlice[j-1] {
                    cntTmp := strconv.Itoa(cnt)
                    tmp += cntTmp
                    tmp += strSlice[j-1]
                    cnt = 1
                else {
                    cnt++
                }
            }
     
            str = tmp
        }
     
        v, err := strconv.Atoi(str)
        //v, err := strconv.ParseInt(str, 10, 64)
        if err != nil {
            return -1
        }
        if v > math.MaxInt32 {
            return -1
        }
     
        return v
     
    }
     
    // 给定任意种子数 seed, 获取 LookAndSay 数列的 第 position 项
    func getNumberOfLookAndSaySequece(seed int, position intint {
     
        if seed == 22 {
            return 22
        }
        if position == 1 {
            return seed
        }
        seedStr := strconv.Itoa(seed)
        str := "2" + seedStr
        if position == 2 {
            v, err := strconv.Atoi(str)
            if err != nil {
                return -1
            }
            if v > math.MaxInt32 {
                return -1
            }
            return v
        }
     
        for i := 3; i < position; i++ {
            str += "$"
            length := len(str)
            tmp := ""
            cnt := 1
            for j := 1; j < length; j++ {
                strSlice := strings.Split(str, "")
                if strSlice[j] != strSlice[j-1] {
     
                    cntTmp := strconv.Itoa(cnt)
                    tmp += cntTmp
                    tmp += strSlice[j-1]
                    cnt = 1
                else {
                    cnt++
                }
            }
     
            str = tmp
        }
     
        r, err := strconv.Atoi(str)
        if err != nil {
            return -1
        }
        if r > math.MaxInt32 {
            return -1
        }
     
        return r
    }
     
    func main() {
     
        position := 5
        a := getNumberOfLookAndSaySequeceSeed1(position)
     
        seed := 1
        pos := 5
        b := getNumberOfLookAndSaySequece(seed, pos)
     
        fmt.Println(a)
        fmt.Println(b)
     
    }

    PS: 由于这个 js 不支持 Go 语言代码高亮,并且缩进也显示有问题, 所以请在粘贴后执行 go fmt。

    结论

    有一种声音认为:宇宙是一个程序,这个数列和康威常数用数字支持了这种说法。

     

  • 相关阅读:
    jdk环境变量及1.6官方下载地址
    linux创建用户和用户组
    java左移右移运算符
    浏览器是如何存储密码的
    【转】 ip段/数字,如192.168.0.1/24是什么意思?
    动态代理实现AOP【转】
    java自定义注解注解方法、类、属性等等【转】
    oracle插入主键数据、sequence和触发器
    ThreadLocal意为变量副本
    【转】java内部类的作用
  • 原文地址:https://www.cnblogs.com/beef/p/7420407.html
Copyright © 2011-2022 走看看