Go语言实现PTA L1-002打印沙漏算法解析
本文针对PTA L1-002“打印沙漏”题目,利用等差数列公式计算最大可用符号数,并结合Go语言的循环控制语句,实现了沙漏图案的中心对齐打印及剩余数量统计,为初学者提供清晰的解题思路与代码参考。
问题背景
在PTA团体程序设计天梯赛中,L1-002《打印沙漏》是一道经典的入门练习题。题目要求给定正整数N(N≤1000)和一个字符,程序需要将该字符排列成最大的沙漏形状。沙漏形状的规律如下:
- 每行输出的奇数个符号;
- 各行符号中心对齐;
- 相邻两行符号数相差2;
- 第一行符号数最多,逐行递减至中间的1个符号,随后递增回第一行的数量;
- 首尾行符号数相等。
核心难点在于:给定的N不一定能正好组成一个完整的沙漏,因此必须计算出最接近N且不超过N的沙漏所需的总符号数,最后输出未使用的符号数量。
解题思路
第一步:计算沙漏层级
观察沙漏结构可知,若将上下两层合并看为一个以1为核心、向上下对称扩展的结构,除去中间最核心的1个字符,每一层增加的字符数是 2 * i(其中i表示该层单边比内一层多出的行数)。这构成了一个等差数列:
- 第1层(含顶层和底层)消耗符号:
1 + 2*3 = 7 - 第2层累加后:
1 + 2*3 + 2*5 = 17 - 第k层累加后:
1 + ∑(2*(2*k+1))
我们需要找到一个最大的层数 i,使得总符号数 sum <= N。
第二步:输出沙漏图案
确定最大层数后,沙漏共有 2*i - 1 行。可以使用两个嵌套循环分别处理上半部分(包括中间行)和下半部分:
- 上半部分:行数从
i递减到 1,当前行字符数为j,需打印的前导空格数为(i - j) / 2。 - 下半部分:行数从
3递增到i(因为第1行已在上面打印过),同样利用空格数公式进行对齐。
Go语言实现
以下是完整的代码实现。注意输入处理时,fmt.Scanf 需要正确绑定变量地址;打印空格与字符时使用 fmt.Printf 保持格式控制。
package main
import (
"fmt"
)
func main() {
var n int
var tag byte
var sum, nextSum int
_, _ = fmt.Scanf("%d %c", &n, &tag)
sum = 1
nextSum = 1
i := 1
last := 0
for true { // 先是计算出所需要多少的符号
i += 2
nextSum += i * 2
if nextSum <= n {
sum += i * 2
} else {
i -= 2
last = n - sum
break
}
}
for j:=i; j>=1; j=j-2 { // 先打印上半部分
var space = (i - j) / 2
for k:=0; k<i-space; k++ {
if k < space {
fmt.Printf(" ") // 先打印空格
} else {
fmt.Printf("%c", tag) //再打印*
}
}
fmt.Println() // 最后记得要换行
}
for j:=3; j<=i; j=j+2 {
var space = (i - j) / 2 //再打印下半部分
for k:=0; k<i-space; k++ {
if k < space{
fmt.Printf(" ") //再打印*
} else {
fmt.Printf("%c", tag)
}
}
fmt.Println()
}
fmt.Println(last)
}
运行示例
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
在这个例子中,19个 '*' 最多可以组成消耗17个 '*' 的沙漏结构,剩余2个符号未被使用,程序末尾输出了这个数字2。
总结
本题主要考察了基本的算术运算和字符串格式化输出。关键在于理解沙漏结构的数学规律(等差数列求和),并能够通过循环精确控制前导空格的数量来实现居中效果。以上就是Go语言小白入门刷题打印输出沙漏的详细内容,更多关于Go语言打印沙漏的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













