16: Apply `cargo fmt` and `cargo clippy` to the solution for Rust track exercise "Beer Song". Also add previous versions.

[?]
Aaw9nJhsNmfzFih9mKyNw9mV8CgERXJkRa1kK1Kx3LQH
Aug 22, 2021, 1:19 PM
7NUHCTMKPF5ZPTU3RRTZ6XCEZC7PZVIEOWIMVH4FG2WTWSXGK6IQC

Dependencies

  • [2] 6DOVDD66 15: Add solution for Rust track exercise "Beer Song".
  • [3] QK6XE5XF 13: Add Rust track exercises "Beer Song", "Proverb", "Difference Of Squares", "Sum Of Multiples", "Grains", "Prime Factors", "Armstrong Numbers" and "Reverse String".

Change contents

  • file addition: lib_1.rs (----------)
    [3.37636]
    /*
    Potential improvements:
    * Hard code lengths for verses 0, 1, 2, and the common strings from verses 3 onwards.
    * Calculate extra lengths needed for the common strings from verses 3 onwards using `1 + floor(log10(n))`.
    Notes:
    * http://www.mattmahoney.net/dc/text.html
    * How to create a dictionary: https://groups.google.com/g/comp.compression/c/ZcOTiqck9Tc/m/1KHNFB5ocpoJ.
    * cmix pre-processor converts uppercase characters to lowercase characters prepended with escapes codes which decreases symbol vocabulary but increases input length.
    */
    /* const ALPHABET: [char; 27] = [
    "\n", // 0
    " ", // 1
    ",", // 2
    ".", // 3
    "9", // 4
    "G" // 5
    "N", // 6
    "T", // 7
    "a", // 8
    "b", // 9
    "d" // 10
    "e" // 11
    "f", // 12
    "h", // 13
    "i", // 14
    "k", // 15
    "l", // 16
    "m", // 17
    "n", // 18
    "o", // 19
    "p", // 20
    "r", // 21
    "s", // 22
    "t", // 23
    "u", // 24
    "w", // 25
    "y" // 26
    ]; */
    /* "<n length> bottles of beer on the wall, <n length> bottles of beer.
    Take one down and pass it around, <(n - 1) length> bottles of beer on the wall.
    2 bottles of beer on the wall, 2 bottles of beer.
    Take one down and pass it around, 1 bottle of beer on the wall.
    1 bottle of beer on the wall, 1 bottle of beer.
    Take it down and pass it around, no more bottles of beer on the wall.
    No more bottles of beer on the wall, no more bottles of beer.
    Go to the store and buy some more, 99 bottles of beer on the wall.
    " */
    const DICT: [&str; 24] = [
    "N", // 0
    "o m", // 1
    "ore", // 2
    " bottle", // 3
    "s", // 4
    " of beer", // 5
    " on", // 6
    " th", // 7
    "e ", // 8
    "wall", // 9
    ", ", // 10
    "n", // 11
    ".\n", // 12
    "Go to", // 13
    "st", // 14
    " and ", // 15
    "buy som", // 16
    "m", // 17
    "99", // 18
    "Take", // 19
    " it ", // 20
    "down", // 21
    "pass", // 22
    "around", // 23
    ];
    // const LENGTHS: [usize; 4] = [];
    trait CalculateLength {
    fn calculate_length(&self) -> usize;
    }
    struct Indices<'a>(&'a [usize]);
    impl CalculateLength for Indices<'_> {
    fn calculate_length(&self) -> usize {
    self.0.iter().fold(0, |length, index| length + DICT[*index].len())
    }
    }
    struct IndicesWithPrefixes<'a>(&'a [(&'a str, Indices<'a>)]);
    impl CalculateLength for IndicesWithPrefixes<'_> {
    fn calculate_length(&self) -> usize {
    self.0.iter().fold(0, |a, (prefix, indices)| a + prefix.len() + indices.calculate_length())
    }
    }
    impl IndicesWithPrefixes<'_> {
    fn generate_verse(&self) -> String {
    let mut out = String::with_capacity(self.calculate_length());
    self.0.iter().for_each(|(prefix, indices)| {
    out.push_str(prefix);
    indices.0.iter().for_each(|index| out.push_str(DICT[*index]));
    });
    out
    }
    }
    pub fn verse(n: u32) -> String {
    match n {
    0 => {
    let indices = Indices(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5, 12, 13, 7, 8, 14, 2, 15, 16, 8, 17, 2, 10, 18, 3, 4, 5, 6, 7, 8, 9, 12]);
    let mut out = String::with_capacity(indices.calculate_length());
    indices.0.iter().for_each(|index| out.push_str(DICT[*index]));
    out
    }
    1 => {
    let n_string = n.to_string();
    IndicesWithPrefixes(&[(&n_string, Indices(&[3, 5, 6, 7, 8, 9, 10])), (&n_string, Indices(&[3, 5, 12, 19, 20, 21, 15, 22, 20, 23, 10, 11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12]))]).generate_verse()
    }
    2 => {
    let (n_string, m_string) = (n.to_string(), (n - 1).to_string());
    IndicesWithPrefixes(&[(&n_string, Indices(&[3, 4, 5, 6, 7, 8, 9, 10])), (&n_string, Indices(&[3, 4, 5, 12, 19, 6, 8, 21, 15, 22, 20, 23, 10])), (&m_string, Indices(&[3, 5, 6, 7, 8, 9, 12]))]).generate_verse()
    }
    _ => {
    let (n_string, m_string) = (n.to_string(), (n - 1).to_string());
    IndicesWithPrefixes(&[(&n_string, Indices(&[3, 4, 5, 6, 7, 8, 9, 10])), (&n_string, Indices(&[3, 4, 5, 12, 19, 6, 8, 21, 15, 22, 20, 23, 10])), (&m_string, Indices(&[3, 4, 5, 6, 7, 8, 9, 12]))]).generate_verse()
    }
    }
    }
    pub fn sing(start: u32, end: u32) -> String {
    "".to_string()
    }
  • file addition: lib_0.rs (----------)
    [3.37636]
    /*
    Can nncp be used for this?
    Ways of encoding data for compression: entropy encoding (Huffman, Arithmetic, Asymmetric Numerical Systems), dictionary encoding (Lempel-Ziv), delta encoding.
    How to create a dictionary: https://groups.google.com/g/comp.compression/c/ZcOTiqck9Tc/m/1KHNFB5ocpoJ.
    cmix pre-processor converts uppercase characters to lowercase characters prepended with escapes codes which decreases symbol vocabulary but increases input length.
    */
    /* const ALPHABET: [char; 27] = [
    "\n", // 0
    " ", // 1
    ",", // 2
    ".", // 3
    "9", // 4
    "G" // 5
    "N", // 6
    "T", // 7
    "a", // 8
    "b", // 9
    "d" // 10
    "e" // 11
    "f", // 12
    "h", // 13
    "i", // 14
    "k", // 15
    "l", // 16
    "m", // 17
    "n", // 18
    "o", // 19
    "p", // 20
    "r", // 21
    "s", // 22
    "t", // 23
    "u", // 24
    "w", // 25
    "y" // 26
    ]; */
    /* "<n length> bottles of beer on the wall, <n length> bottles of beer.
    Take one down and pass it around, <(n - 1) length> bottles of beer on the wall.
    2 bottles of beer on the wall, 2 bottles of beer.
    Take one down and pass it around, 1 bottle of beer on the wall.
    1 bottle of beer on the wall, 1 bottle of beer.
    Take it down and pass it around, no more bottles of beer on the wall.
    No more bottles of beer on the wall, no more bottles of beer.
    Go to the store and buy some more, 99 bottles of beer on the wall.
    " */
    const DICT: [&str; 24] = [
    "N", // 0
    "o m", // 1
    "ore", // 2
    " bottle", // 3
    "s", // 4
    " of beer", // 5
    " on", // 6
    " th", // 7
    "e ", // 8
    "wall", // 9
    ", ", // 10
    "n", // 11
    ".\n", // 12
    "Go to", // 13
    "st", // 14
    " and ", // 15
    "buy som", // 16
    "m", // 17
    "99", // 18
    "Take", // 19
    " it ", // 20
    "down", // 21
    "pass", // 22
    "around", // 23
    ];
    // (count, index)
    fn calculate_length(strings: &[(usize, usize)]) -> usize {
    strings.iter().fold(0, |a, (b, c)| a + b * DICT[*c].len())
    }
    /*
    Common string: " bottle of beer on the wall, bottle of beer.\n, bottle of beer on the wall.\n".
    Composed of:
    " bottle": 3 of 3
    " of beer": 3 of 5
    " on": 2 of 6
    " th": 2 of 7
    "e ": 2 of 8
    "wall": 2 of 9
    ", ": 2 of 10
    ".\n": 2 of 12
    */
    fn common_length() -> usize {
    calculate_length(&[(3, 3), (3, 5), (2, 6), (2, 7), (2, 8), (2, 9), (2, 10), (2, 12)])
    }
    fn allocate_string(strings: &[(usize, usize)], more: usize) -> String {
    String::with_capacity(common_length() + calculate_length(strings) + more)
    }
    fn modify_string(mut string: String, prefices_and_indices: &[(&str, &[usize])]) -> String {
    prefices_and_indices.iter().for_each(|(prefix, indices)| {
    string.push_str(prefix);
    indices.iter().for_each(|index| string.push_str(DICT[*index]));
    });
    string
    }
    fn allocate_and_modify_verse(strings: &[(usize, usize)], more: usize, prefices_and_indices: &[(&str, &[usize])]) -> String {
    let mut out = String::with_capacity(common_length() + calculate_length(strings) + more);
    prefices_and_indices.iter().for_each(|(prefix, indices)| {
    out.push_str(prefix);
    indices.iter().for_each(|index| out.push_str(DICT[*index]));
    });
    out
    }
    // TODO: Refactor common code blocks.
    pub fn verse(n: u32) -> String {
    match n {
    // Easy mode: 0 => [0usize, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5, 12, 13, 7, 8, 14, 2, 15, 16, 8, 17, 2, 10, 18, 3, 4, 5, 6, 7, 8, 9, 12].iter().map(|a| DICT[*a]).collect::<String>(),
    0 => {
    /*
    Extras are:
    "N": 1 of 0
    "o m": 2 of 1
    "ore": 4 of 2
    "s": 3 of 4
    "n": 1 of 11
    "Go to": 1 of 13
    " th": 1 of 7
    "e ": 2 of 8
    "st": 1 of 14
    " and ": 1 of 15
    "buy som": 1 of 16
    "m": 1 of 17
    "99": 1 of 18
    */
    // assert_eq!("No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n".len(), common_length + calculate_length(&[(1, 0), (2, 1), (4, 2), (3, 4), (1, 11), (1, 13), (1, 7), (2, 8), (1, 14), (1, 15), (1, 16), (1, 17), (1, 18)]));
    allocate_and_modify_verse(&[(1, 0), (2, 1), (4, 2), (3, 4), (1, 11), (1, 13), (1, 7), (2, 8), (1, 14), (1, 15), (1, 16), (1, 17), (1, 18)], 0, &[(&"", &[0usize, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5, 12, 13, 7, 8, 14, 2, 15, 16, 8, 17, 2, 10, 18, 3, 4, 5, 6, 7, 8, 9, 12])])
    }
    1 => {
    /*
    Extras are:
    n: 2
    "Take": 1 of 19
    " it ": 2 of 20
    "down": 1 of 21
    " and ": 1 of 15
    "pass": 1 of 22
    "around": 1 of 23
    "n": 1 of 11
    "o m": 1 of 1
    "ore": 1 of 2
    "s": 1 of 4
    */
    let n_string = n.to_string();
    // assert_eq!("1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n".len(), common_length + 2 + calculate_length(&[(1, 19), (2, 20), (1, 21), (1, 15), (1, 22), (1, 23), (1, 11), (1, 1), (1, 2), (1, 4)]));
    allocate_and_modify_verse(&[(1, 19), (2, 20), (1, 21), (1, 15), (1, 22), (1, 23), (1, 11), (1, 1), (1, 2), (1, 4)], 2, &[(&n_string, &[3usize, 5, 6, 7, 8, 9, 10]), (&n_string, &[3usize, 5, 12, 19, 20, 21, 15, 22, 20, 23, 10, 11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12])])
    }
    2 => {
    /*
    Extras are:
    n: 2
    "s": 2 of 4
    "Take": 1 of 19
    " on": 1 of 6
    "e ": 1 of 8
    "down": 1 of 21
    " and ": 1 of 15
    "pass": 1 of 22
    " it": 1 of 20
    "around": 1 of 23
    n - 1: 1
    */
    let (n_string, m_string) = (n.to_string(), (n - 1).to_string());
    // assert_eq!("2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n".len(), common_length + 2 * n_string.len() + calculate_length(&[(2, 4), (1, 19), (1, 6), (1, 8), (1, 21), (1, 15), (1, 22), (1, 20), (1, 23)]) + m_string.len());
    allocate_and_modify_verse(&[(2, 4), (1, 19), (1, 6), (1, 8), (1, 21), (1, 15), (1, 22), (1, 20), (1, 23)], 2 * n_string.len() + m_string.len(), &[(&n_string, &[3usize, 4, 5, 6, 7, 8, 9, 10]), (&n_string, &[3usize, 4, 5, 12, 19, 6, 8, 21, 15, 22, 20, 23, 10]), (&m_string, &[3, 5, 6, 7, 8, 9, 12])])
    }
    _ => {
    /*
    Extras are:
    n: 2
    "s": 3 of 4
    "Take": 1 of 19
    " on": 1 of 6
    "e ": 1 of 8
    "down": 1 of 21
    " and ": 1 of 15
    "pass": 1 of 22
    " it": 1 of 20
    "around": 1 of 23
    n - 1: 1
    */
    let (n_string, m_string) = (n.to_string(), (n - 1).to_string());
    // assert_eq!("3 bottles of beer on the wall, 3 bottles of beer.\nTake one down and pass it around, 2 bottles of beer on the wall.\n".len(), common_length + 2 * n_string.len() + calculate_length(&[(3, 4), (1, 19), (1, 6), (1, 8), (1, 21), (1, 15), (1, 22), (1, 20), (1, 23)]) + m_string.len());
    allocate_and_modify_verse(&[(3, 4), (1, 19), (1, 6), (1, 8), (1, 21), (1, 15), (1, 22), (1, 20), (1, 23)], 2 * n_string.len() + m_string.len(), &[(&n_string, &[3usize, 4, 5, 6, 7, 8, 9, 10]), (&n_string, &[3usize, 4, 5, 12, 19, 6, 8, 21, 15, 22, 20, 23, 10]), (&m_string, &[3, 4, 5, 6, 7, 8, 9, 12])])
    }
    }
    }
    pub fn sing(start: u32, end: u32) -> String {
    "".to_string()
    // (start..=end).for_each(verse)
    }
  • replacement in rust/beer-song/src/lib.rs at line 4
    [2.1592][2.1592:1657]()
    "N", // 0
    "o m", // 1
    "ore", // 2
    " bottle", // 3
    "s", // 4
    [2.1592]
    [2.1657]
    "N", // 0
    "o m", // 1
    "ore", // 2
    " bottle", // 3
    "s", // 4
  • replacement in rust/beer-song/src/lib.rs at line 10
    [2.1675][2.1675:1931]()
    " on", // 6
    " th", // 7
    "e ", // 8
    "wall", // 9
    ", ", // 10
    "n", // 11
    ".\n", // 12
    "Go to", // 13
    "st", // 14
    " and ", // 15
    "buy som", // 16
    "m", // 17
    "99", // 18
    "Take", // 19
    " it ", // 20
    "down", // 21
    "pass", // 22
    "around", // 23
    [2.1675]
    [2.1931]
    " on", // 6
    " th", // 7
    "e ", // 8
    "wall", // 9
    ", ", // 10
    "n", // 11
    ".\n", // 12
    "Go to", // 13
    "st", // 14
    " and ", // 15
    "buy som", // 16
    "m", // 17
    "99", // 18
    "Take", // 19
    " it ", // 20
    "down", // 21
    "pass", // 22
    "around", // 23
  • replacement in rust/beer-song/src/lib.rs at line 44
    [2.2467][2.2467:2494]()
    } else { LENGTHS[n] } );
    [2.2467]
    [2.2494]
    } else {
    LENGTHS[n]
    });
  • replacement in rust/beer-song/src/lib.rs at line 59
    [2.2721][2.2721:2903]()
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5, 12, 13, 7, 8, 14, 2, 15, 16, 8, 17, 2, 10, 18, 3, 4, 5, 6, 7, 8, 9, 12].iter().for_each(|index| out.push_str(DICT[*index]));
    [2.2721]
    [2.2903]
    [
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5, 12, 13, 7, 8, 14, 2, 15, 16,
    8, 17, 2, 10, 18, 3, 4, 5, 6, 7, 8, 9, 12,
    ]
    .iter()
    .for_each(|index| out.push_str(DICT[*index]));
  • replacement in rust/beer-song/src/lib.rs at line 69
    [2.2956][2.2956:3131]()
    IndicesWithPrefixes(&[(&n_string, &[3, 5, 6, 7, 8, 9, 10]), (&n_string, &[3, 5, 12, 19, 20, 21, 15, 22, 20, 23, 10, 11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12])]).generate_verse(n)
    [2.2956]
    [2.3131]
    IndicesWithPrefixes(&[
    (&n_string, &[3, 5, 6, 7, 8, 9, 10]),
    (
    &n_string,
    &[
    3, 5, 12, 19, 20, 21, 15, 22, 20, 23, 10, 11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12,
    ],
    ),
    ])
    .generate_verse(n)
  • replacement in rust/beer-song/src/lib.rs at line 82
    [2.3212][2.3212:3398]()
    IndicesWithPrefixes(&[(&n_string, &[3, 4, 5, 6, 7, 8, 9, 10]), (&n_string, &[3, 4, 5, 12, 19, 6, 8, 21, 15, 22, 20, 23, 10]), (&m_string, &[3, 5, 6, 7, 8, 9, 12])]).generate_verse(n)
    [2.3212]
    [2.3398]
    IndicesWithPrefixes(&[
    (&n_string, &[3, 4, 5, 6, 7, 8, 9, 10]),
    (&n_string, &[3, 4, 5, 12, 19, 6, 8, 21, 15, 22, 20, 23, 10]),
    (&m_string, &[3, 5, 6, 7, 8, 9, 12]),
    ])
    .generate_verse(n)
  • replacement in rust/beer-song/src/lib.rs at line 91
    [2.3479][2.3479:3668]()
    IndicesWithPrefixes(&[(&n_string, &[3, 4, 5, 6, 7, 8, 9, 10]), (&n_string, &[3, 4, 5, 12, 19, 6, 8, 21, 15, 22, 20, 23, 10]), (&m_string, &[3, 4, 5, 6, 7, 8, 9, 12])]).generate_verse(n)
    [2.3479]
    [2.3668]
    IndicesWithPrefixes(&[
    (&n_string, &[3, 4, 5, 6, 7, 8, 9, 10]),
    (&n_string, &[3, 4, 5, 12, 19, 6, 8, 21, 15, 22, 20, 23, 10]),
    (&m_string, &[3, 4, 5, 6, 7, 8, 9, 12]),
    ])
    .generate_verse(n)
  • replacement in rust/beer-song/src/lib.rs at line 103
    [2.3819][2.3819:4167]()
    let (a, b) = ((10_f64.powi(start_digits.try_into().unwrap()) - 1.0) as usize, 10_f64.powi((end_digits - 1).try_into().unwrap()) as usize);
    (integer_length(a + 1)..=integer_length(b - 1)).fold(0, |acc, elem| acc + 9 * elem * (10_f64.powi((elem - 1).try_into().unwrap()) as usize)) + ((a - start + 1) * start_digits) + ((end - b + 1) * end_digits)
    [2.3819]
    [3.37741]
    let (a, b) = (
    (10_f64.powi(start_digits.try_into().unwrap()) - 1.0) as usize,
    10_f64.powi((end_digits - 1).try_into().unwrap()) as usize,
    );
    (integer_length(a + 1)..=integer_length(b - 1)).fold(0, |acc, elem| {
    acc + 9 * elem * (10_f64.powi((elem - 1).try_into().unwrap()) as usize)
    }) + ((a - start + 1) * start_digits)
    + ((end - b + 1) * end_digits)
  • replacement in rust/beer-song/src/lib.rs at line 129
    [2.4537][2.4537:4789]()
    (_, _) => (s as usize - 2) * LENGTHS[3] + integer_range_length(3, s as usize) + match e {
    0 => LENGTHS[0] + LENGTHS[1] + LENGTHS[2],
    1 => LENGTHS[1] + LENGTHS[2],
    2 => LENGTHS[2],
    _ => 0,
    },
    } + ((s - e) as usize)
    [2.4537]
    [2.4789]
    (_, _) => {
    (s as usize - 2) * LENGTHS[3]
    + integer_range_length(3, s as usize)
    + match e {
    0 => LENGTHS[0] + LENGTHS[1] + LENGTHS[2],
    1 => LENGTHS[1] + LENGTHS[2],
    2 => LENGTHS[2],
    _ => 0,
    }
    }
    } + ((s - e) as usize),
  • replacement in rust/beer-song/src/lib.rs at line 144
    [2.4875][2.4875:4900]()
    out.push_str("\n");
    [2.4875]
    [2.4900]
    out.push('\n');
  • replacement in rust/beer-song/src/lib.rs at line 150
    [2.5016][2.5016:5041]()
    out.push_str("\n");
    [2.5016]
    [2.5041]
    out.push('\n');