Introduction
This problem was shared by a skilled programmer from BUAA.
When I first saw this graphical problem, I was drawn to the way its pattern evolved, so much like a fractal. It looked like a straightforward drawing simulation, but as the number of operations n increased, the pattern’s size and complexity grew explosively. That made me realize that simply drawing everything by brute force could not be the right approach. This post reviews the whole process of discovering and implementing an elegant recurrence amid those complicated transformations, and ultimately solving the problem neatly.
The Problem
Background
A lilac flower usually has four petals. Their relative positions can be represented by the basic pattern below.
Four squares alone clearly cannot convey a lilac’s charm, so we perform one operation on the pattern, consisting of these two steps:
- Repeat the pattern 4 times, arranged as in the repetition diagram below.
- Rotate the pattern 45 degrees, as in the diagram showing the result of one operation.
We call these two steps together one operation. Repeating one more operation on the resulting pattern gives the pattern shown below after two operations.
![]() |
![]() |
![]() |
![]() |
| Basic pattern | The basic pattern repeated four times | After one operation | After two operations |
Description
Write a program to draw the pattern after n operations. Note that the basic pattern is the result of 0 operations.
When printing, output the character o wherever the pattern contains a square and a space wherever it does not. Trailing spaces on a line may be ignored.
For example, the basic pattern (n=0) should be printed as:
1 | o |
The pattern after two operations (n=2) should be printed as:
1 | o o |
Input
Input a nonnegative integer n, the number of operations.
The data guarantees 0 <= n <= 6.
Output
Print the pattern after n operations.
Special note: To make console output easier, when the number of operations n is odd, rotate the pattern 45 degrees before printing.
Sample Input
1 | 1 |
Sample Output
1 | o o |
Analysis
Once we understand the statement, we can break one operation into two basic steps:
- Expansion: Treat the current pattern as a unit and tile it without overlap into a larger 2x2 pattern.
- Rearrangement: Rearrange the four expanded quadrants with overlap to create a visual effect similar to a 45-degree rotation.
The difficulty in simulating this directly lies in the second step, rearrangement. What is the side length of the new pattern after each rearrangement? At exactly which coordinates should the four quadrants be placed? These parameters do not change linearly; without finding a pattern, there is no clear way to proceed. So the heart of the problem shifts from how to draw the pattern to how to calculate the canvas size and placement coordinates at each step.
My solution takes an iterative approach: start from the basic pattern at n=0, then loop n times, generating the next stage on each iteration. These iterations do not all behave the same way. They use two quite different generation rules depending on whether the iteration number is odd or even.
Algorithm Design and Implementation
My algorithm makes the statement’s abstract “one operation” concrete by alternating expansion on odd-numbered steps with rearrangement on even-numbered steps. A for loop simulates n of these alternating transformations to produce the target pattern.
The Core Idea: Iterative Generation Alternating by Parity
We iterate from i=1 to n in a for loop, where i is the current transformation number.
When
iis odd: the expansion stage- Task: Simply copy and enlarge.
- Implementation: Treat the entire pattern from the previous step (
i-1), calledtemp, as a “tile.” On a new canvas calledpic, of sizea_temp * 2, tile it into the four quadrants ofpicwithout overlap. This step is intuitive: the pattern’s structure stays the same, while its dimensions double.
When
iis even: the rearrangement stage- Task: Carry out the more complicated overlap and contraction.
- Implementation: This step works with the expanded pattern of four quadrants generated at the odd-numbered stage. Rearrange these four “tiles,” placing them at the top, bottom, left, and right of a new canvas to form a cross with overlap in the center.
- The challenge: The new canvas size
a_picand the exact coordinates for the four “tiles” are the key. Through observation and working through the patterns, I found a crucial recurrence.
The Key Discovery: The b[i-3] Recurrence
The parameters in the rearrangement stage are not arbitrary. I found that for transformation i (where i is even and i >= 4), both the new canvas size and the depth of the overlap have a definite mathematical relationship with the canvas side length b[i-3] after transformation i-3.
Here is a hand-drawn diagram from my working notes to make this easier to see:
Diagram guide: The sketch shows successive stages labeled n=1 through n=5. Dashed outlines mark the canvases; the small highlighted squares mark overlap regions used when working out the side-length recurrence.
Calculating the new canvas size
a_pic(theupdate_afunction):
a_pic(i) = a_pic(i-1) + (a_pic(i-1) - b[i-3]) * 2
Here,a_pic(i-1)is the side length from the preceding odd-numbered expansion stage. The formula describes how the new canvas expands from the previous stage according to the historical state at stepi-3.Calculating the placement coordinates (the
drawfunction):
Indraw, the starting-coordinate offsets for placing the “tiles” are also determined byb[i-3]. For example, both theycoordinate of the left tile and thexcoordinate of the top tile involve the key offseta_temp - (b[i - 3] - 1), wherea_tempisa_pic(i-1).
This recurrence is the key to the pattern’s evolution. It turns a complicated geometry problem into a mathematical calculation that can be performed precisely using historical data. The case i=2 needs separate handling, since i-3 is not meaningful then.
Feasibility Analysis
Time complexity:
- The outer loop runs
ntimes. Within each iteration, the core operation isdraw, which essentially copies an array and takesO(a_temp^2). - The canvas side length
a_picgrows roughly like a geometric sequence with common ratio2*sqrt(2)(*2on odd steps and around*sqrt(2)on even steps). For smalln, the growth ofa_picremains manageable, and the total amount of computation is acceptable within the problem’s constraints.
- The outer loop runs
Space complexity:
- We need two two-dimensional arrays,
picandtemp, to store the patterns. Their size is determined by the finala_pic, so space complexity isO(a_pic^2).
- We need two two-dimensional arrays,
Conclusion:
The algorithm turns complicated pattern generation into iterative calculation. Finding the recurrence avoids complicated geometric derivations. The approach is feasible.
Implementation
I built the final accepted code from these ideas. It uses the two arrays pic and temp as a double buffer, alternating between generating and temporarily storing the pattern. The update_a and draw functions implement the odd/even transformation rules precisely.
Expand/collapse the final accepted code
1 |
|
The Pattern at Each Stage
To show the final results of the algorithm and the beauty of the pattern’s evolution, here are the complete outputs from n=0 through n=6.
Expand/collapse the output for n=0
Expand/collapse the output for n=1
Expand/collapse the output for n=2
Expand/collapse the output for n=3
Expand/collapse the output for n=4
Expand/collapse the output for n=5
Expand/collapse the output for n=6
Takeaways
- Break the operation into steps: The first step in solving this problem is to break the statement’s single complicated operation into two alternating steps with clearer logic that is easier to implement: expansion on odd steps and rearrangement on even steps.
- Look for a recurrence: In complicated simulation problems, deriving a closed-form expression directly is often difficult. The breakthrough here was observing and discovering the recurrence that controls pattern size and coordinates—the
b[i-3]relationship—which is much more direct than a purely geometric analysis. - Iteration and double buffering: Building the final pattern step by step from the initial state is a dependable way to solve this type of problem. Using
picandtempas a double buffer makes it easy to generate the next stage from the previous one, avoiding conflicts from modifying the data in place.



