美文网首页
打印围城

打印围城

作者: imjcw | 来源:发表于2018-09-15 15:01 被阅读0次

    题目

    写一个脚本,这个脚本可以输入多个参数,参数不可少于两个,执行完成后输出回形矩阵,具体查看下面两个例子的结果。

    示例

    示例1:

    执行脚本命令,传入三个参数: php test.php a b c

    脚本执行输出结果:

    a a a a a
    a b b b a
    a b c b a
    a b b b a
    a a a a a
    

    示例2:

    执行脚本命令,传入两个参数: php test.php a b

    脚本执行输出结果:

    a a a
    a b a
    a a a
    

    提示

    执行结果其实是一个 2n-1 * 2n-1 的数组,而且是一个轴对称的数组。

    解析思路

    利用其轴对称的特性,拼凑出上面的一部分,并复制反转,将两个数组合并成一个新的数组,最终输出结果。

    假设:

    有三个参数,这三个参数分别是: abc

    脚本执行结果如下:

    a a a a a
    a b b b a
    a b c b a
    a b b b a
    a a a a a
    

    观察执行结果:

    • 每行都有第一个参数 a
    • 整个数组相对于第 n 行轴对称,相对于第 n 列轴对称
    • 第一行之后第一个参数,第二行有第一和第二个参数,以此类推到 n
    • 结果总共有 2n-1 行,2n-1

    具体解题思路:

    第一步:生成 n 行值为第一个参数 a 的数组。

    $line = array_fill(0, $len * 2 - 1, 'a');
    $rows = array_fill(0, $len, $line);
    

    第二步:逐步替换每行的内容,并逐步替换每行的内容,这里以第三行举例

    // 原始
    // ['a', 'a', 'a', 'a', 'a']
    
    // 第一次替换
    // ['a', 'b', 'b', 'b', 'a']
    
    // 第二次替换
    // ['a', 'b', 'c', 'b', 'a']
    
    $argv = ['a', 'b', 'c'];
    $len = count($argv);
    $maxLen = $len * 2 - 1;
    foreach ($rows as $key => &$row) {
        for ($i = 1; $i <= $key; $i++) {
            $line = array_fill($i, $maxLen - $i * 2, $argv[$i]);
            $row = array_replace($row, $line);
        }
    }
    
    // ['a', 'a', 'a', 'a', 'a']
    // ['a', 'b', 'b', 'b', 'a']
    // ['a', 'b', 'c', 'b', 'a']
    

    第三步:复制已经获得的结果,然后反转

    $rest = array_reverse($rows);
    
    // ['a', 'b', 'c', 'b', 'a']
    // ['a', 'b', 'b', 'b', 'a']
    // ['a', 'a', 'a', 'a', 'a']
    

    第四步:去除反转数组的第一行

    array_shift($rest);
    
    // ['a', 'b', 'b', 'b', 'a']
    // ['a', 'a', 'a', 'a', 'a']
    

    第五步:拼接反转前和反转处理后的数组

    array_merge($rows, $rest);
    
    // ['a', 'a', 'a', 'a', 'a']
    // ['a', 'b', 'b', 'b', 'a']
    // ['a', 'b', 'c', 'b', 'a']
    // ['a', 'b', 'b', 'b', 'a']
    // ['a', 'a', 'a', 'a', 'a']
    

    大功告成。

    完整代码

    这里提供了多个版本的解题方法
    后续可能会增加其它语言的解题方法

    PHP版本

    $argv = ['👦', '❤️', '🐘'];
    $len = count($argv);
    $maxLen = 2*$len-1;
    $line = array_fill(0, $maxLen, reset($argv));
    $rows = array_fill(0, $len, $line);
    foreach ($rows as $key => &$row) {
        for ($i = 1; $i <= $key; $i++) {
            $line = array_fill($i, $maxLen - $i * 2, $argv[$i]);
            $row = array_replace($row, $line);
        }
    }
    unset($row);
    $rest = array_reverse($rows);
    array_shift($rest);
    $result = array_merge($rows, $rest);
    
    // 👦 👦 👦 👦 👦
    // 👦 ❤️ ❤️ ❤️ 👦
    // 👦 ❤️ 🐘 ❤️ 👦
    // 👦 ❤️ ❤️ ❤️ 👦
    // 👦 👦 👦 👦 👦
    

    JS版本

    这里需要注意的是,JS 的数组是用引用的方式传递的,如果想要复制,必须深复制,不然会发生改变复制数组,造成原数组同时改变的结果。

    var argv = ['a', 'b', 'c']
    var len = argv.length, maxLen = 2 * len - 1
    var rows = Array(len).fill(0)
    var result = []
    for (var i in rows) {
        i = parseInt(i)
        rows[i] = Array(maxLen).fill(argv[0])
        for (var j = 1; j <= i; j++) {
            rows[i].fill(argv[j], j, maxLen - j)
        }
    }
    var rest = [].concat(rows)
    rest.pop()
    rest.reduceRight(function (previous, current) {
        previous.push(current)
        return previous
    }, rows)
    

    相关文章

      网友评论

          本文标题:打印围城

          本文链接:https://www.haomeiwen.com/subject/zszzgftx.html