How to print 1 22 333 in Python

Discover multiple ways to print the 1 22 333 number pattern in Python. Get tips, see applications, and learn to debug common errors.

How to print 1 22 333 in Python
Published on: 
Tue
Apr 21, 2026
Updated on: 
Wed
Apr 22, 2026
The Replit Team

Number patterns like 1 22 333 are a common exercise for Python beginners. This task helps you understand loops and string manipulation, which are fundamental programming concepts.

In this article, we'll explore various techniques to solve this problem. You'll find practical tips, see real-world applications, and get advice to debug your code to help you master this pattern.

Basic pattern printing with a for loop

for i in range(1, 4):
print(str(i) * i, end=" ")--OUTPUT--1 22 0333

This solution leverages a neat Python feature—string multiplication. The for loop iterates from 1 to 3, and in each step, the expression str(i) * i does the heavy lifting. It converts the loop variable i to a string and repeats it that many times.

  • When i is 1, you get "1".
  • When i is 2, you get "22".
  • When i is 3, you get "333".

The end=" " argument in the print() function is also crucial. It replaces the default newline character with a space, which strings the pattern together on a single line.

Basic techniques

While the for loop is a solid start, you can write more idiomatic Python using techniques like the join() method, list comprehensions, or even f-strings.

Using string multiplication with join()

numbers = [str(i) * i for i in range(1, 4)]
print(" ".join(numbers))--OUTPUT--1 22 0333

This approach is a bit more idiomatic because it separates the logic into two clear steps. First, a list comprehension generates all the necessary string segments and stores them in a list.

  • The expression [str(i) * i for i in range(1, 4)] efficiently builds the list ['1', '22', '333'].
  • Then, the join() method is called on a space character to concatenate the list's elements into a single, space-separated string for printing.

Using list comprehension with inline generation

print(" ".join(str(i) * i for i in range(1, 4)))--OUTPUT--1 22 0333

This method refines the list comprehension approach by generating the pattern segments directly inside the join() function. It's a more memory-efficient way to achieve the same result, especially for larger ranges.

  • The code uses a generator expression—(str(i) * i for i in range(1, 4))—which produces each string segment on the fly.
  • Because you aren't storing the entire list in memory first, this technique is often faster and more efficient.

Using f-strings to build the pattern

result = ""
for i in range(1, 4):
result += f"{i}" * i + " "
print(result.strip())--OUTPUT--1 22 0333

This approach builds the pattern piece by piece inside a loop. An empty string, result, is initialized first. Then, the loop uses an f-string, f"{i}", to convert the current number to a string, which is then multiplied and appended to result along with a space.

  • The += operator handles this cumulative string building.
  • Finally, result.strip() removes the extra space added at the end of the last loop iteration before printing the final pattern.

Advanced techniques

While the basic methods work well, advanced techniques like lambda functions, recursion, and generators offer more power and control over your code.

Using a lambda function for reusable patterns

pattern = lambda n: " ".join(str(i) * i for i in range(1, n+1))
print(pattern(3))--OUTPUT--1 22 0333

A lambda function is a concise way to create small, single-expression functions. We assign one to the variable pattern, which makes the logic reusable. You can now generate the pattern up to any number by simply calling pattern(n).

  • The function takes an integer n as its input to define the pattern's length.
  • It uses the familiar generator expression and join() method to construct the final string.
  • This approach is great for simple functions where a full def statement feels like overkill.

Using recursion to build the pattern

def pattern_recursive(n, current=1):
if current > n:
return ""
return str(current) * current + (" " + pattern_recursive(n, current+1) if current < n else "")

print(pattern_recursive(3))--OUTPUT--1 22 0333

This recursive solution works by having the pattern_recursive function call itself to build the sequence piece by piece. The function stops when the current counter is greater than n—this is the base case that prevents an infinite loop.

  • In each step, the function generates the current number segment, such as str(2) * 2.
  • It then calls itself again with an incremented counter, current + 1, to generate the next segment.
  • A conditional expression adds a space only if it's not the last number, which neatly avoids a trailing space.

Using generators for memory efficiency

def pattern_generator(n):
for i in range(1, n+1):
yield str(i) * i

print(" ".join(pattern_generator(3)))--OUTPUT--1 22 0333

A generator function, like pattern_generator, offers a highly memory-efficient way to create sequences. Instead of building a full list in memory, it produces values one by one as they're requested.

  • The yield keyword is the key. It pauses the function and sends back a value.
  • When the join() method asks for the next item, the function resumes where it left off.
  • This "lazy evaluation" is perfect for large datasets where storing everything at once would be wasteful.

Move faster with Replit

Replit is an AI-powered development platform where all Python dependencies are pre-installed, so you can skip setup and start coding instantly. You can go from practicing techniques to building a complete product with Agent 4, which handles everything from code and databases to deployment, directly from your description.

Instead of just piecing together code snippets, you can build a complete application that uses these same concepts:

  • A test data generator that creates patterned strings, like user-1-aa-bbb, for validating input fields.
  • A log formatter that processes a stream of events and joins them into a single, space-separated line for easier debugging.
  • A custom ID creator that generates a sequence of unique identifiers by repeating numbers or characters based on a given length.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

Even simple patterns can trip you up; here are some common mistakes to watch out for when coding this sequence in Python.

  • Forgetting to convert numbers to strings when using the * operator
  • The multiplication operator (*) behaves differently for numbers and strings. If you try 2 * 2, you get 4, but if you try "2" * 2, you get "22". A common mistake is forgetting to convert the number to a string first, which results in a TypeError.
  • Off-by-one errors when using range() for patterns
  • The range() function can be tricky because its stop value is exclusive. For example, range(1, 4) generates numbers 1, 2, and 3, but stops before reaching 4. It's easy to get the range wrong and either miss the last number or include an extra one.
  • Handling newlines in multi-row pattern printing
  • While printing on a single line is straightforward, creating multi-row patterns adds complexity. You need to manage when to print a space and when to start a new line, which often requires nested loops and careful placement of your print() statements.

Forgetting to convert numbers to strings when using the * operator

Python's multiplication operator (*) behaves differently with numbers versus strings. A common mistake is forgetting to convert a number to a string before multiplication. This results in mathematical calculation instead of string repetition, which breaks the intended pattern.

The code below demonstrates this error in action.

for i in range(1, 4):
print(i * i, end=" ") # This multiplies the number by itself

The code performs mathematical multiplication with i * i, producing 1 4 9 instead of the desired pattern. The corrected version below shows how to achieve the intended string repetition.

for i in range(1, 4):
print(str(i) * i, end=" ") # Convert to string first for repetition

The fix is to explicitly convert the number to a string using the str() function before multiplying. When you use str(i) * i, you're telling Python to repeat the string representation of the number, not perform math.

This ensures you get the correct output, like "22" instead of 4. You'll want to watch for this whenever you're generating patterns or formatted strings inside a loop where you need repetition instead of calculation.

Off-by-one errors when using range() for patterns

Off-by-one errors are a classic pitfall, especially with Python's range() function. Because its stop value is exclusive, it's easy to get your loop's boundaries wrong, causing your pattern to end too soon. The code below shows this common mistake in action.

# Trying to print pattern for numbers 1 to 5
for i in range(1, 5): # Incorrect range
print(str(i) * i, end=" ")

The code intends to print up to 5, but range(1, 5) stops at 4. As a result, the loop terminates one step too early, leaving the pattern incomplete. The corrected code below demonstrates the simple fix.

# Printing pattern for numbers 1 to 5
for i in range(1, 6): # Correct range includes upper bound
print(str(i) * i, end=" ")

The fix is to increase the stop value in the range() function by one. Using range(1, 6) ensures the loop runs up to and includes the number 5, as the function generates numbers up to but not including the stop value. You'll want to watch for this whenever you're defining loops for patterns or data processing, as it's a frequent source of bugs for both new and experienced developers.

Handling newlines in multi-row pattern printing

While single-line patterns are straightforward, creating multi-row patterns adds complexity. You need to control exactly when to print a space versus when to start a new line, which often requires nested loops and careful placement of your print() statements.

The code below demonstrates what happens when line breaks are missed.

# Attempting to print a square pattern
for i in range(1, 4):
for j in range(1, 4):
print(i, end="")

The print() function is called with end="", which prevents it from ever adding a line break. This mashes all the numbers together onto a single line instead of creating a structured pattern. Check out the corrected code below.

# Correctly printing a square pattern
for i in range(1, 4):
for j in range(1, 4):
print(i, end="")
print() # Add newline after each row

The solution is an empty print() call placed strategically after the inner loop. While the inner loop builds a row of numbers without line breaks, the outer print() executes once per row to add the necessary newline. You'll need this pattern anytime you're working with nested loops to create structured, multi-line text like grids or ASCII art. It gives you precise control over when to break to a new line.

Real-world applications

Beyond debugging simple patterns, this logic is surprisingly useful for building visual elements like terminal progress bars and ASCII art pyramids.

Building a terminal progress bar using the * operator

You can use the same string multiplication technique with the * operator to create a dynamic terminal progress bar that visually represents task completion.

def progress_bar(progress, total):
length = 20
filled = "█" * int(length * progress // total)
empty = "-" * (length - len(filled))
print(f"Progress: [{filled}{empty}] {progress}/{total}")

for i in range(0, 101, 25):
progress_bar(i, 100)

The progress_bar function creates a text-based visual by calculating the ratio of task completion. It uses this ratio to determine how many filled characters to display within a fixed length of 20.

  • The number of filled blocks () is found by scaling the progress against the total using integer division (//).
  • The remaining space is then filled with empty characters (-).
  • An f-string assembles these parts into a single line, showing the bar and the numeric progress, which the for loop updates.

Creating ASCII art pyramids with string multiplication

String multiplication is also perfect for building geometric shapes like pyramids, where each row requires a calculated number of spaces and characters.

def pyramid(height):
for i in range(1, height + 1):
spaces = " " * (height - i)
stars = "*" * (2 * i - 1)
print(spaces + stars)

pyramid(5)

The pyramid function builds the shape line by line using a for loop. For each row, represented by i, it performs two key calculations using string multiplication.

  • First, it determines the correct number of leading spaces with height - i. This makes the pyramid narrower at the top and wider at the bottom, effectively centering it.
  • Second, it generates the stars for the current row. The formula 2 * i - 1 produces an odd number of stars (1, 3, 5, etc.), which creates the pyramid's angled sides.

Get started with Replit

Now, turn these concepts into a real tool. Describe what you want to Replit Agent, like "build a terminal-based countdown timer using repeated blocks" or "create a text banner generator from a user's input."

Replit Agent writes the code, tests for errors, and deploys the app directly from your instructions. Start building with Replit and watch your project take shape.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.