Two Sum Leetcode Rust Solution?












1















I've been trying to use rust to answer some questions in leetcode. While I feel it hard to deal with linked-list, especially for question Two Sum. How should I deal with the problem of moved value?



This is a piece of code can pass the test.



// Definition for singly-linked list.
// #[derive(PartialEq, Eq, Debug)]
// pub struct ListNode {
// pub val: i32,
// pub next: Option<Box<ListNode>>
// }
//
// impl ListNode {
// #[inline]
// fn new(val: i32) -> Self {
// ListNode {
// next: None,
// val
// }
// }
// }
pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
let mut head1 = l1;
let mut head2 = l2;
let mut res = Some(Box::new(ListNode::new(0)));
let mut tmp = &mut res;
loop {
let node1 = head1.take().unwrap_or(Box::new(ListNode::new(0)));
let node2 = head2.take().unwrap_or(Box::new(ListNode::new(0)));
tmp = match tmp.as_mut(){
Some(_n) => {
let sum = node1.val + node2.val + _n.val;
let carry = sum /10;
_n.val = sum % 10;
if node1.next.is_none() && node2.next.is_none() && carry == 0{
return res;
} else {
_n.next = Some(Box::new(ListNode::new(carry)));
}
&mut _n.next
}
_ => unreachable!(),
};
head1 = node1.next;
head2 = node2.next;
}
}


While it can't pass local compile, having error message



error[E0506]: cannot assign to `tmp` because it is borrowed
--> empty.rs:109:13
|
109 | tmp = match tmp.as_mut(){
| ^ --- borrow of `tmp` occurs here
| _____________|
| |
110 | | Some(_n) => {
111 | | let sum = node1.val + node2.val + _n.val;
112 | | let carry = sum /10;
... |
121 | | _ => unreachable!(),
122 | | };
| |_____________^ assignment to borrowed `tmp` occurs here

error[E0499]: cannot borrow `*tmp` as mutable more than once at a time
--> empty.rs:109:25
|
109 | tmp = match tmp.as_mut(){
| ^^^ mutable borrow starts here in previous iteration of loop
...
126 | }
| - mutable borrow ends here

error[E0505]: cannot move out of `res` because it is borrowed
--> empty.rs:115:28
|
105 | let mut tmp = &mut res;
| --- borrow of `res` occurs here
...
115 | return res;
| ^^^ move out of `res` occurs here


I thought I might understand a little bit since tmp is a mutable reference to res, then res is moved. But how could I keep the head of a linked list while at the meantime, keep adding tails to it?










share|improve this question



























    1















    I've been trying to use rust to answer some questions in leetcode. While I feel it hard to deal with linked-list, especially for question Two Sum. How should I deal with the problem of moved value?



    This is a piece of code can pass the test.



    // Definition for singly-linked list.
    // #[derive(PartialEq, Eq, Debug)]
    // pub struct ListNode {
    // pub val: i32,
    // pub next: Option<Box<ListNode>>
    // }
    //
    // impl ListNode {
    // #[inline]
    // fn new(val: i32) -> Self {
    // ListNode {
    // next: None,
    // val
    // }
    // }
    // }
    pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
    let mut head1 = l1;
    let mut head2 = l2;
    let mut res = Some(Box::new(ListNode::new(0)));
    let mut tmp = &mut res;
    loop {
    let node1 = head1.take().unwrap_or(Box::new(ListNode::new(0)));
    let node2 = head2.take().unwrap_or(Box::new(ListNode::new(0)));
    tmp = match tmp.as_mut(){
    Some(_n) => {
    let sum = node1.val + node2.val + _n.val;
    let carry = sum /10;
    _n.val = sum % 10;
    if node1.next.is_none() && node2.next.is_none() && carry == 0{
    return res;
    } else {
    _n.next = Some(Box::new(ListNode::new(carry)));
    }
    &mut _n.next
    }
    _ => unreachable!(),
    };
    head1 = node1.next;
    head2 = node2.next;
    }
    }


    While it can't pass local compile, having error message



    error[E0506]: cannot assign to `tmp` because it is borrowed
    --> empty.rs:109:13
    |
    109 | tmp = match tmp.as_mut(){
    | ^ --- borrow of `tmp` occurs here
    | _____________|
    | |
    110 | | Some(_n) => {
    111 | | let sum = node1.val + node2.val + _n.val;
    112 | | let carry = sum /10;
    ... |
    121 | | _ => unreachable!(),
    122 | | };
    | |_____________^ assignment to borrowed `tmp` occurs here

    error[E0499]: cannot borrow `*tmp` as mutable more than once at a time
    --> empty.rs:109:25
    |
    109 | tmp = match tmp.as_mut(){
    | ^^^ mutable borrow starts here in previous iteration of loop
    ...
    126 | }
    | - mutable borrow ends here

    error[E0505]: cannot move out of `res` because it is borrowed
    --> empty.rs:115:28
    |
    105 | let mut tmp = &mut res;
    | --- borrow of `res` occurs here
    ...
    115 | return res;
    | ^^^ move out of `res` occurs here


    I thought I might understand a little bit since tmp is a mutable reference to res, then res is moved. But how could I keep the head of a linked list while at the meantime, keep adding tails to it?










    share|improve this question

























      1












      1








      1








      I've been trying to use rust to answer some questions in leetcode. While I feel it hard to deal with linked-list, especially for question Two Sum. How should I deal with the problem of moved value?



      This is a piece of code can pass the test.



      // Definition for singly-linked list.
      // #[derive(PartialEq, Eq, Debug)]
      // pub struct ListNode {
      // pub val: i32,
      // pub next: Option<Box<ListNode>>
      // }
      //
      // impl ListNode {
      // #[inline]
      // fn new(val: i32) -> Self {
      // ListNode {
      // next: None,
      // val
      // }
      // }
      // }
      pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
      let mut head1 = l1;
      let mut head2 = l2;
      let mut res = Some(Box::new(ListNode::new(0)));
      let mut tmp = &mut res;
      loop {
      let node1 = head1.take().unwrap_or(Box::new(ListNode::new(0)));
      let node2 = head2.take().unwrap_or(Box::new(ListNode::new(0)));
      tmp = match tmp.as_mut(){
      Some(_n) => {
      let sum = node1.val + node2.val + _n.val;
      let carry = sum /10;
      _n.val = sum % 10;
      if node1.next.is_none() && node2.next.is_none() && carry == 0{
      return res;
      } else {
      _n.next = Some(Box::new(ListNode::new(carry)));
      }
      &mut _n.next
      }
      _ => unreachable!(),
      };
      head1 = node1.next;
      head2 = node2.next;
      }
      }


      While it can't pass local compile, having error message



      error[E0506]: cannot assign to `tmp` because it is borrowed
      --> empty.rs:109:13
      |
      109 | tmp = match tmp.as_mut(){
      | ^ --- borrow of `tmp` occurs here
      | _____________|
      | |
      110 | | Some(_n) => {
      111 | | let sum = node1.val + node2.val + _n.val;
      112 | | let carry = sum /10;
      ... |
      121 | | _ => unreachable!(),
      122 | | };
      | |_____________^ assignment to borrowed `tmp` occurs here

      error[E0499]: cannot borrow `*tmp` as mutable more than once at a time
      --> empty.rs:109:25
      |
      109 | tmp = match tmp.as_mut(){
      | ^^^ mutable borrow starts here in previous iteration of loop
      ...
      126 | }
      | - mutable borrow ends here

      error[E0505]: cannot move out of `res` because it is borrowed
      --> empty.rs:115:28
      |
      105 | let mut tmp = &mut res;
      | --- borrow of `res` occurs here
      ...
      115 | return res;
      | ^^^ move out of `res` occurs here


      I thought I might understand a little bit since tmp is a mutable reference to res, then res is moved. But how could I keep the head of a linked list while at the meantime, keep adding tails to it?










      share|improve this question














      I've been trying to use rust to answer some questions in leetcode. While I feel it hard to deal with linked-list, especially for question Two Sum. How should I deal with the problem of moved value?



      This is a piece of code can pass the test.



      // Definition for singly-linked list.
      // #[derive(PartialEq, Eq, Debug)]
      // pub struct ListNode {
      // pub val: i32,
      // pub next: Option<Box<ListNode>>
      // }
      //
      // impl ListNode {
      // #[inline]
      // fn new(val: i32) -> Self {
      // ListNode {
      // next: None,
      // val
      // }
      // }
      // }
      pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
      let mut head1 = l1;
      let mut head2 = l2;
      let mut res = Some(Box::new(ListNode::new(0)));
      let mut tmp = &mut res;
      loop {
      let node1 = head1.take().unwrap_or(Box::new(ListNode::new(0)));
      let node2 = head2.take().unwrap_or(Box::new(ListNode::new(0)));
      tmp = match tmp.as_mut(){
      Some(_n) => {
      let sum = node1.val + node2.val + _n.val;
      let carry = sum /10;
      _n.val = sum % 10;
      if node1.next.is_none() && node2.next.is_none() && carry == 0{
      return res;
      } else {
      _n.next = Some(Box::new(ListNode::new(carry)));
      }
      &mut _n.next
      }
      _ => unreachable!(),
      };
      head1 = node1.next;
      head2 = node2.next;
      }
      }


      While it can't pass local compile, having error message



      error[E0506]: cannot assign to `tmp` because it is borrowed
      --> empty.rs:109:13
      |
      109 | tmp = match tmp.as_mut(){
      | ^ --- borrow of `tmp` occurs here
      | _____________|
      | |
      110 | | Some(_n) => {
      111 | | let sum = node1.val + node2.val + _n.val;
      112 | | let carry = sum /10;
      ... |
      121 | | _ => unreachable!(),
      122 | | };
      | |_____________^ assignment to borrowed `tmp` occurs here

      error[E0499]: cannot borrow `*tmp` as mutable more than once at a time
      --> empty.rs:109:25
      |
      109 | tmp = match tmp.as_mut(){
      | ^^^ mutable borrow starts here in previous iteration of loop
      ...
      126 | }
      | - mutable borrow ends here

      error[E0505]: cannot move out of `res` because it is borrowed
      --> empty.rs:115:28
      |
      105 | let mut tmp = &mut res;
      | --- borrow of `res` occurs here
      ...
      115 | return res;
      | ^^^ move out of `res` occurs here


      I thought I might understand a little bit since tmp is a mutable reference to res, then res is moved. But how could I keep the head of a linked list while at the meantime, keep adding tails to it?







      linked-list rust






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 3 at 1:18









      burytheupsidedownburytheupsidedown

      112




      112
























          1 Answer
          1






          active

          oldest

          votes


















          0
















          Your code compiles as written in stable Rust 2018 (or in nightly Rust 2015 with #![feature(nll)]).



          You can make it compile in stable Rust 2015 with just a few tweaks:



          pub fn add_two_numbers(
          l1: Option<Box<ListNode>>,
          l2: Option<Box<ListNode>>,
          ) -> Option<Box<ListNode>> {
          let mut head1 = l1;
          let mut head2 = l2;
          let mut res = Some(Box::new(ListNode::new(0)));
          // Add this block to limit the scope of tmp.
          {
          let mut tmp = &mut res;
          loop {
          let node1 = head1.take().unwrap_or(Box::new(ListNode::new(0)));
          let node2 = head2.take().unwrap_or(Box::new(ListNode::new(0)));
          // Add braces around tmp to force it to be moved instead of reborrowed.
          tmp = match { tmp }.as_mut() {
          Some(_n) => {
          let sum = node1.val + node2.val + _n.val;
          let carry = sum / 10;
          _n.val = sum % 10;
          if node1.next.is_none() && node2.next.is_none() && carry == 0 {
          // Move the return statement outside the block.
          break;
          } else {
          _n.next = Some(Box::new(ListNode::new(carry)));
          }
          &mut _n.next
          }
          _ => unreachable!(),
          };
          head1 = node1.next;
          head2 = node2.next;
          }
          }
          return res;
          }


          It probably makes sense why return res needs to be moved outside the scope of tmp. The { tmp } thing is a bit more confusing: it tells the compiler to move tmp instead of reborrowing it (see this explanation).






          share|improve this answer


























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54015194%2ftwo-sum-leetcode-rust-solution%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0
















            Your code compiles as written in stable Rust 2018 (or in nightly Rust 2015 with #![feature(nll)]).



            You can make it compile in stable Rust 2015 with just a few tweaks:



            pub fn add_two_numbers(
            l1: Option<Box<ListNode>>,
            l2: Option<Box<ListNode>>,
            ) -> Option<Box<ListNode>> {
            let mut head1 = l1;
            let mut head2 = l2;
            let mut res = Some(Box::new(ListNode::new(0)));
            // Add this block to limit the scope of tmp.
            {
            let mut tmp = &mut res;
            loop {
            let node1 = head1.take().unwrap_or(Box::new(ListNode::new(0)));
            let node2 = head2.take().unwrap_or(Box::new(ListNode::new(0)));
            // Add braces around tmp to force it to be moved instead of reborrowed.
            tmp = match { tmp }.as_mut() {
            Some(_n) => {
            let sum = node1.val + node2.val + _n.val;
            let carry = sum / 10;
            _n.val = sum % 10;
            if node1.next.is_none() && node2.next.is_none() && carry == 0 {
            // Move the return statement outside the block.
            break;
            } else {
            _n.next = Some(Box::new(ListNode::new(carry)));
            }
            &mut _n.next
            }
            _ => unreachable!(),
            };
            head1 = node1.next;
            head2 = node2.next;
            }
            }
            return res;
            }


            It probably makes sense why return res needs to be moved outside the scope of tmp. The { tmp } thing is a bit more confusing: it tells the compiler to move tmp instead of reborrowing it (see this explanation).






            share|improve this answer






























              0
















              Your code compiles as written in stable Rust 2018 (or in nightly Rust 2015 with #![feature(nll)]).



              You can make it compile in stable Rust 2015 with just a few tweaks:



              pub fn add_two_numbers(
              l1: Option<Box<ListNode>>,
              l2: Option<Box<ListNode>>,
              ) -> Option<Box<ListNode>> {
              let mut head1 = l1;
              let mut head2 = l2;
              let mut res = Some(Box::new(ListNode::new(0)));
              // Add this block to limit the scope of tmp.
              {
              let mut tmp = &mut res;
              loop {
              let node1 = head1.take().unwrap_or(Box::new(ListNode::new(0)));
              let node2 = head2.take().unwrap_or(Box::new(ListNode::new(0)));
              // Add braces around tmp to force it to be moved instead of reborrowed.
              tmp = match { tmp }.as_mut() {
              Some(_n) => {
              let sum = node1.val + node2.val + _n.val;
              let carry = sum / 10;
              _n.val = sum % 10;
              if node1.next.is_none() && node2.next.is_none() && carry == 0 {
              // Move the return statement outside the block.
              break;
              } else {
              _n.next = Some(Box::new(ListNode::new(carry)));
              }
              &mut _n.next
              }
              _ => unreachable!(),
              };
              head1 = node1.next;
              head2 = node2.next;
              }
              }
              return res;
              }


              It probably makes sense why return res needs to be moved outside the scope of tmp. The { tmp } thing is a bit more confusing: it tells the compiler to move tmp instead of reborrowing it (see this explanation).






              share|improve this answer




























                0












                0








                0









                Your code compiles as written in stable Rust 2018 (or in nightly Rust 2015 with #![feature(nll)]).



                You can make it compile in stable Rust 2015 with just a few tweaks:



                pub fn add_two_numbers(
                l1: Option<Box<ListNode>>,
                l2: Option<Box<ListNode>>,
                ) -> Option<Box<ListNode>> {
                let mut head1 = l1;
                let mut head2 = l2;
                let mut res = Some(Box::new(ListNode::new(0)));
                // Add this block to limit the scope of tmp.
                {
                let mut tmp = &mut res;
                loop {
                let node1 = head1.take().unwrap_or(Box::new(ListNode::new(0)));
                let node2 = head2.take().unwrap_or(Box::new(ListNode::new(0)));
                // Add braces around tmp to force it to be moved instead of reborrowed.
                tmp = match { tmp }.as_mut() {
                Some(_n) => {
                let sum = node1.val + node2.val + _n.val;
                let carry = sum / 10;
                _n.val = sum % 10;
                if node1.next.is_none() && node2.next.is_none() && carry == 0 {
                // Move the return statement outside the block.
                break;
                } else {
                _n.next = Some(Box::new(ListNode::new(carry)));
                }
                &mut _n.next
                }
                _ => unreachable!(),
                };
                head1 = node1.next;
                head2 = node2.next;
                }
                }
                return res;
                }


                It probably makes sense why return res needs to be moved outside the scope of tmp. The { tmp } thing is a bit more confusing: it tells the compiler to move tmp instead of reborrowing it (see this explanation).






                share|improve this answer

















                Your code compiles as written in stable Rust 2018 (or in nightly Rust 2015 with #![feature(nll)]).



                You can make it compile in stable Rust 2015 with just a few tweaks:



                pub fn add_two_numbers(
                l1: Option<Box<ListNode>>,
                l2: Option<Box<ListNode>>,
                ) -> Option<Box<ListNode>> {
                let mut head1 = l1;
                let mut head2 = l2;
                let mut res = Some(Box::new(ListNode::new(0)));
                // Add this block to limit the scope of tmp.
                {
                let mut tmp = &mut res;
                loop {
                let node1 = head1.take().unwrap_or(Box::new(ListNode::new(0)));
                let node2 = head2.take().unwrap_or(Box::new(ListNode::new(0)));
                // Add braces around tmp to force it to be moved instead of reborrowed.
                tmp = match { tmp }.as_mut() {
                Some(_n) => {
                let sum = node1.val + node2.val + _n.val;
                let carry = sum / 10;
                _n.val = sum % 10;
                if node1.next.is_none() && node2.next.is_none() && carry == 0 {
                // Move the return statement outside the block.
                break;
                } else {
                _n.next = Some(Box::new(ListNode::new(carry)));
                }
                &mut _n.next
                }
                _ => unreachable!(),
                };
                head1 = node1.next;
                head2 = node2.next;
                }
                }
                return res;
                }


                It probably makes sense why return res needs to be moved outside the scope of tmp. The { tmp } thing is a bit more confusing: it tells the compiler to move tmp instead of reborrowing it (see this explanation).







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jan 4 at 10:38

























                answered Jan 3 at 4:14









                Anders KaseorgAnders Kaseorg

                1,790918




                1,790918
































                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54015194%2ftwo-sum-leetcode-rust-solution%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    MongoDB - Not Authorized To Execute Command

                    How to fix TextFormField cause rebuild widget in Flutter

                    Npm cannot find a required file even through it is in the searched directory