Sorry if this is a stupid question, but I’m struggling with what I think is ownership in rust.

I’m completely new to rust, but have done low level languages before so I know the concept of pointers pretty well. However, this rust ownership I can’t quite wrap my head around.

I’m trying to refactor my solution to AoC Day 4 Part 2 using a struct reference instead of a stand-alone vector.

The error I’m getting, and can’t figure out is in the process function at line

cards.iter_mut().for_each(|card | {

The error is

cannot borrow cards as mutable more than once at a time second mutable borrow occurs here

There is a lot of parsing in my code, so I stuck that in a spoiler below.

The relevant code is:

#[derive(Debug)]
struct Card {
    id: u32,
    score: u32,
    copies: u32,
}

fn process(input: &str) -> u32 {
    let mut cards: Vec = parse_cards(input);

    cards.iter_mut().for_each(|card| {
        let copy_from = card.id as usize + 1;
        let copy_to: usize = copy_from + card.score as usize - 1;

        if card.score == 0 || copy_from > cards.len() {
            return;
        }

        for card_copy in cards[copy_from - 1..copy_to].iter() {
            let id = card_copy.id as usize - 1;
            let add = cards[card.id as usize - 1].copies;
            cards[id].copies += add;
        }
    });

    return cards.iter().map(|c| c.copies).sum();
}

Other code:

spoiler
fn main() {
    let input = include_str!("./input1.txt");
    let output = process(input);
    dbg!(output);
}

fn parse_cards(input: &str) -> Vec {
    return input.lines().map(|line| parse_line(line)).collect();
}

fn parse_line(line: &str) -> Card {
    let mut card_split = line.split(':');
    let id = card_split
        .next()
        .unwrap()
        .replace("Card", "")
        .trim()
        .parse::()
        .unwrap();

    let mut number_split = card_split.next().unwrap().trim().split('|');

    let winning: Vec = number_split
        .next()
        .unwrap()
        .trim()
        .split_whitespace()
        .map(|nbr| nbr.trim().parse::().unwrap())
        .collect();
    let drawn: Vec = number_split
        .next()
        .unwrap()
        .trim()
        .split_whitespace()
        .map(|nbr| nbr.trim().parse::().unwrap())
        .collect();

    let mut score = 0;

    for nbr in &drawn {
        if winning.contains(&nbr) {
            score = score + 1;
        }
    }

    return Card {
        id,
        score,
        copies: 1,
    };
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn full_test() {
        let result = process(
            "Card 1: 41 48 83 86 17 | 83 86  6 31 17  9 48 53
        Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
        Card 3:  1 21 53 59 44 | 69 82 63 72 16 21 14  1
        Card 4: 41 92 73 84 69 | 59 84 76 51 58  5 54 83
        Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
        Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11",
        );
        assert!(result != 0);
        assert_eq!(result, 30);
    }
}
3 points
*

Might be best to share a rust playground link https://play.rust-lang.org/

Others can then execute and see the error.

Edit: here’s the link

permalink
report
reply
1 point
*

Thank you. I made the change suggested below to the linked one, but it still fails with the error.

cannot borrow cards as mutable because it is also borrowed as immutable

permalink
report
parent
reply
2 points

Why are you doing

cards.iter_mut().for_each(|card| {

I don’t see that you mutate card anywhere, am I missing something?

permalink
report
reply
1 point
*

No, that’s probably wrong.

I’ve just been trying different combinations of borrowing, but I can’t get it to works.

I’m pretty sure it’s the cards[id].copies += add that is the cause of my issues.

permalink
report
parent
reply
1 point

OK, so I’m thinking…

The error says I can’t combine immutable and mutable in the same function. I guess this makes sense, and that it’s because I’m not allowed to mutate an object while accessing it.

Is this a correct understanding of the error, or is there anything I can do to use this approach?

permalink
report
reply

Rust

!rust@programming.dev

Create post

Welcome to the Rust community! This is a place to discuss about the Rust programming language.

Wormhole

!performance@programming.dev

Credits
  • The icon is a modified version of the official rust logo (changing the colors to a gradient and black background)

Community stats

  • 1

    Monthly active users

  • 398

    Posts

  • 396

    Comments