Chapter 7

Home

Refactoring: Cleaner Functions

Writing code that works is step one. Writing code that's easy to read and change is step two. This chapter is about refactoring — restructuring code without changing what it does.

Why Refactor?

In competitive programming, speed matters — but so does correctness. A well-organized solution is easier to debug, easier to modify when you misread the problem, and easier to reuse in future contests.

Before vs After

Here's a typical beginner solution — it works, but everything is in main().

Before — everything in main

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n; cin >> n;
    vector<int> arr(n);
    for (int i = 0; i < n; i++) cin >> arr[i];

    int min_val = arr[0], max_val = arr[0];
    for (int i = 1; i < n; i++) {
        if (arr[i] < min_val) min_val = arr[i];
        if (arr[i] > max_val) max_val = arr[i];
    }
    cout << max_val - min_val << "\n";
    return 0;
}

After — extracted helpers

#include <bits/stdc++.h>
using namespace std;

// One function = one job
vector<int> read_array() {
    int n; cin >> n;
    vector<int> arr(n);
    for (int i = 0; i < n; i++) cin >> arr[i];
    return arr;
}

int find_min(const vector<int>& arr) {
    return *min_element(arr.begin(), arr.end());
}

int find_max(const vector<int>& arr) {
    return *max_element(arr.begin(), arr.end());
}

int main() {
    vector<int> arr = read_array();
    cout << find_max(arr) - find_min(arr) << "\n";
    return 0;
}

Rust Refactoring

Rust's ownership model encourages breaking code into small functions. Each function borrows what it needs.

Before — monolithic main

use std::io::{self, Read};

fn main() {
    let mut input = String::new();
    io::stdin().lock().read_to_string(&mut input).unwrap();
    let nums: Vec<i64> = input
        .split_whitespace()
        .map(|x| x.parse().unwrap())
        .collect();
    let n = nums[0] as usize;
    let arr = &nums[1..=n];
    let min = arr.iter().min().unwrap();
    let max = arr.iter().max().unwrap();
    println!("{}", max - min);
}

After — extracted helpers

use std::io::{self, Read};

fn read_ints() -> Vec<i64> {
    let mut input = String::new();
    io::stdin().lock().read_to_string(&mut input).unwrap();
    input.split_whitespace()
         .map(|x| x.parse().unwrap())
         .collect()
}

fn range(arr: &[i64]) -> i64 {
    arr.iter().max().unwrap()
    - arr.iter().min().unwrap()
}

fn main() {
    let nums = read_ints();
    let n = nums[0] as usize;
    println!("{}", range(&nums[1..=n]));
}

Refactoring Checklist

When you finish a solution, ask yourself:

Key Takeaways

Practice