Question

Reverse for Loops in Rust: Iterating from 100 Down to 1

rustfor-loop

Question

I want to print FizzBuzz in reverse order in Rust, counting from 100 down to 1.

I tried this code:

fn main() {
    for n in std::iter::range_step(100u, 0, -1) {
        if n % 15 == 0 {
            println!("fizzbuzz");
        } else if n % 3 == 0 {
            println!("fizz");
        } else if n % 5 == 0 {
            println!("buzz");
        } else {
            println!("{}", n);
        }
    }
}

The code compiles, but it does not print anything. How can I correctly iterate from 100 down to 1 in Rust?

Short Answer

By the end of this page, you will understand how reverse iteration works in Rust, why some descending loop attempts produce no output, and how to correctly loop from a larger number down to a smaller one using ranges and .rev(). You will also see practical examples, common mistakes, and a small reverse-counting mini-project.

Concept

In Rust, a for loop works by iterating over an iterator. That means the important question is not just “what numbers do I want,” but also “what iterator produces them?”

For counting upward, Rust ranges are straightforward:

for n in 1..=5 {
    println!("{}", n);
}

This prints 1 through 5.

For counting downward, Rust does not usually use a negative step directly in a range expression. Instead, the common Rust style is:

  1. Create a normal forward range.
  2. Reverse it with .rev().

Example:

for n in (1..=5).rev() {
    println!("{}", n);
}

This prints 5 down to 1.

This matters because Rust's iterator system is designed to be explicit, safe, and composable. Rather than special loop syntax for every situation, Rust encourages you to build the iterator you want. Reversing an iterator is one of the most common tools for this.

In your original code, the issue is that the iterator setup did not actually produce values in the way you expected. In modern Rust, the clearest and most idiomatic solution is to use a range with .rev().

Mental Model

Think of a Rust range like a list of pages in a book.

  • 1..=5 means: pages 1, 2, 3, 4, 5
  • .rev() means: read those pages from the back to the front

So instead of asking Rust to “walk backward with a negative step,” you usually tell it:

  • “Make the normal sequence first”
  • “Now reverse it”

That is much like stacking numbered cards from 1 to 100, then flipping the stack over and reading from the top.

Take Quiz

Syntax and Examples

The most common way to write a reverse loop in Rust is:

for n in (start..=end).rev() {
    // use n
}

Example: count from 5 down to 1

fn main() {
    for n in (1..=5).rev() {
        println!("{}", n);
    }
}

Output:

5
4
3
2
1

Example: reverse FizzBuzz from 100 to 1

fn main() {
    for n in (1..=100).rev() {
        if n % 15 == 0 {
            println!("fizzbuzz");
        } else if n % 3 == 0 {
            println!("fizz");
        } else if n % 5 == 0 {
            println!("buzz");
        } else {
            println!("{}", n);
        }
    }
}

Exclusive vs inclusive ranges

Rust has two very common range forms:

1..5   // 1, 2, 3, 4
1..=5  // 1, 2, 3, 4, 5

If you want to include 100 and 1, use an inclusive range and reverse it:

for n in (1..=100).rev() {
    println!("{}", n);
}

Alternative with while

You can also count down manually:

fn main() {
    let mut n = 100;

    while n >= 1 {
        println!("{}", n);
        n -= 1;
    }
}

This works, but for simple iteration, for with a range is usually cleaner and more idiomatic in Rust.

Step by Step Execution

Consider this code:

fn main() {
    for n in (1..=5).rev() {
        println!("{}", n);
    }
}

Here is what happens step by step:

  1. Rust creates the range 1..=5.

    • This represents the values 1, 2, 3, 4, 5.
  2. .rev() is called on that range.

    • The iterator is reversed.
    • Now it will yield 5, 4, 3, 2, 1.
  3. The for loop starts.

    • First iteration: n = 5
    • println! prints 5
  4. Second iteration:

    • n = 4
    • println! prints 4
  5. The loop continues:

    • n = 3
    • n = 2
    • n = 1
  6. After 1, the iterator has no more values.

    • The loop ends.

Trace table

IterationValue of nPrinted
155
244
333
422
511

Now apply the same idea to 1..=100, and you get a clean reverse loop from 100 down to 1.

Real World Use Cases

Reverse iteration appears in many real programs, not just counting examples.

Common practical uses

  • Displaying recent items first

    • Show newest notifications before older ones.
  • Countdowns

    • Timers, launch countdowns, game start sequences.
  • Processing collections from the end

    • Some algorithms inspect the last items first.
  • Undo history

    • Traverse recent actions in reverse order.
  • Log analysis

    • Read recent events before older records.

Example: countdown

fn main() {
    for seconds in (1..=10).rev() {
        println!("{}...", seconds);
    }
    println!("Go!");
}

Example: iterating a vector in reverse

fn main() {
    let messages = vec!["old", "middle", "new"];

    for message in messages.iter().rev() {
        println!("{}", message);
    }
}

This prints the newest item first if the vector is stored oldest-to-newest.

Take Quiz

Real Codebase Usage

In real Rust codebases, developers often use reverse iteration with iterator adapters rather than manual index manipulation.

Common patterns

Reverse a range

for i in (0..10).rev() {
    println!("{}", i);
}

Useful for countdowns or reverse traversal.

Reverse a collection iterator

let items = vec![1, 2, 3, 4];
for item in items.iter().rev() {
    println!("{}", item);
}

This avoids indexing and is safer.

Combine with filters or mapping

let nums = vec![1, 2, 3, 4, 5, 6];
for n in nums.iter().rev().filter(|n| **n % 2 == 0) {
    println!("{}", n);
}

This is common in data processing pipelines.

Guarding boundaries clearly

When reverse loops involve endpoints, developers often choose inclusive ranges so the intent is obvious:

for id in (1..=max_id).rev() {
    // process from latest to earliest
}

This is easier to read than custom stepping logic.

Why this style is preferred

  • It is idiomatic Rust.
  • It works well with the iterator ecosystem.
  • It reduces off-by-one mistakes.
  • It avoids unsafe or confusing manual control flow.

Common Mistakes

1. Forgetting that .. excludes the end value

Broken example:

for n in (1..100).rev() {
    println!("{}", n);
}

This prints 99 down to 1, not 100 down to 1.

Correct version:

for n in (1..=100).rev() {
    println!("{}", n);
}

2. Expecting a negative step in modern range syntax

Beginners sometimes expect something like this to work:

// Not valid modern Rust range syntax for descending loops
for n in 100..1 {
    println!("{}", n);
}

A forward range where the start is larger than the end yields no values.

Use:

for n in (1..=100).rev() {
    println!("{}", n);
}

3. Missing parentheses before .rev()

Broken example:

for n in 1..=100.rev() {
    println!("{}", n);
}

The method must be called on the whole range, not just on 100.

Correct:

for n in (1..=100).rev() {
    println!("{}", n);
}

4. Using while and forgetting to update the counter

Broken example:

let mut n = 100;
while n >= 1 {
    println!("{}", n);
}

This causes an infinite loop because n never changes.

Correct:

let mut n = 100;
while n >= 1 {
    println!("{}", n);
    n -= 1;
}

5. Off-by-one errors at the lower bound

Broken example:

let mut n = 100;
while n > 1 {
    println!("{}", n);
    n -= 1;
}

This never prints 1.

Correct:

let mut n = 100;
while n >= 1 {
    println!("{}", n);
    n -= 1;
}

Comparisons

ApproachExampleBest forNotes
for with reversed rangefor n in (1..=100).rev()Simple reverse countingMost idiomatic for numeric countdowns
while loopwhile n >= 1Custom loop controlMore manual, easier to make mistakes
Reverse collection iteratoritems.iter().rev()Traversing arrays, vectors, slicesPreferred over manual indexing
Forward rangefor n in 1..=100Normal ascending iterationNot for descending order unless combined with .rev()

for vs while

Featureforwhile
ReadabilityHigh for simple iterationGood for custom conditions
SafetyFewer manual mistakesMore room for infinite loops
Idiomatic RustVery commonUsed when more control is needed
Best use caseIterating known sequencesComplex stopping logic

Inclusive vs exclusive ranges

SyntaxIncludes end?Example values
1..5No1, 2, 3, 4
1..=5Yes1, 2, 3, 4, 5

For looping from 100 down to 1, 1..=100 is usually the correct starting range before reversing.

Take Quiz

Cheat Sheet

// Count up
for n in 1..=5 {
    println!("{}", n);
}

// Count down
for n in (1..=5).rev() {
    println!("{}", n);
}

// Exclusive upper bound
for n in (1..5).rev() {
    println!("{}", n); // prints 4, 3, 2, 1
}

// Manual countdown
let mut n = 5;
while n >= 1 {
    println!("{}", n);
    n -= 1;
}

Quick rules

  • Use .. for an exclusive end.
  • Use ..= for an inclusive end.
  • Use .rev() to reverse a range or iterator.
  • Put parentheses around the range before calling .rev().
  • Prefer for over while when iterating a known sequence.

Common pattern

for n in (start..=end).rev() {
    // descending loop
}

Example for this topic

for n in (1..=100).rev() {
    println!("{}", n);
}

FAQ

How do I loop backwards in Rust?

Use a normal range and reverse it with .rev():

for n in (1..=10).rev() {
    println!("{}", n);
}

Why does 100..1 not work the way I expect?

Rust ranges normally move forward. If the start is greater than the end, the range produces no values.

What is the difference between .. and ..= in Rust?

  • .. excludes the end value
  • ..= includes the end value

So 1..100 stops at 99, while 1..=100 includes 100.

Is .rev() only for ranges?

No. It also works on many iterators, such as vectors, slices, and other iterable collections.

Should I use for or while for reverse loops?

Use for when you are iterating over a known range. Use while when you need more manual control.

How do I print FizzBuzz from 100 down to 1 in Rust?

Use:

for n in (1..=100).rev() {
    // fizzbuzz logic
}

Do I need parentheses around the range before .rev()?

Yes, usually:

for n in (1..=100).rev() {
    println!("{}", n);
}
Take Quiz

Mini Project

Description

Build a small Rust program that prints a reverse countdown with custom messages. This project helps you practice descending for loops, inclusive ranges, and conditional logic together. It is similar to reverse FizzBuzz but simpler to modify and test.

Goal

Create a Rust program that counts from 10 down to 1 and prints special labels for certain numbers.

Requirements

  • Count from 10 down to 1 using a for loop.
  • Use an inclusive range and reverse it.
  • Print even for even numbers.
  • Print multiple of 3 for numbers divisible by 3.
  • Print the number itself for all other values.
Take Quiz

Keep learning

Related questions

View more