Skip to content

Instantly share code, notes, and snippets.

@erochest
Last active Apr 18, 2018
Embed
What would you like to do?
Print 7-digit numbers
#![feature(test)]
#[cfg(test)]
extern crate spectral;
extern crate test;
/// Takes a string containing a number and increments it in place. Returns whether the operation
/// was successful. The only time it isn't successful is if the input is empty or the operation
/// overflows.
///
/// ```rust
/// use print_numbers::increment_string;
///
/// let mut number = String::from("000");
///
/// assert!(increment_string(&mut number));
/// assert_eq!(number, String::from("001"));
///
/// for _ in 0..10 {
/// assert!(increment_string(&mut number));
/// }
/// assert_eq!(number, String::from("011"));
/// ```
pub fn increment_string(n: &mut str) -> bool {
if n.len() == 0 {
return false;
}
unsafe {
let n_bytes = n.as_bytes_mut();
let mut i = n_bytes.len() - 1;
while n_bytes[i] == b'9' {
if i == 0 {
return false;
}
n_bytes[i] = b'0';
i -= 1;
}
n_bytes[i] += 1;
}
true
}
#[cfg(test)]
mod tests {
use super::*;
use spectral::prelude::*;
#[test]
fn increments_the_right_digit() {
let mut buffer = String::from("000");
assert_that(&increment_string(&mut buffer)).is_true();
assert_that(&buffer).is_equal_to(String::from("001"));
assert_that(&increment_string(&mut buffer)).is_true();
assert_that(&buffer).is_equal_to(String::from("002"));
assert_that(&increment_string(&mut buffer)).is_true();
assert_that(&buffer).is_equal_to(String::from("003"));
}
#[test]
fn carries() {
let mut buffer = String::from("009");
assert_that(&increment_string(&mut buffer)).is_true();
assert_that(&buffer).is_equal_to(String::from("010"));
let mut buffer = String::from("099");
assert_that(&increment_string(&mut buffer)).is_true();
assert_that(&buffer).is_equal_to(String::from("100"));
let mut buffer = String::from("109");
assert_that(&increment_string(&mut buffer)).is_true();
assert_that(&buffer).is_equal_to(String::from("110"));
let mut buffer = String::from("199");
assert_that(&increment_string(&mut buffer)).is_true();
assert_that(&buffer).is_equal_to(String::from("200"));
}
#[test]
fn returns_false_when_overflows() {
let mut buffer = String::from("998");
assert_that(&increment_string(&mut buffer)).is_true();
assert_that(&increment_string(&mut buffer)).is_false();
}
#[test]
fn returns_false_on_empty_string() {
let mut buffer = String::from("");
assert_that(&increment_string(&mut buffer)).is_false();
}
}
#[cfg(test)]
mod bench {
mod iterate {
use super::super::*;
use test::{black_box, Bencher};
#[bench]
fn bench_iterate_format(b: &mut Bencher) {
b.iter(|| {
(0..1_000_000)
.into_iter()
.map(|i| format!("{:07}", i))
.for_each(|n| {
black_box(n);
()
});
});
}
#[bench]
fn bench_for_format(b: &mut Bencher) {
b.iter(|| {
for i in 0..1_000_000 {
black_box(format!("{:07}", &i));
}
});
}
#[bench]
fn bench_mutate_string(b: &mut Bencher) {
b.iter(|| {
let mut buffer = String::from("0000000");
while increment_string(&mut buffer) {
black_box(&buffer);
}
});
}
#[bench]
fn bench_mutate_clone(b: &mut Bencher) {
b.iter(|| {
let mut buffer = String::from("0000000");
while increment_string(&mut buffer) {
black_box(buffer.clone());
}
});
}
}
}
test bench::iterate::bench_for_format ... bench: 115,474,903 ns/iter (+/- 7,441,441)
test bench::iterate::bench_iterate_format ... bench: 114,379,497 ns/iter (+/- 8,669,838)
test bench::iterate::bench_mutate_clone ... bench: 337,568,166 ns/iter (+/- 24,854,535)
test bench::iterate::bench_mutate_string ... bench: 10,936,343 ns/iter (+/- 592,779)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment