打印围城

2018-09-15  本文已影响0人  imjcw

题目

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

示例

示例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

观察执行结果:

具体解题思路:

第一步:生成 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)
上一篇 下一篇

猜你喜欢

热点阅读